diff options
231 files changed, 16557 insertions, 13270 deletions
diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index b79bb5d161..be114bcf68 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -21,10 +21,12 @@ Mozilla Corporation Turbulenz Klarälvdalens Datakonsult AB Microsoft Open Technologies, Inc. +NVIDIA Corporation Jacek Caban Mark Callow Ginn Chen +Tibor den Ouden James Hauxwell Sam Hocevar Pierre Leveille diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index 0cae10a0f6..94d009f2b3 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -78,7 +78,12 @@ Turbulenz Ulrik Persson (ddefrostt) Mark Banner (standard8mbp) David Kilzer +Jacek Caban +Tibor den Ouden Microsoft Open Technologies, Inc. Cooper Partin Austin Kinross + +NVIDIA Corporation + Olli Etuaho diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h index ab2f0cdfbe..12590a0e20 100644 --- a/src/3rdparty/angle/include/EGL/egl.h +++ b/src/3rdparty/angle/include/EGL/egl.h @@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); #ifndef EGL_VERSION_1_5 #define EGL_VERSION_1_5 1 typedef void *EGLSync; -typedef khronos_intptr_t EGLAttrib; +typedef intptr_t EGLAttrib; typedef khronos_utime_nanoseconds_t EGLTime; #define EGL_CONTEXT_MAJOR_VERSION 0x3098 #define EGL_CONTEXT_MINOR_VERSION 0x30FB diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h index 989359b026..0cc5eec293 100644 --- a/src/3rdparty/angle/include/EGL/eglext.h +++ b/src/3rdparty/angle/include/EGL/eglext.h @@ -59,7 +59,7 @@ extern "C" { #ifndef EGL_KHR_cl_event2 #define EGL_KHR_cl_event2 1 typedef void *EGLSyncKHR; -typedef khronos_intptr_t EGLAttribKHR; +typedef intptr_t EGLAttribKHR; typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); @@ -442,20 +442,22 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #define EGL_ANGLE_platform_angle 1 #define EGL_PLATFORM_ANGLE_ANGLE 0x3201 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 #endif /* EGL_ANGLE_platform_angle */ #ifndef EGL_ANGLE_platform_angle_d3d #define EGL_ANGLE_platform_angle_d3d 1 -#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 #endif /* EGL_ANGLE_platform_angle_d3d */ #ifndef EGL_ANGLE_platform_angle_opengl #define EGL_ANGLE_platform_angle_opengl 1 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A #endif /* EGL_ANGLE_platform_angle_opengl */ #ifndef EGL_ARM_pixmap_multisample_discard diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h index ea9f5778ee..2eb3674a0b 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h @@ -67,23 +67,22 @@ * implementations. */ -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ - -struct IUnknown; - -typedef IUnknown *EGLNativeDisplayType; -typedef void *EGLNativePixmapType; -typedef IUnknown *EGLNativeWindowType; - -#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include <windows.h> -typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ +#include <inspectable.h> +typedef IInspectable* EGLNativeDisplayType; +typedef IInspectable* EGLNativeWindowType; +#else +typedef HDC EGLNativeDisplayType; typedef HWND EGLNativeWindowType; +#endif #elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index b7989f5f7e..647fed6a02 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -27,6 +27,10 @@ #include "KHR/khrplatform.h" +#include <map> +#include <string> +#include <vector> + // // This is the platform independent interface between an OGL driver // and the shading language compiler. @@ -42,18 +46,17 @@ typedef unsigned int GLenum; // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h #include "ShaderVars.h" -#ifdef __cplusplus -extern "C" { -#endif - // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 130 +#define ANGLE_SH_VERSION 132 typedef enum { SH_GLES2_SPEC = 0x8B40, SH_WEBGL_SPEC = 0x8B41, + SH_GLES3_SPEC = 0x8B86, + SH_WEBGL2_SPEC = 0x8B87, + // The CSS Shaders spec is a subset of the WebGL spec. // // In both CSS vertex and fragment shaders, ANGLE: @@ -85,31 +88,6 @@ typedef enum { SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; -typedef enum { - SH_PRECISION_HIGHP = 0x5001, - SH_PRECISION_MEDIUMP = 0x5002, - SH_PRECISION_LOWP = 0x5003, - SH_PRECISION_UNDEFINED = 0 -} ShPrecisionType; - -typedef enum { - SH_INFO_LOG_LENGTH = 0x8B84, - SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH - SH_ACTIVE_UNIFORMS = 0x8B86, - SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, - SH_ACTIVE_ATTRIBUTES = 0x8B89, - SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, - SH_VARYINGS = 0x8BBB, - SH_VARYING_MAX_LENGTH = 0x8BBC, - SH_MAPPED_NAME_MAX_LENGTH = 0x6000, - SH_NAME_MAX_LENGTH = 0x6001, - SH_HASHED_NAME_MAX_LENGTH = 0x6002, - SH_HASHED_NAMES_COUNT = 0x6003, - SH_SHADER_VERSION = 0x6004, - SH_RESOURCES_STRING_LENGTH = 0x6005, - SH_OUTPUT_TYPE = 0x6006 -} ShShaderInfo; - // Compile options. typedef enum { SH_VALIDATE = 0, @@ -208,14 +186,14 @@ typedef enum { // // Driver must call this first, once, before doing any other // compiler operations. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // -COMPILER_EXPORT int ShInitialize(); +COMPILER_EXPORT bool ShInitialize(); // // Driver should call this at shutdown. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // -COMPILER_EXPORT int ShFinalize(); +COMPILER_EXPORT bool ShFinalize(); // The 64 bits hash function. The first parameter is the input string; the // second parameter is the string length. @@ -246,6 +224,12 @@ typedef struct int EXT_frag_depth; int EXT_shader_texture_lod; + // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives + // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate + // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers + // function. This applies to Tegra K1 devices. + int NV_draw_buffers; + // Set to 1 if highp precision is supported in the fragment language. // Default is 0. int FragmentPrecisionHigh; @@ -274,8 +258,10 @@ typedef struct // // Initialize built-in resources with minimum expected values. +// Parameters: +// resources: The object to initialize. Will be comparable with memcmp. // -COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); +COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources); // // ShHandle held by but opaque to the driver. It is allocated, @@ -284,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); // // If handle creation fails, 0 will be returned. // -typedef void* ShHandle; +typedef void *ShHandle; // -// Returns the a concatenated list of the items in ShBuiltInResources as a string. +// Returns the a concatenated list of the items in ShBuiltInResources as a +// null-terminated string. // This function must be updated whenever ShBuiltInResources is changed. // Parameters: // handle: Specifies the handle of the compiler to be used. -// outStringLen: Specifies the size of the buffer, in number of characters. The size -// of the buffer required to store the resources string can be obtained -// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH. -// outStr: Returns a null-terminated string representing all the built-in resources. -COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr); +COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle); // // Driver calls these to create and destroy compiler objects. @@ -313,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, - const ShBuiltInResources* resources); + const ShBuiltInResources *resources); COMPILER_EXPORT void ShDestruct(ShHandle handle); // // Compiles the given shader source. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // Parameters: // handle: Specifies the handle of compiler to be used. // shaderStrings: Specifies an array of pointers to null-terminated strings @@ -340,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle); // SH_VARIABLES: Extracts attributes, uniforms, and varyings. // Can be queried by calling ShGetVariableInfo(). // -COMPILER_EXPORT int ShCompile( +COMPILER_EXPORT bool ShCompile( const ShHandle handle, - const char* const shaderStrings[], + const char * const shaderStrings[], size_t numStrings, - int compileOptions - ); + int compileOptions); -// Returns a parameter from a compiled shader. -// Parameters: -// handle: Specifies the compiler -// pname: Specifies the parameter to query. -// The following parameters are defined: -// SH_INFO_LOG_LENGTH: the number of characters in the information log -// including the null termination character. -// SH_OBJECT_CODE_LENGTH: the number of characters in the object code -// including the null termination character. -// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables. -// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute -// variable name including the null -// termination character. -// SH_ACTIVE_UNIFORMS: the number of active uniform variables. -// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform -// variable name including the null -// termination character. -// SH_VARYINGS: the number of varying variables. -// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name -// including the null termination character. -// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including -// the null termination character. -// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the -// null termination character. -// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the -// null termination character. -// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile. -// SH_SHADER_VERSION: the version of the shader language -// SH_OUTPUT_TYPE: the currently set language output type -// -// params: Requested parameter -COMPILER_EXPORT void ShGetInfo(const ShHandle handle, - ShShaderInfo pname, - size_t* params); +// Return the version of the shader language. +COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle); -// Returns nul-terminated information log for a compiled shader. +// Return the currently set language output type. +COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType( + const ShHandle handle); + +// Returns null-terminated information log for a compiled shader. // Parameters: // handle: Specifies the compiler -// infoLog: Specifies an array of characters that is used to return -// the information log. It is assumed that infoLog has enough memory -// to accomodate the information log. The size of the buffer required -// to store the returned information log can be obtained by calling -// ShGetInfo with SH_INFO_LOG_LENGTH. -COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog); +COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle); // Returns null-terminated object code for a compiled shader. // Parameters: // handle: Specifies the compiler -// infoLog: Specifies an array of characters that is used to return -// the object code. It is assumed that infoLog has enough memory to -// accomodate the object code. The size of the buffer required to -// store the returned object code can be obtained by calling -// ShGetInfo with SH_OBJECT_CODE_LENGTH. -COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode); - -// Returns information about a shader variable. -// Parameters: -// handle: Specifies the compiler -// variableType: Specifies the variable type; options include -// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS. -// index: Specifies the index of the variable to be queried. -// length: Returns the number of characters actually written in the string -// indicated by name (excluding the null terminator) if a value other -// than NULL is passed. -// size: Returns the size of the variable. -// type: Returns the data type of the variable. -// precision: Returns the precision of the variable. -// staticUse: Returns 1 if the variable is accessed in a statement after -// pre-processing, whether or not run-time flow of control will -// cause that statement to be executed. -// Returns 0 otherwise. -// name: Returns a null terminated string containing the name of the -// variable. It is assumed that name has enough memory to accormodate -// the variable name. The size of the buffer required to store the -// variable name can be obtained by calling ShGetInfo with -// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH, -// SH_VARYING_MAX_LENGTH. -// mappedName: Returns a null terminated string containing the mapped name of -// the variable, It is assumed that mappedName has enough memory -// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the -// mapped name. If the name is not mapped, then name and mappedName -// are the same. -COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle, - ShShaderInfo variableType, - int index, - size_t* length, - int* size, - sh::GLenum* type, - ShPrecisionType* precision, - int* staticUse, - char* name, - char* mappedName); - -// Returns information about a name hashing entry from the latest compile. +COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle); + +// Returns a (original_name, hash) map containing all the user defined +// names in the shader, including variable names, function names, struct +// names, and struct field names. // Parameters: // handle: Specifies the compiler -// index: Specifies the index of the name hashing entry to be queried. -// name: Returns a null terminated string containing the user defined name. -// It is assumed that name has enough memory to accomodate the name. -// The size of the buffer required to store the user defined name can -// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH. -// hashedName: Returns a null terminated string containing the hashed name of -// the uniform variable, It is assumed that hashedName has enough -// memory to accomodate the name. The size of the buffer required -// to store the name can be obtained by calling ShGetInfo with -// SH_HASHED_NAME_MAX_LENGTH. -COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, - int index, - char* name, - char* hashedName); +COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap( + const ShHandle handle); // Shader variable inspection. // Returns a pointer to a list of variables of the designated type. @@ -476,17 +372,17 @@ typedef struct int size; } ShVariableInfo; -// Returns 1 if the passed in variables pack in maxVectors following +// Returns true if the passed in variables pack in maxVectors following // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. -// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS +// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS // flag above. // Parameters: // maxVectors: the available rows of registers. // varInfoArray: an array of variable info (types and sizes). // varInfoArraySize: the size of the variable array. -COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( +COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits( int maxVectors, - ShVariableInfo* varInfoArray, + ShVariableInfo *varInfoArray, size_t varInfoArraySize); // Gives the compiler-assigned register for an interface block. @@ -497,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( // interfaceBlockName: Specifies the interface block // indexOut: output variable that stores the assigned register COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, - const char *interfaceBlockName, + const std::string &interfaceBlockName, unsigned int *indexOut); // Gives the compiler-assigned register for uniforms in the default @@ -509,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, // interfaceBlockName: Specifies the uniform // indexOut: output variable that stores the assigned register COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, - const char *uniformName, + const std::string &uniformName, unsigned int *indexOut); -#ifdef __cplusplus -} -#endif - #endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h index 9c38647dda..da21c3e76e 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h @@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable unsigned int elementCount() const { return std::max(1u, arraySize); } bool isStruct() const { return !fields.empty(); } + // All of the shader's variables are described using nested data + // structures. This is needed in order to disambiguate similar looking + // types, such as two structs containing the same fields, but in + // different orders. "findInfoByMappedName" provides an easy query for + // users to dive into the data structure and fetch the unique variable + // instance corresponding to a dereferencing chain of the top-level + // variable. + // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable + // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]' + // in |originalName|, based on the assumption that |this| defines 'a'. + // If no match is found, return false. + bool findInfoByMappedName(const std::string &mappedFullName, + const ShaderVariable **leafVar, + std::string* originalFullName) const; + GLenum type; GLenum precision; std::string name; @@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable bool staticUse; std::vector<ShaderVariable> fields; std::string structName; + + protected: + bool isSameVariableAtLinkTime(const ShaderVariable &other, + bool matchPrecision) const; + + bool operator==(const ShaderVariable &other) const; + bool operator!=(const ShaderVariable &other) const + { + return !operator==(other); + } }; struct COMPILER_EXPORT Uniform : public ShaderVariable @@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable ~Uniform(); Uniform(const Uniform &other); Uniform &operator=(const Uniform &other); + bool operator==(const Uniform &other) const; + bool operator!=(const Uniform &other) const + { + return !operator==(other); + } + + // Decide whether two uniforms are the same at shader link time, + // assuming one from vertex shader and the other from fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.5. + bool isSameUniformAtLinkTime(const Uniform &other) const; }; struct COMPILER_EXPORT Attribute : public ShaderVariable @@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable ~Attribute(); Attribute(const Attribute &other); Attribute &operator=(const Attribute &other); + bool operator==(const Attribute &other) const; + bool operator!=(const Attribute &other) const + { + return !operator==(other); + } int location; }; @@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable ~InterfaceBlockField(); InterfaceBlockField(const InterfaceBlockField &other); InterfaceBlockField &operator=(const InterfaceBlockField &other); + bool operator==(const InterfaceBlockField &other) const; + bool operator!=(const InterfaceBlockField &other) const + { + return !operator==(other); + } + + // Decide whether two InterfaceBlock fields are the same at shader + // link time, assuming one from vertex shader and the other from + // fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.7. + bool isSameInterfaceBlockFieldAtLinkTime( + const InterfaceBlockField &other) const; bool isRowMajorLayout; }; @@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable { Varying(); ~Varying(); - Varying(const Varying &other); + Varying(const Varying &otherg); Varying &operator=(const Varying &other); + bool operator==(const Varying &other) const; + bool operator!=(const Varying &other) const + { + return !operator==(other); + } + + // Decide whether two varyings are the same at shader link time, + // assuming one from vertex shader and the other from fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.9. + bool isSameVaryingAtLinkTime(const Varying &other) const; InterpolationType interpolation; bool isInvariant; diff --git a/src/3rdparty/angle/include/angle_windowsstore.h b/src/3rdparty/angle/include/angle_windowsstore.h new file mode 100644 index 0000000000..53ec93e037 --- /dev/null +++ b/src/3rdparty/angle/include/angle_windowsstore.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// angle_windowsstore.h: + +#ifndef ANGLE_WINDOWSSTORE_H_ +#define ANGLE_WINDOWSSTORE_H_ + +// The following properties can be set on the CoreApplication to support additional +// ANGLE configuration options. +// +// The Visual Studio sample templates provided with this version of ANGLE have examples +// of how to set these property values. + +// +// Property: EGLNativeWindowTypeProperty +// Type: IInspectable +// Description: Set this property to specify the window type to use for creating a surface. +// If this property is missing, surface creation will fail. +// +const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty"; + +// +// Property: EGLRenderSurfaceSizeProperty +// Type: Size +// Description: Set this property to specify a preferred size in pixels of the render surface. +// The render surface size width and height must be greater than 0. +// If this property is set, then the render surface size is fixed. +// If this property is missing, a default behavior will be provided. +// The default behavior uses the window size if a CoreWindow is specified or +// the size of the SwapChainPanel control if one is specified. +// +const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty"; + +#endif // ANGLE_WINDOWSSTORE_H_ diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h index a2e761b131..08fc893c25 100644 --- a/src/3rdparty/angle/src/commit.h +++ b/src/3rdparty/angle/src/commit.h @@ -7,6 +7,6 @@ // This is a default commit hash header, when git is not available. // -#define ANGLE_COMMIT_HASH "abce76206141" +#define ANGLE_COMMIT_HASH "30d6c255d238" #define ANGLE_COMMIT_HASH_SIZE 12 -#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000" +#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000" diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h new file mode 100644 index 0000000000..9e93aeacde --- /dev/null +++ b/src/3rdparty/angle/src/common/NativeWindow.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// NativeWindow.h: Defines NativeWindow, a class for managing and +// performing operations on an EGLNativeWindowType. +// It is used for HWND (Desktop Windows) and IInspectable objects +//(Windows Store Applications). + +#ifndef COMMON_NATIVEWINDOW_H_ +#define COMMON_NATIVEWINDOW_H_ + +#include <EGL/eglplatform.h> +#include "common/debug.h" +#include "common/platform.h" + +// DXGISwapChain and DXGIFactory are typedef'd to specific required +// types. The HWND NativeWindow implementation requires IDXGISwapChain +// and IDXGIFactory and the Windows Store NativeWindow +// implementation requires IDXGISwapChain1 and IDXGIFactory2. +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef IDXGISwapChain1 DXGISwapChain; +typedef IDXGIFactory2 DXGIFactory; + +#include <wrl.h> +#include <wrl/wrappers/corewrappers.h> +#include <windows.applicationmodel.core.h> +#include <memory> + +namespace rx +{ +class InspectableNativeWindow; +} + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +#else +typedef IDXGISwapChain DXGISwapChain; +typedef IDXGIFactory DXGIFactory; +#endif + +namespace rx +{ + +class NativeWindow +{ +public: + explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); + + bool initialize(); + bool getClientRect(LPRECT rect); + bool isIconic(); + + HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, + DXGI_FORMAT format, UINT width, UINT height, + DXGISwapChain** swapChain); + + inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; } + + private: + EGLNativeWindowType mWindow; + EGLNativeDisplayType mDisplay; + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + std::shared_ptr<InspectableNativeWindow> mImpl; +#endif + +}; + +bool IsValidEGLNativeWindowType(EGLNativeWindowType window); +} + +#endif // COMMON_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp index 2673abf30a..c1367c460a 100644 --- a/src/3rdparty/angle/src/common/angleutils.cpp +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -5,26 +5,33 @@ // #include "common/angleutils.h" - +#include "debug.h" +#include <stdio.h> #include <vector> -std::string FormatString(const char *fmt, va_list vararg) +size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer) { - static std::vector<char> buffer(512); - // Attempt to just print to the current buffer - int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg); - if (len < 0 || static_cast<size_t>(len) >= buffer.size()) + int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg); + if (len < 0 || static_cast<size_t>(len) >= outBuffer.size()) { // Buffer was not large enough, calculate the required size and resize the buffer len = vsnprintf(NULL, 0, fmt, vararg); - buffer.resize(len + 1); + outBuffer.resize(len + 1); // Print again - vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg); } + ASSERT(len >= 0); + return static_cast<size_t>(len); +} + +std::string FormatString(const char *fmt, va_list vararg) +{ + static std::vector<char> buffer(512); - return std::string(buffer.data(), len); + size_t len = FormatStringIntoVector(fmt, vararg, buffer); + return std::string(&buffer[0], len); } std::string FormatString(const char *fmt, ...) diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index ddbbd5f501..b343ece5bc 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -17,6 +17,7 @@ #include <set> #include <sstream> #include <cstdarg> +#include <vector> // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class @@ -95,6 +96,13 @@ inline void StructZero(T *obj) memset(obj, 0, sizeof(T)); } +template <typename T> +inline bool IsMaskFlagSet(T mask, T flag) +{ + // Handles multibit flags as well + return (mask & flag) == flag; +} + inline const char* MakeStaticString(const std::string &str) { static std::set<std::string> strings; @@ -132,9 +140,12 @@ inline std::string Str(int i) return strstr.str(); } +size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer); + std::string FormatString(const char *fmt, va_list vararg); std::string FormatString(const char *fmt, ...); +// snprintf is not defined with MSVC prior to to msvc14 #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index dcad327564..5f55ff1e39 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -17,41 +17,211 @@ namespace gl { -#if defined(ANGLE_ENABLE_PERF) -typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR); -#else -typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); -#endif +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) +// Wraps the D3D9/D3D11 debug annotation functions. +class DebugAnnotationWrapper +{ + public: + DebugAnnotationWrapper() { }; + virtual ~DebugAnnotationWrapper() { }; + virtual void beginEvent(const std::wstring &eventName) = 0; + virtual void endEvent() = 0; + virtual void setMarker(const std::wstring &markerName) = 0; + virtual bool getStatus() = 0; +}; -static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) +#if defined(ANGLE_ENABLE_D3D9) +class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper { -#if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE) - std::string formattedMessage = FormatString(format, vararg); + public: + void beginEvent(const std::wstring &eventName) + { + D3DPERF_BeginEvent(0, eventName.c_str()); + } + + void endEvent() + { + D3DPERF_EndEvent(); + } + + void setMarker(const std::wstring &markerName) + { + D3DPERF_SetMarker(0, markerName.c_str()); + } + + bool getStatus() + { + return !!D3DPERF_GetStatus(); + } +}; +#endif // ANGLE_ENABLE_D3D9 + +#if defined(ANGLE_ENABLE_D3D11) +class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper +{ + public: + + D3D11DebugAnnotationWrapper() + : mInitialized(false), + mD3d11Module(NULL), + mUserDefinedAnnotation(NULL) + { + // D3D11 devices can't be created during DllMain. + // We defer device creation until the object is actually used. + } + + ~D3D11DebugAnnotationWrapper() + { + if (mInitialized) + { + SafeRelease(mUserDefinedAnnotation); + FreeLibrary(mD3d11Module); + } + } + + virtual void beginEvent(const std::wstring &eventName) + { + initializeDevice(); + + mUserDefinedAnnotation->BeginEvent(eventName.c_str()); + } + + virtual void endEvent() + { + initializeDevice(); + + mUserDefinedAnnotation->EndEvent(); + } + + virtual void setMarker(const std::wstring &markerName) + { + initializeDevice(); + + mUserDefinedAnnotation->SetMarker(markerName.c_str()); + } + + virtual bool getStatus() + { + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. + +#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) + // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // This should only be called in DEBUG mode. + // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. + IDXGraphicsAnalysis* graphicsAnalysis; + DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); + bool underCapture = (graphicsAnalysis != NULL); + SafeRelease(graphicsAnalysis); + return underCapture; #endif -#if defined(ANGLE_ENABLE_PERF) - if (perfActive()) + // Otherwise, we have to return true here. + return true; + } + + protected: + + void initializeDevice() { - // The perf function only accepts wide strings, widen the ascii message - static std::wstring wideMessage; - if (wideMessage.capacity() < formattedMessage.length()) + if (!mInitialized) { - wideMessage.reserve(formattedMessage.size()); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + ASSERT(mD3d11Module); + + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + ASSERT(D3D11CreateDevice != NULL); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + + ID3D11Device* device = NULL; + ID3D11DeviceContext* context = NULL; + + HRESULT hr = E_FAIL; + + // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context); + ASSERT(SUCCEEDED(hr)); + + hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation)); + ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL); + + SafeRelease(device); + SafeRelease(context); + + mInitialized = true; } + } + + bool mInitialized; + HMODULE mD3d11Module; + ID3DUserDefinedAnnotation* mUserDefinedAnnotation; +}; +#endif // ANGLE_ENABLE_D3D11 + +static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL; + +void InitializeDebugAnnotations() +{ +#if defined(ANGLE_ENABLE_D3D9) + g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper(); +#elif defined(ANGLE_ENABLE_D3D11) + // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer. + // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations. + // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext. + // This doesn't have to be the same DeviceContext that the renderer uses, though. + g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper(); +#endif +} + +void UninitializeDebugAnnotations() +{ + if (g_DebugAnnotationWrapper != NULL) + { + SafeDelete(g_DebugAnnotationWrapper); + } +} + +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS - wideMessage.assign(formattedMessage.begin(), formattedMessage.end()); +enum DebugTraceOutputType +{ + DebugTraceOutputTypeNone, + DebugTraceOutputTypeSetMarker, + DebugTraceOutputTypeBeginEvent +}; + +static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg) +{ +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + static std::vector<char> buffer(512); - perfFunc(0, wideMessage.c_str()); + if (perfActive()) + { + size_t len = FormatStringIntoVector(format, vararg, buffer); + std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len); + + switch (outputType) + { + case DebugTraceOutputTypeNone: + break; + case DebugTraceOutputTypeBeginEvent: + g_DebugAnnotationWrapper->beginEvent(formattedWideMessage); + break; + case DebugTraceOutputTypeSetMarker: + g_DebugAnnotationWrapper->setMarker(formattedWideMessage); + break; + } } -#endif // ANGLE_ENABLE_PERF +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS -#if defined(ANGLE_ENABLE_TRACE) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) #if defined(NDEBUG) - if (traceFileDebugOnly) + if (traceInDebugOnly) { return; } #endif // NDEBUG + std::string formattedMessage = FormatString(format, vararg); static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) @@ -60,25 +230,29 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c file.flush(); } -#endif // ANGLE_ENABLE_TRACE +#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) + OutputDebugStringA(formattedMessage.c_str()); +#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER + +#endif // ANGLE_ENABLE_DEBUG_TRACE } -void trace(bool traceFileDebugOnly, const char *format, ...) +void trace(bool traceInDebugOnly, const char *format, ...) { va_list vararg; va_start(vararg, format); -#if defined(ANGLE_ENABLE_PERF) - output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg); +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg); #else - output(traceFileDebugOnly, NULL, format, vararg); + output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg); #endif va_end(vararg); } bool perfActive() { -#if defined(ANGLE_ENABLE_PERF) - static bool active = D3DPERF_GetStatus() != 0; +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + static bool active = g_DebugAnnotationWrapper->getStatus(); return active; #else return false; @@ -87,26 +261,28 @@ bool perfActive() ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { -#if defined(ANGLE_ENABLE_PERF) -#if !defined(ANGLE_ENABLE_TRACE) +#if !defined(ANGLE_ENABLE_DEBUG_TRACE) if (!perfActive()) { return; } -#endif // !ANGLE_ENABLE_TRACE +#endif // !ANGLE_ENABLE_DEBUG_TRACE va_list vararg; va_start(vararg, format); - output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg); +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + output(true, DebugTraceOutputTypeBeginEvent, format, vararg); +#else + output(true, DebugTraceOutputTypeNone, format, vararg); +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS va_end(vararg); -#endif // ANGLE_ENABLE_PERF } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) if (perfActive()) { - D3DPERF_EndEvent(); + g_DebugAnnotationWrapper->endEvent(); } #endif } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index bf2bca8f24..c177f51314 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -20,8 +20,8 @@ namespace gl { - // Outputs text to the debugging log - void trace(bool traceFileDebugOnly, const char *format, ...); + // Outputs text to the debugging log, or the debugging window + void trace(bool traceInDebugOnly, const char *format, ...); // Returns whether D3DPERF is active. bool perfActive(); @@ -36,31 +36,34 @@ namespace gl private: DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper); }; + + void InitializeDebugAnnotations(); + void UninitializeDebugAnnotations(); } // A macro to output a trace of a function call and its arguments to the debugging log -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define TRACE(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define FIXME(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, in case of error. -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define ERR(message, ...) (void(0)) #endif // A macro to log a performance event around a scope. -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); #else @@ -83,7 +86,7 @@ namespace gl #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable) #endif -#ifndef ANGLE_ENABLE_TRACE +#ifndef ANGLE_ENABLE_DEBUG_TRACE #define UNUSED_TRACE_VARIABLE(variable) ((void)variable) #else #define UNUSED_TRACE_VARIABLE(variable) @@ -128,7 +131,7 @@ namespace gl #endif // A macro functioning as a compile-time assert to validate constant conditions -#if defined(_MSC_VER) && _MSC_VER >= 1600 +#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) #define META_ASSERT_MSG(condition, msg) static_assert(condition, msg) #else #define META_ASSERT_CONCAT(a, b) a ## b diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/common/features.h new file mode 100644 index 0000000000..b49a0ee852 --- /dev/null +++ b/src/3rdparty/angle/src/common/features.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#define ANGLE_DISABLED 0 +#define ANGLE_ENABLED 1 + +// Feature defaults + +// Direct3D9EX +// The "Debug This Pixel..." feature in PIX often fails when using the +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 +// machine, define "ANGLE_D3D9EX=0" in your project file. +#if !defined(ANGLE_D3D9EX) +#define ANGLE_D3D9EX ANGLE_ENABLED +#endif + +// Vsync +// ENABLED allows Vsync to be configured at runtime +// DISABLED disallows Vsync +#if !defined(ANGLE_VSYNC) +#define ANGLE_VSYNC ANGLE_ENABLED +#endif + +// Program binary loading +#if !defined(ANGLE_PROGRAM_BINARY_LOAD) +#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED +#endif + +// Shader debug info +#if !defined(ANGLE_SHADER_DEBUG_INFO) +#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED +#endif diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index 52f2bc1c0e..a1717892fd 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -109,7 +109,7 @@ inline unsigned int unorm(float x) inline bool supportsSSE2() { -#ifdef ANGLE_PLATFORM_WINDOWS +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) static bool checked = false; static bool supports = false; @@ -118,7 +118,6 @@ inline bool supportsSSE2() return supports; } -#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid() int info[4]; __cpuid(info, 0); @@ -128,7 +127,6 @@ inline bool supportsSSE2() supports = (info[3] >> 26) & 1; } -#endif checked = true; diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index b53394f337..0001e7142e 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -11,9 +11,6 @@ #if defined(_WIN32) || defined(_WIN64) # define ANGLE_PLATFORM_WINDOWS 1 -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -# define ANGLE_PLATFORM_WINRT 1 -# endif #elif defined(__APPLE__) # define ANGLE_PLATFORM_APPLE 1 # define ANGLE_PLATFORM_POSIX 1 @@ -37,6 +34,9 @@ #endif #ifdef ANGLE_PLATFORM_WINDOWS +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +# define ANGLE_ENABLE_WINDOWS_STORE 1 +# endif # ifndef STRICT # define STRICT 1 # endif @@ -50,7 +50,7 @@ # include <windows.h> # include <intrin.h> -# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) +# if defined(ANGLE_ENABLE_D3D9) # include <d3d9.h> # if !defined(COMPILER_IMPLEMENTATION) # include <d3dcompiler.h> @@ -62,13 +62,26 @@ # include <d3d10.h> # include <d3d11.h> # include <dxgi.h> -# if _MSC_VER >= 1700 +# if defined(_MSC_VER) && (_MSC_VER >= 1700) +# include <d3d11_1.h> # include <dxgi1_2.h> # endif # if !defined(COMPILER_IMPLEMENTATION) # include <d3dcompiler.h> # endif -# if defined(__MINGW32__) +# endif + +# if defined(ANGLE_ENABLE_WINDOWS_STORE) +# include <dxgi1_3.h> +# if defined(_DEBUG) +# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) +# include <DXProgrammableCapture.h> +# endif +# include <dxgidebug.h> +# endif +# endif + +# if defined(__MINGW32__) // Missing defines on MinGW typedef enum D3D11_MAP_FLAG { D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L @@ -78,8 +91,68 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS UINT64 NumPrimitivesWritten; UINT64 PrimitivesStorageNeeded; } D3D11_QUERY_DATA_SO_STATISTICS; -# endif -# endif +typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)( + IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *, + UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); +#define D3D11_MESSAGE_CATEGORY UINT +#define D3D11_MESSAGE_SEVERITY UINT +#define D3D11_MESSAGE_ID UINT +struct D3D11_MESSAGE; +typedef struct D3D11_INFO_QUEUE_FILTER_DESC +{ + UINT NumCategories; + D3D11_MESSAGE_CATEGORY *pCategoryList; + UINT NumSeverities; + D3D11_MESSAGE_SEVERITY *pSeverityList; + UINT NumIDs; + D3D11_MESSAGE_ID *pIDList; +} D3D11_INFO_QUEUE_FILTER_DESC; +typedef struct D3D11_INFO_QUEUE_FILTER +{ + D3D11_INFO_QUEUE_FILTER_DESC AllowList; + D3D11_INFO_QUEUE_FILTER_DESC DenyList; +} D3D11_INFO_QUEUE_FILTER; +static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; +MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown +{ +public: + virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; + virtual void __stdcall ClearStoredMessages() = 0; + virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; + virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumStoredMessages() = 0; + virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; + virtual UINT64 __stdcall GetMessageCountLimit() = 0; + virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearStorageFilter() = 0; + virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; + virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; + virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopStorageFilter() = 0; + virtual UINT __stdcall GetStorageFilterStackSize() = 0; + virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearRetrievalFilter() = 0; + virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; + virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; + virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopRetrievalFilter() = 0; + virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; + virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; + virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; + virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; + virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; + virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; + virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; + virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; + virtual BOOL __stdcall GetMuteDebugOutput() = 0; +}; +#endif // __MINGW32__ # undef near # undef far diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp index c46fab5303..cb1b32d325 100644 --- a/src/3rdparty/angle/src/common/tls.cpp +++ b/src/3rdparty/angle/src/common/tls.cpp @@ -10,29 +10,50 @@ #include <assert.h> -#if defined(ANGLE_PLATFORM_WINRT) +#ifdef ANGLE_ENABLE_WINDOWS_STORE #include <vector> -std::vector<void *> *tls = nullptr; -std::vector<TLSIndex> *freeIndices = nullptr; +#include <set> +#include <map> +#include <mutex> + +#include <wrl/client.h> +#include <wrl/async.h> +#include <Windows.System.Threading.h> + +using namespace std; +using namespace Windows::Foundation; +using namespace ABI::Windows::System::Threading; + +// Thread local storage for Windows Store support +typedef vector<void*> ThreadLocalData; + +static __declspec(thread) ThreadLocalData* currentThreadData = nullptr; +static set<ThreadLocalData*> allThreadData; +static DWORD nextTlsIndex = 0; +static vector<DWORD> freeTlsIndices; + #endif TLSIndex CreateTLSIndex() { TLSIndex index; -#if defined(ANGLE_PLATFORM_WINRT) - if (!tls) - tls = new std::vector<void *>; - if (freeIndices && !freeIndices->empty()) { - index = freeIndices->back(); - freeIndices->pop_back(); - return index; - } else { - tls->push_back(nullptr); - return tls->size() - 1; +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + if (!freeTlsIndices.empty()) + { + DWORD result = freeTlsIndices.back(); + freeTlsIndices.pop_back(); + index = result; } -#elif defined(ANGLE_PLATFORM_WINDOWS) + else + { + index = nextTlsIndex++; + } +#else index = TlsAlloc(); +#endif + #elif defined(ANGLE_PLATFORM_POSIX) // Create global pool key if ((pthread_key_create(&index, NULL)) != 0) @@ -53,13 +74,23 @@ bool DestroyTLSIndex(TLSIndex index) return false; } -#if defined(ANGLE_PLATFORM_WINRT) - if (!freeIndices) - freeIndices = new std::vector<TLSIndex>; - freeIndices->push_back(index); +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + assert(index < nextTlsIndex); + assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end()); + + freeTlsIndices.push_back(index); + for (auto threadData : allThreadData) + { + if (threadData->size() > index) + { + threadData->at(index) = nullptr; + } + } return true; -#elif ANGLE_PLATFORM_WINDOWS +#else return (TlsFree(index) == TRUE); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return (pthread_key_delete(index) == 0); #endif @@ -73,11 +104,25 @@ bool SetTLSValue(TLSIndex index, void *value) return false; } -#if defined(ANGLE_PLATFORM_WINRT) - tls->at(index) = value; +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + ThreadLocalData* threadData = currentThreadData; + if (!threadData) + { + threadData = new ThreadLocalData(index + 1, nullptr); + allThreadData.insert(threadData); + currentThreadData = threadData; + } + else if (threadData->size() <= index) + { + threadData->resize(index + 1, nullptr); + } + + threadData->at(index) = value; return true; -#elif defined(ANGLE_PLATFORM_WINDOWS) +#else return (TlsSetValue(index, value) == TRUE); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return (pthread_setspecific(index, value) == 0); #endif @@ -85,18 +130,26 @@ bool SetTLSValue(TLSIndex index, void *value) void *GetTLSValue(TLSIndex index) { -#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); -#endif if (index == TLS_INVALID_INDEX) { return NULL; } -#if defined(ANGLE_PLATFORM_WINRT) - return tls->at(index); -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + ThreadLocalData* threadData = currentThreadData; + if (threadData && threadData->size() > index) + { + return threadData->at(index); + } + else + { + return nullptr; + } +#else return TlsGetValue(index); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return pthread_getspecific(index); #endif diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h index c40ae1a061..8a06e92d1a 100644 --- a/src/3rdparty/angle/src/common/tls.h +++ b/src/3rdparty/angle/src/common/tls.h @@ -11,11 +11,15 @@ #include "common/platform.h" -#if defined(ANGLE_PLATFORM_WINRT) - typedef size_t TLSIndex; -# define TLS_OUT_OF_INDEXES (static_cast<TLSIndex>(-1)) -# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS + +// TLS does not exist for Windows Store and needs to be emulated +# ifdef ANGLE_ENABLE_WINDOWS_STORE +# define TLS_OUT_OF_INDEXES -1 +# ifndef CREATE_SUSPENDED +# define CREATE_SUSPENDED 0x00000004 +# endif +# endif typedef DWORD TLSIndex; # define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) #elif defined(ANGLE_PLATFORM_POSIX) @@ -28,6 +32,9 @@ # error Unsupported platform. #endif +// TODO(kbr): for POSIX platforms this will have to be changed to take +// in a destructor function pointer, to allow the thread-local storage +// to be properly deallocated upon thread exit. TLSIndex CreateTLSIndex(); bool DestroyTLSIndex(TLSIndex index); diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp index 4b8e325d22..9d797a6612 100644 --- a/src/3rdparty/angle/src/common/utilities.cpp +++ b/src/3rdparty/angle/src/common/utilities.cpp @@ -9,17 +9,16 @@ #include "common/utilities.h" #include "common/mathutil.h" #include "common/platform.h" -#if defined(ANGLE_PLATFORM_WINRT) -# include <locale> -# include <codecvt> -# include <wrl.h> -# include <windows.storage.h> - using namespace Microsoft::WRL; - using namespace ABI::Windows::Storage; -#endif #include <set> +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +# include <wrl.h> +# include <wrl/wrappers/corewrappers.h> +# include <windows.applicationmodel.core.h> +# include <windows.graphics.display.h> +#endif + namespace gl { @@ -447,50 +446,10 @@ int VariableSortOrder(GLenum type) } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) std::string getTempPath() { -#if defined(ANGLE_PLATFORM_WINRT) - static std::string path; - - while (path.empty()) - { - ComPtr<IApplicationDataStatics> factory; - Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); - HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); - if (FAILED(result)) - break; - - ComPtr<IApplicationData> applicationData; - result = factory->get_Current(&applicationData); - if (FAILED(result)) - break; - - ComPtr<IStorageFolder> storageFolder; - result = applicationData->get_LocalFolder(&storageFolder); - if (FAILED(result)) - break; - - ComPtr<IStorageItem> localFolder; - result = storageFolder.As(&localFolder); - if (FAILED(result)) - break; - - HSTRING localFolderPath; - result = localFolder->get_Path(&localFolderPath); - if (FAILED(result)) - break; - - std::wstring_convert< std::codecvt_utf8<wchar_t> > converter; - path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); - if (path.empty()) - { - UNREACHABLE(); - break; - } - } - - return path; -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS char path[MAX_PATH]; DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); if (pathLen == 0) @@ -525,3 +484,33 @@ void writeFile(const char* path, const void* content, size_t size) fwrite(content, sizeof(char), size, file); fclose(file); } +#endif // !ANGLE_ENABLE_WINDOWS_STORE + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + +void Sleep(unsigned long dwMilliseconds) +{ + static HANDLE singletonEvent = nullptr; + HANDLE sleepEvent = singletonEvent; + if (!sleepEvent) + { + sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + + if (!sleepEvent) + return; + + HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr); + + if (previousEvent) + { + // Back out if multiple threads try to demand create at the same time. + CloseHandle(sleepEvent); + sleepEvent = previousEvent; + } + } + + // Emulate sleep by waiting with timeout on an event that is never signalled. + WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); +} + +#endif // ANGLE_ENABLE_WINDOWS_STORE diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h index a823184ecd..2cf6bed176 100644 --- a/src/3rdparty/angle/src/common/utilities.h +++ b/src/3rdparty/angle/src/common/utilities.h @@ -46,7 +46,13 @@ template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>( } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); +#endif + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +void Sleep(_In_ unsigned long dwMilliseconds); +#endif #endif // LIBGLESV2_UTILITIES_H diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp new file mode 100644 index 0000000000..2440747260 --- /dev/null +++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// NativeWindow.cpp: Handler for managing HWND native window types. + +#include "common/NativeWindow.h" +#include "common/debug.h" + +namespace rx +{ +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return (IsWindow(window) == TRUE); +} + +NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display) +{ +} + +bool NativeWindow::initialize() +{ + return true; +} + +bool NativeWindow::getClientRect(LPRECT rect) +{ + return GetClientRect(mWindow, rect) == TRUE; +} + +bool NativeWindow::isIconic() +{ + return IsIconic(mWindow) == TRUE; +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, + DXGI_FORMAT format, unsigned int width, unsigned int height, + DXGISwapChain** swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = format; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + return factory->CreateSwapChain(device, &swapChainDesc, swapChain); +} +} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp new file mode 100644 index 0000000000..9b65c15625 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp @@ -0,0 +1,200 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. + +#include <algorithm> +#include "common/winrt/CoreWindowNativeWindow.h" +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ + +typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler; + +CoreWindowNativeWindow::~CoreWindowNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +{ + ComPtr<IPropertySet> props = propertySet; + ComPtr<IInspectable> win = window; + ComPtr<IInspectable> displayInformation = display; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mCoreWindow); + } + + if (SUCCEEDED(result)) + { + result = displayInformation.As(&mDisplayInformation); + } + + if (SUCCEEDED(result)) + { +#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2; + result = mDisplayInformation.As(&displayInformation2); + ASSERT(SUCCEEDED(result)); + + result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); + ASSERT(SUCCEEDED(result)); +#else + ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; + result = mDisplayInformation->get_ResolutionScale(&resolutionScale); + ASSERT(SUCCEEDED(result)); + + mScaleFactor = DOUBLE(resolutionScale) / 100.0; +#endif + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output occurs automatically because if + // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + mSupportsSwapChainResize = false; + } + else + { + ABI::Windows::Foundation::Rect rect; + HRESULT result = mCoreWindow->get_Bounds(&rect); + if (SUCCEEDED(result)) + { + LONG width = std::floor(rect.Width * mScaleFactor + 0.5); + LONG height = std::floor(rect.Height * mScaleFactor + 0.5); + mClientRect = { 0, 0, width, height }; + } + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool CoreWindowNativeWindow::registerForSizeChangeEvents() +{ + HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(), + &mSizeChangedEventToken); + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void CoreWindowNativeWindow::unregisterForSizeChangeEvents() +{ + if (mCoreWindow) + { + (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); + } + mSizeChangedEventToken.value = 0; +} + +HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + + *swapChain = nullptr; + + ComPtr<IDXGISwapChain1> newSwapChain; + HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + if (SUCCEEDED(result)) + { + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected + // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On + // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed + // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. + if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) + { + mSupportsSwapChainResize = false; + } +#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + + result = newSwapChain.CopyTo(swapChain); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +// Basically, this shouldn't be used on Phone +HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) +{ + ABI::Windows::Foundation::Size size; + if (SUCCEEDED(e->get_Size(&size))) + { + SIZE windowSizeInPixels = { + std::floor(size.Width * mScaleFactor + 0.5), + std::floor(size.Height * mScaleFactor + 0.5) + }; + setNewClientSize(windowSizeInPixels); + } + + return S_OK; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h new file mode 100644 index 0000000000..1c5512417d --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types. + +#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ +#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ + +#include "common/winrt/InspectableNativeWindow.h" +#include <memory> +#include <windows.graphics.display.h> + +namespace rx +{ + +class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow> +{ + public: + ~CoreWindowNativeWindow(); + + bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + + private: + HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); + + ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow; + ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; +}; + +} + +#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp new file mode 100644 index 0000000000..0589f6dce5 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp @@ -0,0 +1,274 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "common/winrt/CoreWindowNativeWindow.h" +#include "common/winrt/SwapChainPanelNativeWindow.h" + +namespace rx +{ +NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) + : mWindow(window), mDisplay(display) +{ +} + +bool NativeWindow::initialize() +{ + // If the native window type is a IPropertySet, extract the + // EGLNativeWindowType (IInspectable) and initialize the + // proper host with this IPropertySet. + ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet; + ComPtr<IInspectable> eglNativeWindow; + if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow)) + { + // A property set was found and the EGLNativeWindowType was + // retrieved. The mWindow member of the host to must be updated + // to use the EGLNativeWindowType specified in the property set. + // mWindow is treated as a raw pointer not an AddRef'd interface, so + // the old mWindow does not need a Release() before this assignment. + mWindow = eglNativeWindow.Get(); + } + + ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow; + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel; + if (IsCoreWindow(mWindow, &coreWindow)) + { + mImpl = std::make_shared<CoreWindowNativeWindow>(); + if (mImpl) + { + return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else if (IsSwapChainPanel(mWindow, &swapChainPanel)) + { + mImpl = std::make_shared<SwapChainPanelNativeWindow>(); + if (mImpl) + { + return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else + { + ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); + } + + return false; +} + +bool NativeWindow::getClientRect(RECT *rect) +{ + if (mImpl) + { + return mImpl->getClientRect(rect); + } + + return false; +} + +bool NativeWindow::isIconic() +{ + return false; +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (mImpl) + { + return mImpl->createSwapChain(device, factory, format, width, height, swapChain); + } + + return E_UNEXPECTED; +} + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> win = window; + ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin; + if (SUCCEEDED(win.As(&coreWin))) + { + if (coreWindow != nullptr) + { + *coreWindow = coreWin.Detach(); + } + return true; + } + + return false; +} + +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> win = window; + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel; + if (SUCCEEDED(win.As(&panel))) + { + if (swapChainPanel != nullptr) + { + *swapChainPanel = panel.Detach(); + } + return true; + } + + return false; +} + +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow) +{ + if (!window) + { + return false; + } + + ComPtr<IInspectable> props = window; + ComPtr<IPropertySet> propSet; + ComPtr<IInspectable> nativeWindow; + ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap; + boolean hasEglNativeWindowPropertyKey = false; + + HRESULT result = props.As(&propSet); + if (SUCCEEDED(result)) + { + result = propSet.As(&propMap); + } + + // Look for the presence of the EGLNativeWindowType in the property set + if (SUCCEEDED(result)) + { + result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey); + } + + // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is + // considered invalid. + if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) + { + ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); + return false; + } + + // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType + if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey) + { + result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow); + } + + if (SUCCEEDED(result)) + { + if (propertySet != nullptr) + { + result = propSet.CopyTo(propertySet); + } + } + + if (SUCCEEDED(result)) + { + if (eglNativeWindow != nullptr) + { + result = nativeWindow.CopyTo(eglNativeWindow); + } + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +// A Valid EGLNativeWindowType IInspectable can only be: +// +// ICoreWindow +// IPropertySet +// +// Anything else will be rejected as an invalid IInspectable. +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); +} + +// Attempts to read an optional SIZE property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Size. This function validates the Size value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated +// S_OK, valueExists == false - optional SIZE value was not found +// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Size) +// * Invalid property value (width/height must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists) +{ + if (!propertyMap || !propertyName || !value || !valueExists) + { + return false; + } + + // Assume that the value does not exist + *valueExists = false; + *value = { 0, 0 }; + + ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + Size sizeValue = { 0, 0 }; + boolean hasKey = false; + + HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey); + if (SUCCEEDED(result) && !hasKey) + { + // Value does not exist, so return S_OK and set the exists parameter to false to indicate + // that a the optional property does not exist. + *valueExists = false; + return S_OK; + } + + if (SUCCEEDED(result)) + { + result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); + } + + if (SUCCEEDED(result)) + { + result = propertyValue->get_Type(&propertyType); + } + + // Check if the expected Size property is of PropertyType_Size type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) + { + if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + { + // A valid property value exists + *value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) }; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid Size property was detected. Width/Height values must > 0 + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Size + result = E_INVALIDARG; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h new file mode 100644 index 0000000000..402941a788 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InspectableNativeWindow.h: Host specific implementation interface for +// managing IInspectable native window types. + +#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ +#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ + +#include "common/platform.h" +#include "common/NativeWindow.h" +#include "angle_windowsstore.h" + +#include <windows.ui.xaml.h> +#include <windows.ui.xaml.media.dxinterop.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +class InspectableNativeWindow +{ + public: + InspectableNativeWindow() : + mSupportsSwapChainResize(true), + mRequiresSwapChainScaling(false), + mClientRectChanged(false), + mClientRect({0,0,0,0}), + mNewClientRect({0,0,0,0}), + mScaleFactor(1.0) + { + mSizeChangedEventToken.value = 0; + } + virtual ~InspectableNativeWindow(){} + + virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; + virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; + virtual bool registerForSizeChangeEvents() = 0; + virtual void unregisterForSizeChangeEvents() = 0; + virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; } + + bool getClientRect(RECT *rect) + { + if (mClientRectChanged && mSupportsSwapChainResize) + { + mClientRect = mNewClientRect; + mClientRectChanged = false; + } + + *rect = mClientRect; + + return true; + } + + void setNewClientSize(const SIZE &newSize) + { + if (mSupportsSwapChainResize && !mRequiresSwapChainScaling) + { + mNewClientRect = { 0, 0, newSize.cx, newSize.cy }; + mClientRectChanged = true; + } + + if (mRequiresSwapChainScaling) + { + scaleSwapChain(newSize); + } + } + +protected: + bool mSupportsSwapChainResize; + bool mRequiresSwapChainScaling; + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; + DOUBLE mScaleFactor; + + EventRegistrationToken mSizeChangedEventToken; +}; + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr); +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr); +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); +HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists); +} +#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp new file mode 100644 index 0000000000..268dfbd8f0 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp @@ -0,0 +1,226 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. + +#include "common/winrt/SwapChainPanelNativeWindow.h" +#include <algorithm> +#include <math.h> +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +{ + ComPtr<IPropertySet> props = propertySet; + ComPtr<IInspectable> win = window; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mSwapChainPanel); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output needs to be handled by the + // host for swapchain panels even though the scaling mode setting + // DXGI_SCALING_STRETCH is configured on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + + // Enable host swapchain scaling + mRequiresSwapChainScaling = true; + } + else + { + result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect); + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() +{ + ComPtr<ABI::Windows::UI::Xaml::ISizeChangedEventHandler> sizeChangedHandler; + ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement; + HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&frameworkElement); + } + + if (SUCCEEDED(result)) + { + result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() +{ + ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement; + if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) + { + (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + } + + mSizeChangedEventToken.value = 0; +} + +HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + *swapChain = nullptr; + + ComPtr<IDXGISwapChain1> newSwapChain; + ComPtr<ISwapChainPanelNative> swapChainPanelNative; + RECT currentPanelSize = {}; + + HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelNative); + } + + if (SUCCEEDED(result)) + { + result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + } + + if (SUCCEEDED(result)) + { + // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel + // to perform the runtime-scale behavior. This swapchain is cached here because there are + // no methods for retreiving the currently configured on from ISwapChainPanelNative. + mSwapChain = newSwapChain; + result = newSwapChain.CopyTo(swapChain); + } + + // If the host is responsible for scaling the output of the swapchain, then + // scale it now before returning an instance to the caller. This is done by + // first reading the current size of the swapchain panel, then scaling + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + result = GetSwapChainPanelSize(mSwapChainPanel, ¤tPanelSize); + } + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom }; + result = scaleSwapChain(currentSize); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize) +{ + ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom }; + // Setup a scale matrix for the swap chain + DXGI_MATRIX_3X2_F scaleMatrix = {}; + scaleMatrix._11 = renderScale.Width; + scaleMatrix._22 = renderScale.Height; + + ComPtr<IDXGISwapChain2> swapChain2; + HRESULT result = mSwapChain.As(&swapChain2); + if (SUCCEEDED(result)) + { + result = swapChain2->SetMatrixTransform(&scaleMatrix); + } + + return result; +} + +HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize) +{ + ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement; + ABI::Windows::Foundation::Size renderSize = { 0, 0 }; + HRESULT result = swapChainPanel.As(&uiElement); + if (SUCCEEDED(result)) + { + result = uiElement->get_RenderSize(&renderSize); + } + + if (SUCCEEDED(result)) + { + *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) }; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h new file mode 100644 index 0000000000..5bbf274e64 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. + +#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ + +#include "common/winrt/InspectableNativeWindow.h" + +namespace rx +{ +class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow> +{ + public: + ~SwapChainPanelNativeWindow(); + + bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + HRESULT scaleSwapChain(const SIZE &newSize); + + private: + ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; + ComPtr<DXGISwapChain> mSwapChain; +}; + +[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] +class SwapChainPanelSizeChangedHandler : + public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler> +{ + public: + SwapChainPanelSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // ISizeChangedEventHandler + IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); + if (host) + { + // The size of the ISwapChainPanel control is returned in DIPs. + // We are keeping these in dips because the swapchain created for composition + // also uses dip units. This keeps dimensions, viewports, etc in the same unit. + // XAML Clients of the ISwapChainPanel are required to use dips to define their + // layout sizes as well. + ABI::Windows::Foundation::Size newSize; + HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize); + if (SUCCEEDED(result)) + { + SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) }; + host->setNewClientSize(windowSize); + } + } + + return S_OK; + } + + private: + std::weak_ptr<InspectableNativeWindow> mHost; +}; + +HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize); +} +#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h index 040b25c6a2..eec0d5e5f0 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h @@ -29,7 +29,8 @@ class DirectiveHandler // Handle pragma of form: #pragma name[(value)] virtual void handlePragma(const SourceLocation &loc, const std::string &name, - const std::string &value) = 0; + const std::string &value, + bool stdgl) = 0; virtual void handleExtension(const SourceLocation &loc, const std::string &name, diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp index 6434d5cb5c..7803ee845a 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp @@ -38,19 +38,19 @@ enum DirectiveType DirectiveType getDirective(const pp::Token *token) { - static const std::string kDirectiveDefine("define"); - static const std::string kDirectiveUndef("undef"); - static const std::string kDirectiveIf("if"); - static const std::string kDirectiveIfdef("ifdef"); - static const std::string kDirectiveIfndef("ifndef"); - static const std::string kDirectiveElse("else"); - static const std::string kDirectiveElif("elif"); - static const std::string kDirectiveEndif("endif"); - static const std::string kDirectiveError("error"); - static const std::string kDirectivePragma("pragma"); - static const std::string kDirectiveExtension("extension"); - static const std::string kDirectiveVersion("version"); - static const std::string kDirectiveLine("line"); + const char kDirectiveDefine[] = "define"; + const char kDirectiveUndef[] = "undef"; + const char kDirectiveIf[] = "if"; + const char kDirectiveIfdef[] = "ifdef"; + const char kDirectiveIfndef[] = "ifndef"; + const char kDirectiveElse[] = "else"; + const char kDirectiveElif[] = "elif"; + const char kDirectiveEndif[] = "endif"; + const char kDirectiveError[] = "error"; + const char kDirectivePragma[] = "pragma"; + const char kDirectiveExtension[] = "extension"; + const char kDirectiveVersion[] = "version"; + const char kDirectiveLine[] = "line"; if (token->type != pp::Token::IDENTIFIER) return DIRECTIVE_NONE; @@ -155,7 +155,7 @@ class DefinedParser : public Lexer protected: virtual void lex(Token *token) { - static const std::string kDefined("defined"); + const char kDefined[] = "defined"; mLexer->lex(token); if (token->type != Token::IDENTIFIER) @@ -592,6 +592,11 @@ void DirectiveParser::parsePragma(Token *token) int state = PRAGMA_NAME; mTokenizer->lex(token); + bool stdgl = token->text == "STDGL"; + if (stdgl) + { + mTokenizer->lex(token); + } while ((token->type != '\n') && (token->type != Token::LAST)) { switch(state++) @@ -627,7 +632,7 @@ void DirectiveParser::parsePragma(Token *token) } else if (state > PRAGMA_NAME) // Do not notify for empty pragma. { - mDirectiveHandler->handlePragma(token->location, name, value); + mDirectiveHandler->handlePragma(token->location, name, value, stdgl); } } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp index d7e0c83465..69e2f39069 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -194,8 +194,8 @@ bool MacroExpander::expandMacro(const Macro ¯o, if (macro.predefined) { - static const std::string kLine = "__LINE__"; - static const std::string kFile = "__FILE__"; + const char kLine[] = "__LINE__"; + const char kFile[] = "__FILE__"; assert(replacements->size() == 1); Token& repl = replacements->front(); diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 368cd2ae4a..5c62a64d10 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -29,24 +29,27 @@ bool IsWebGLBasedSpec(ShShaderSpec spec) { - return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC; + return (spec == SH_WEBGL_SPEC || + spec == SH_CSS_SHADERS_SPEC || + spec == SH_WEBGL2_SPEC); } size_t GetGlobalMaxTokenSize(ShShaderSpec spec) { // WebGL defines a max token legnth of 256, while ES2 leaves max token // size undefined. ES3 defines a max size of 1024 characters. - if (IsWebGLBasedSpec(spec)) + switch (spec) { + case SH_WEBGL_SPEC: + case SH_CSS_SHADERS_SPEC: return 256; - } - else - { + default: return 1024; } } namespace { + class TScopedPoolAllocator { public: @@ -82,6 +85,24 @@ class TScopedSymbolTableLevel private: TSymbolTable* mTable; }; + +int MapSpecToShaderVersion(ShShaderSpec spec) +{ + switch (spec) + { + case SH_GLES2_SPEC: + case SH_WEBGL_SPEC: + case SH_CSS_SHADERS_SPEC: + return 100; + case SH_GLES3_SPEC: + case SH_WEBGL2_SPEC: + return 300; + default: + UNREACHABLE(); + return 0; + } +} + } // namespace TShHandleBase::TShHandleBase() @@ -178,9 +199,21 @@ bool TCompiler::compile(const char* const shaderStrings[], (parseContext.treeRoot != NULL); shaderVersion = parseContext.getShaderVersion(); + if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion) + { + infoSink.info.prefix(EPrefixError); + infoSink.info << "unsupported shader version"; + success = false; + } if (success) { + mPragma = parseContext.pragma(); + if (mPragma.stdgl.invariantAll) + { + symbolTable.setGlobalInvariant(); + } + TIntermNode* root = parseContext.treeRoot; success = intermediate.postProcess(root); @@ -360,7 +393,8 @@ void TCompiler::setResourceString() << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset - << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset; + << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset + << ":NV_draw_buffers:" << compileResources.NV_draw_buffers; builtInResourcesString = strstream.str(); } @@ -377,7 +411,6 @@ void TCompiler::clearResults() uniforms.clear(); expandedUniforms.clear(); varyings.clear(); - expandedVaryings.clear(); interfaceBlocks.clear(); builtInFunctionEmulator.Cleanup(); @@ -507,13 +540,12 @@ void TCompiler::collectVariables(TIntermNode* root) &uniforms, &varyings, &interfaceBlocks, - hashFunction); + hashFunction, + symbolTable); root->traverse(&collect); - // For backwards compatiblity with ShGetVariableInfo, expand struct - // uniforms and varyings into separate variables for each field. - sh::ExpandVariables(uniforms, &expandedUniforms); - sh::ExpandVariables(varyings, &expandedVaryings); + // This is for enforcePackingRestriction(). + sh::ExpandUniforms(uniforms, &expandedUniforms); } bool TCompiler::enforcePackingRestrictions() @@ -581,3 +613,10 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const { return builtInFunctionEmulator; } + +void TCompiler::writePragma() +{ + TInfoSinkBase &sink = infoSink.obj; + if (mPragma.stdgl.invariantAll) + sink << "#pragma STDGL invariant(all)\n"; +} diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index ca0c157884..b6c9d13ed0 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -18,6 +18,7 @@ #include "compiler/translator/ExtensionBehavior.h" #include "compiler/translator/HashNames.h" #include "compiler/translator/InfoSink.h" +#include "compiler/translator/Pragma.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/VariableInfo.h" #include "third_party/compiler/ArrayBoundsClamper.h" @@ -71,9 +72,7 @@ class TCompiler : public TShHandleBase const std::vector<sh::Attribute> &getAttributes() const { return attributes; } const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; } const std::vector<sh::Uniform> &getUniforms() const { return uniforms; } - const std::vector<sh::ShaderVariable> &getExpandedUniforms() const { return expandedUniforms; } const std::vector<sh::Varying> &getVaryings() const { return varyings; } - const std::vector<sh::ShaderVariable> &getExpandedVaryings() const { return expandedVaryings; } const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; } ShHashFunction64 getHashFunction() const { return hashFunction; } @@ -81,7 +80,7 @@ class TCompiler : public TShHandleBase TSymbolTable& getSymbolTable() { return symbolTable; } ShShaderSpec getShaderSpec() const { return shaderSpec; } ShShaderOutput getOutputType() const { return outputType; } - std::string getBuiltInResourcesString() const { return builtInResourcesString; } + const std::string &getBuiltInResourcesString() const { return builtInResourcesString; } // Get the resources set by InitBuiltInSymbolTable const ShBuiltInResources& getResources() const; @@ -131,6 +130,8 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; + const TPragma& getPragma() const { return mPragma; } + void writePragma(); const ArrayBoundsClamper& getArrayBoundsClamper() const; ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; @@ -141,7 +142,6 @@ class TCompiler : public TShHandleBase std::vector<sh::Uniform> uniforms; std::vector<sh::ShaderVariable> expandedUniforms; std::vector<sh::Varying> varyings; - std::vector<sh::ShaderVariable> expandedVaryings; std::vector<sh::InterfaceBlock> interfaceBlocks; private: @@ -174,6 +174,8 @@ class TCompiler : public TShHandleBase // name hashing. ShHashFunction64 hashFunction; NameMap nameMap; + + TPragma mPragma; }; // diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp index 334eb0bfa8..f98d32b2b7 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp @@ -14,6 +14,9 @@ namespace sh { + +// Detect Loop Discontinuity + bool DetectLoopDiscontinuity::traverse(TIntermNode *node) { mLoopDepth = 0; @@ -74,6 +77,55 @@ bool containsLoopDiscontinuity(TIntermNode *node) return detectLoopDiscontinuity.traverse(node); } +// Detect Any Loop + +bool DetectAnyLoop::traverse(TIntermNode *node) +{ + mHasLoop = false; + node->traverse(this); + return mHasLoop; +} + +bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop) +{ + mHasLoop = true; + return false; +} + +// The following definitions stop all traversal when we have found a loop +bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *) +{ + return !mHasLoop; +} + +bool containsAnyLoop(TIntermNode *node) +{ + DetectAnyLoop detectAnyLoop; + return detectAnyLoop.traverse(node); +} + +// Detect Gradient Operation + bool DetectGradientOperation::traverse(TIntermNode *node) { mGradientOperation = false; diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 35d66cbc2e..67e37be398 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -32,6 +32,25 @@ class DetectLoopDiscontinuity : public TIntermTraverser bool containsLoopDiscontinuity(TIntermNode *node); +// Checks for the existence of any loop +class DetectAnyLoop : public TIntermTraverser +{ +public: + bool traverse(TIntermNode *node); + +protected: + bool visitBinary(Visit, TIntermBinary *); + bool visitUnary(Visit, TIntermUnary *); + bool visitSelection(Visit, TIntermSelection *); + bool visitAggregate(Visit, TIntermAggregate *); + bool visitLoop(Visit, TIntermLoop *); + bool visitBranch(Visit, TIntermBranch *); + + bool mHasLoop; +}; + +bool containsAnyLoop(TIntermNode *node); + // Checks for intrinsic functions which compute gradients class DetectGradientOperation : public TIntermTraverser { diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp index 59d2835f7b..f67a03aa93 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -13,10 +13,10 @@ static TBehavior getBehavior(const std::string& str) { - static const std::string kRequire("require"); - static const std::string kEnable("enable"); - static const std::string kDisable("disable"); - static const std::string kWarn("warn"); + const char kRequire[] = "require"; + const char kEnable[] = "enable"; + const char kDisable[] = "disable"; + const char kWarn[] = "warn"; if (str == kRequire) return EBhRequire; else if (str == kEnable) return EBhEnable; @@ -46,50 +46,61 @@ void TDirectiveHandler::handleError(const pp::SourceLocation& loc, void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, const std::string& name, - const std::string& value) + const std::string& value, + bool stdgl) { - static const std::string kSTDGL("STDGL"); - static const std::string kOptimize("optimize"); - static const std::string kDebug("debug"); - static const std::string kOn("on"); - static const std::string kOff("off"); - - bool invalidValue = false; - if (name == kSTDGL) + if (stdgl) { + const char kInvariant[] = "invariant"; + const char kAll[] = "all"; + + if (name == kInvariant && value == kAll) + mPragma.stdgl.invariantAll = true; // The STDGL pragma is used to reserve pragmas for use by future - // revisions of GLSL. Ignore it. + // revisions of GLSL. Do not generate an error on unexpected + // name and value. return; } - else if (name == kOptimize) - { - if (value == kOn) mPragma.optimize = true; - else if (value == kOff) mPragma.optimize = false; - else invalidValue = true; - } - else if (name == kDebug) - { - if (value == kOn) mPragma.debug = true; - else if (value == kOff) mPragma.debug = false; - else invalidValue = true; - } else { - mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); - return; - } + const char kOptimize[] = "optimize"; + const char kDebug[] = "debug"; + const char kOn[] = "on"; + const char kOff[] = "off"; - if (invalidValue) - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "invalid pragma value", value, - "'on' or 'off' expected"); + bool invalidValue = false; + if (name == kOptimize) + { + if (value == kOn) mPragma.optimize = true; + else if (value == kOff) mPragma.optimize = false; + else invalidValue = true; + } + else if (name == kDebug) + { + if (value == kOn) mPragma.debug = true; + else if (value == kOff) mPragma.debug = false; + else invalidValue = true; + } + else + { + mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); + return; + } + + if (invalidValue) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "invalid pragma value", value, + "'on' or 'off' expected"); + } + } } void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, const std::string& name, const std::string& behavior) { - static const std::string kExtAll("all"); + const char kExtAll[] = "all"; TBehavior behaviorVal = getBehavior(behavior); if (behaviorVal == EBhUndefined) diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h index 69418c277a..0433c3bf89 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -29,7 +29,8 @@ class TDirectiveHandler : public pp::DirectiveHandler virtual void handlePragma(const pp::SourceLocation& loc, const std::string& name, - const std::string& value); + const std::string& value, + bool stdgl); virtual void handleExtension(const pp::SourceLocation& loc, const std::string& name, diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp index b155545ad2..aa0f31d170 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -133,6 +133,14 @@ bool CompareStructure(const TType &leftNodeType, // //////////////////////////////////////////////////////////////// +void TIntermTyped::setTypePreservePrecision(const TType &t) +{ + TPrecision precision = getPrecision(); + mType = t; + ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined); + mType.setPrecision(precision); +} + #define REPLACE_IF_IS(node, type, original, replacement) \ if (node == original) { \ node = static_cast<type *>(replacement); \ @@ -237,6 +245,52 @@ void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) con } } +void TIntermAggregate::setPrecisionFromChildren() +{ + if (getBasicType() == EbtBool) + { + mType.setPrecision(EbpUndefined); + return; + } + + TPrecision precision = EbpUndefined; + TIntermSequence::iterator childIter = mSequence.begin(); + while (childIter != mSequence.end()) + { + TIntermTyped *typed = (*childIter)->getAsTyped(); + if (typed) + precision = GetHigherPrecision(typed->getPrecision(), precision); + ++childIter; + } + mType.setPrecision(precision); +} + +void TIntermAggregate::setBuiltInFunctionPrecision() +{ + // All built-ins returning bool should be handled as ops, not functions. + ASSERT(getBasicType() != EbtBool); + + TPrecision precision = EbpUndefined; + TIntermSequence::iterator childIter = mSequence.begin(); + while (childIter != mSequence.end()) + { + TIntermTyped *typed = (*childIter)->getAsTyped(); + // ESSL spec section 8: texture functions get their precision from the sampler. + if (typed && IsSampler(typed->getBasicType())) + { + precision = typed->getPrecision(); + break; + } + ++childIter; + } + // ESSL 3.0 spec section 8: textureSize always gets highp precision. + // All other functions that take a sampler are assumed to be texture functions. + if (mName.find("textureSize") == 0) + mType.setPrecision(EbpHigh); + else + mType.setPrecision(precision); +} + bool TIntermSelection::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -336,6 +390,7 @@ bool TIntermUnary::promote(TInfoSink &) return false; break; case EOpNegative: + case EOpPositive: case EOpPostIncrement: case EOpPostDecrement: case EOpPreIncrement: @@ -1068,6 +1123,27 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpPositive: + switch (getType().getBasicType()) + { + case EbtFloat: + tempConstArray[i].setFConst(unionArray[i].getFConst()); + break; + case EbtInt: + tempConstArray[i].setIConst(unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(static_cast<unsigned int>( + static_cast<int>(unionArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + case EOpLogicalNot: // this code is written for possible future use, // will not get executed currently diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h index ec440da010..32c70f4671 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -45,6 +45,7 @@ enum TOperator // EOpNegative, + EOpPositive, EOpLogicalNot, EOpVectorLogicalNot, @@ -265,6 +266,7 @@ class TIntermTyped : public TIntermNode virtual bool hasSideEffects() const = 0; void setType(const TType &t) { mType = t; } + void setTypePreservePrecision(const TType &t); const TType &getType() const { return mType; } TType *getTypePointer() { return &mType; } @@ -613,6 +615,9 @@ class TIntermAggregate : public TIntermOperator virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; + void setPrecisionFromChildren(); + void setBuiltInFunctionPrecision(); + protected: TIntermAggregate(const TIntermAggregate &); // disallow copy constructor TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index ef4f83307c..e558683c55 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -198,6 +198,7 @@ TIntermTyped *TIntermediate::addUnaryMath( case EOpPostDecrement: case EOpPreDecrement: case EOpNegative: + case EOpPositive: if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) { diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index 6d07cccc04..ed590967b1 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -395,6 +395,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) switch (node->getOp()) { case EOpNegative: preString = "(-"; break; + case EOpPositive: preString = "(+"; break; case EOpVectorLogicalNot: preString = "not("; break; case EOpLogicalNot: preString = "(!"; break; @@ -574,7 +575,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) // Function declaration. ASSERT(visit == PreVisit); writeVariableType(node->getType()); - out << " " << hashName(node->getName()); + out << " " << hashFunctionName(node->getName()); out << "("; writeFunctionParameters(*(node->getSequence())); @@ -649,17 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) mDeclaringVariables = false; } break; - case EOpInvariantDeclaration: { - // Invariant declaration. - ASSERT(visit == PreVisit); + case EOpInvariantDeclaration: + // Invariant declaration. + ASSERT(visit == PreVisit); + { const TIntermSequence *sequence = node->getSequence(); ASSERT(sequence && sequence->size() == 1); const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); ASSERT(symbol); - out << "invariant " << symbol->getSymbol() << ";"; - visitChildren = false; - break; + out << "invariant " << hashVariableName(symbol->getSymbol()); } + visitChildren = false; + break; case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; @@ -741,7 +743,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); break; case EOpComma: - writeTriplet(visit, NULL, ", ", NULL); + writeTriplet(visit, "(", ", ", ")"); break; case EOpMod: diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index a5ea71599d..30bbbff0f5 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -135,6 +135,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) mUniqueIndex = 0; mContainsLoopDiscontinuity = false; + mContainsAnyLoop = false; mOutputLod0Function = false; mInsideDiscontinuousLoop = false; mNestedLoopDepth = 0; @@ -172,6 +173,7 @@ OutputHLSL::~OutputHLSL() void OutputHLSL::output() { mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + mContainsAnyLoop = containsAnyLoop(mContext.treeRoot); const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot); makeFlaggedStructMaps(flaggedStructs); @@ -320,14 +322,22 @@ void OutputHLSL::header() if (mUsesDiscardRewriting) { - out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; + out << "#define ANGLE_USES_DISCARD_REWRITING\n"; } if (mUsesNestedBreak) { - out << "#define ANGLE_USES_NESTED_BREAK" << "\n"; + out << "#define ANGLE_USES_NESTED_BREAK\n"; } + out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" + "#define LOOP [loop]\n" + "#define FLATTEN [flatten]\n" + "#else\n" + "#define LOOP\n" + "#define FLATTEN\n" + "#endif\n"; + if (mContext.shaderType == GL_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); @@ -1747,6 +1757,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) switch (node->getOp()) { case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; + case EOpPositive: outputTriplet(visit, "(+", "", ")"); break; case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; @@ -1860,15 +1871,20 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration { - if (!mInsideFunction) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { - out << "static "; - } + if (isSingleStatement(*sit)) + { + mUnfoldShortCircuit->traverse(*sit); + } - out << TypeString(variable->getType()) + " "; + if (!mInsideFunction) + { + out << "static "; + } + + out << TypeString(variable->getType()) + " "; - for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) - { TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); if (symbol) @@ -1884,7 +1900,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (*sit != sequence->back()) { - out << ", "; + out << ";\n"; } } } @@ -1925,7 +1941,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpPrototype: if (visit == PreVisit) { - out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); + out << TypeString(node->getType()) << " " << Decorate(TFunction::unmangleName(node->getName())) << (mOutputLod0Function ? "Lod0(" : "("); TIntermSequence *arguments = node->getSequence(); @@ -2287,6 +2303,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { mUnfoldShortCircuit->traverse(node->getCondition()); + // D3D errors when there is a gradient operation in a loop in an unflattened if + // however flattening all the ifs in branch heavy shaders made D3D error too. + // As a temporary workaround we flatten the ifs only if there is at least a loop + // present somewhere in the shader. + if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop) + { + out << "FLATTEN "; + } + out << "if ("; node->getCondition()->traverse(this); @@ -2367,14 +2392,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) if (node->getType() == ELoopDoWhile) { - out << "{do\n"; + out << "{LOOP do\n"; outputLineDirective(node->getLine().first_line); out << "{\n"; } else { - out << "{for("; + out << "{LOOP for("; if (node->getInit()) { @@ -2503,6 +2528,12 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node) { return false; } + else if (aggregate->getOp() == EOpDeclaration) + { + // Declaring multiple comma-separated variables must be considered multiple statements + // because each individual declaration has side effects which are visible in the next. + return false; + } else { for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++) @@ -2675,7 +2706,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) // for(int index = initial; index < clampedLimit; index += increment) - out << "for("; + out << "LOOP for("; index->traverse(this); out << " = "; out << initial; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index bec02479bb..5525e6eaa6 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -144,6 +144,7 @@ class OutputHLSL : public TIntermTraverser int mUniqueIndex; // For creating unique names bool mContainsLoopDiscontinuity; + bool mContainsAnyLoop; bool mOutputLod0Function; bool mInsideDiscontinuousLoop; int mNestedLoopDepth; diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index ff0a49667c..37969b5468 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -1004,12 +1004,12 @@ void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char* directiveHandler.handleExtension(srcLoc, extName, behavior); } -void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value) +void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl) { pp::SourceLocation srcLoc; srcLoc.file = loc.first_file; srcLoc.line = loc.first_line; - directiveHandler.handlePragma(srcLoc, name, value); + directiveHandler.handlePragma(srcLoc, name, value, stdgl); } ///////////////////////////////////////////////////////////////////////////////// @@ -1364,11 +1364,18 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv { error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); recover(); - return NULL; } else { + const TString kGlFrontFacing("gl_FrontFacing"); + if (*identifier == kGlFrontFacing) + { + error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str()); + recover(); + return NULL; + } + symbolTable.addInvariantVarying(*identifier); const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); ASSERT(variable); const TType &type = variable->getType(); diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index 1f4cbdeba9..414c475cbb 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -116,7 +116,7 @@ struct TParseContext { bool supportsExtension(const char* extension); bool isExtensionEnabled(const char* extension) const; void handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior); - void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value); + void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl); bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h index 2f744123b8..4a930a2962 100644 --- a/src/3rdparty/angle/src/compiler/translator/Pragma.h +++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h @@ -7,13 +7,23 @@ #ifndef COMPILER_PRAGMA_H_ #define COMPILER_PRAGMA_H_ -struct TPragma { +struct TPragma +{ + struct STDGL + { + STDGL() : invariantAll(false) { } + + bool invariantAll; + }; + + // By default optimization is turned on and debug is turned off. TPragma() : optimize(true), debug(false) { } TPragma(bool o, bool d) : optimize(o), debug(d) { } bool optimize; bool debug; + STDGL stdgl; }; #endif // COMPILER_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 20ce71605c..0d6a1d64cf 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -37,72 +37,6 @@ bool isInitialized = false; // and the shading language compiler. // -static bool CheckVariableMaxLengths(const ShHandle handle, - size_t expectedValue) -{ - size_t activeUniformLimit = 0; - ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); - size_t activeAttribLimit = 0; - ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); - size_t varyingLimit = 0; - ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); - return (expectedValue == activeUniformLimit && - expectedValue == activeAttribLimit && - expectedValue == varyingLimit); -} - -bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) -{ - size_t mappedNameMaxLength = 0; - ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); - return (expectedValue == mappedNameMaxLength); -} - -template <typename VarT> -const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index) -{ - if (index < 0 || static_cast<size_t>(index) >= infoList.size()) - { - return NULL; - } - - return &infoList[index]; -} - -const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) -{ - switch (varType) - { - case SH_ACTIVE_ATTRIBUTES: - return ReturnVariable(compiler->getAttributes(), index); - case SH_ACTIVE_UNIFORMS: - return ReturnVariable(compiler->getExpandedUniforms(), index); - case SH_VARYINGS: - return ReturnVariable(compiler->getExpandedVaryings(), index); - default: - UNREACHABLE(); - return NULL; - } -} - -ShPrecisionType ConvertPrecision(sh::GLenum precision) -{ - switch (precision) - { - case GL_HIGH_FLOAT: - case GL_HIGH_INT: - return SH_PRECISION_HIGHP; - case GL_MEDIUM_FLOAT: - case GL_MEDIUM_INT: - return SH_PRECISION_MEDIUMP; - case GL_LOW_FLOAT: - case GL_LOW_INT: - return SH_PRECISION_LOWP; - default: - return SH_PRECISION_UNDEFINED; - } -} - template <typename VarT> const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); @@ -150,32 +84,48 @@ const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariabl return GetVariableList<VarT>(compiler, variableType); } +TCompiler *GetCompilerFromHandle(ShHandle handle) +{ + if (!handle) + return NULL; + TShHandleBase *base = static_cast<TShHandleBase *>(handle); + return base->getAsCompiler(); } +TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) +{ + if (!handle) + return NULL; + TShHandleBase *base = static_cast<TShHandleBase *>(handle); + return base->getAsTranslatorHLSL(); +} + +} // namespace anonymous + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. // -int ShInitialize() +bool ShInitialize() { if (!isInitialized) { isInitialized = InitProcess(); } - return isInitialized ? 1 : 0; + return isInitialized; } // // Cleanup symbol tables // -int ShFinalize() +bool ShFinalize() { if (isInitialized) { DetachProcess(); isInitialized = false; } - return 1; + return true; } // @@ -183,6 +133,9 @@ int ShFinalize() // void ShInitBuiltInResources(ShBuiltInResources* resources) { + // Make comparable. + memset(resources, 0, sizeof(*resources)); + // Constants. resources->MaxVertexAttribs = 8; resources->MaxVertexUniformVectors = 128; @@ -201,6 +154,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->EXT_frag_depth = 0; resources->EXT_shader_texture_lod = 0; + resources->NV_draw_buffers = 0; + // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; @@ -251,23 +206,13 @@ void ShDestruct(ShHandle handle) DeleteCompiler(base->getAsCompiler()); } -void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString) +const std::string &ShGetBuiltInResourcesString(const ShHandle handle) { - if (!handle || !outString) - { - return; - } - - TShHandleBase *base = static_cast<TShHandleBase*>(handle); - TCompiler *compiler = base->getAsCompiler(); - if (!compiler) - { - return; - } - - strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen); - outString[outStringLen - 1] = '\0'; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getBuiltInResourcesString(); } + // // Do an actual compile on the given strings. The result is left // in the given compile object. @@ -275,219 +220,62 @@ void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, cha // Return: The return value of ShCompile is really boolean, indicating // success or failure. // -int ShCompile( +bool ShCompile( const ShHandle handle, - const char* const shaderStrings[], + const char *const shaderStrings[], size_t numStrings, int compileOptions) { - if (handle == 0) - return 0; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); - TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return 0; - - bool success = compiler->compile(shaderStrings, numStrings, compileOptions); - return success ? 1 : 0; + return compiler->compile(shaderStrings, numStrings, compileOptions); } -void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) +int ShGetShaderVersion(const ShHandle handle) { - if (!handle || !params) - return; - - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; + TCompiler* compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getShaderVersion(); +} - switch(pname) - { - case SH_INFO_LOG_LENGTH: - *params = compiler->getInfoSink().info.size() + 1; - break; - case SH_OBJECT_CODE_LENGTH: - *params = compiler->getInfoSink().obj.size() + 1; - break; - case SH_ACTIVE_UNIFORMS: - *params = compiler->getExpandedUniforms().size(); - break; - case SH_ACTIVE_UNIFORM_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_ACTIVE_ATTRIBUTES: - *params = compiler->getAttributes().size(); - break; - case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_VARYINGS: - *params = compiler->getExpandedVaryings().size(); - break; - case SH_VARYING_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_MAPPED_NAME_MAX_LENGTH: - // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to - // handle array and struct dereferences. - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_NAME_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_HASHED_NAME_MAX_LENGTH: - if (compiler->getHashFunction() == NULL) { - *params = 0; - } else { - // 64 bits hashing output requires 16 bytes for hex - // representation. - const char HashedNamePrefix[] = HASHED_NAME_PREFIX; - (void)HashedNamePrefix; - *params = 16 + sizeof(HashedNamePrefix); - } - break; - case SH_HASHED_NAMES_COUNT: - *params = compiler->getNameMap().size(); - break; - case SH_SHADER_VERSION: - *params = compiler->getShaderVersion(); - break; - case SH_RESOURCES_STRING_LENGTH: - *params = compiler->getBuiltInResourcesString().length() + 1; - break; - case SH_OUTPUT_TYPE: - *params = compiler->getOutputType(); - break; - default: UNREACHABLE(); - } +ShShaderOutput ShGetShaderOutputType(const ShHandle handle) +{ + TCompiler* compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getOutputType(); } // // Return any compiler log of messages for the application. // -void ShGetInfoLog(const ShHandle handle, char* infoLog) +const std::string &ShGetInfoLog(const ShHandle handle) { - if (!handle || !infoLog) - return; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - TInfoSink& infoSink = compiler->getInfoSink(); - strcpy(infoLog, infoSink.info.c_str()); + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.info.str(); } // // Return any object code. // -void ShGetObjectCode(const ShHandle handle, char* objCode) +const std::string &ShGetObjectCode(const ShHandle handle) { - if (!handle || !objCode) - return; - - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - TInfoSink& infoSink = compiler->getInfoSink(); - strcpy(objCode, infoSink.obj.c_str()); -} - -void ShGetVariableInfo(const ShHandle handle, - ShShaderInfo varType, - int index, - size_t* length, - int* size, - sh::GLenum* type, - ShPrecisionType* precision, - int* staticUse, - char* name, - char* mappedName) -{ - if (!handle || !size || !type || !precision || !staticUse || !name) - return; - ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || - (varType == SH_ACTIVE_UNIFORMS) || - (varType == SH_VARYINGS)); - - TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return; - - const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index); - if (!varInfo) - { - return; - } + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); - if (length) *length = varInfo->name.size(); - *size = varInfo->elementCount(); - *type = varInfo->type; - *precision = ConvertPrecision(varInfo->precision); - *staticUse = varInfo->staticUse ? 1 : 0; - - // This size must match that queried by - // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH - // in ShGetInfo, below. - size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(CheckVariableMaxLengths(handle, variableLength)); - strncpy(name, varInfo->name.c_str(), variableLength); - name[variableLength - 1] = 0; - if (mappedName) - { - // This size must match that queried by - // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); - mappedName[maxMappedNameLength - 1] = 0; - } + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.obj.str(); } -void ShGetNameHashingEntry(const ShHandle handle, - int index, - char* name, - char* hashedName) +const std::map<std::string, std::string> *ShGetNameHashingMap( + const ShHandle handle) { - if (!handle || !name || !hashedName || index < 0) - return; - - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - const NameMap& nameMap = compiler->getNameMap(); - if (index >= static_cast<int>(nameMap.size())) - return; - - NameMap::const_iterator it = nameMap.begin(); - for (int i = 0; i < index; ++i) - ++it; - - size_t len = it->first.length() + 1; - size_t max_len = 0; - ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); - if (len > max_len) { - ASSERT(false); - len = max_len; - } - strncpy(name, it->first.c_str(), len); - // To be on the safe side in case the source is longer than expected. - name[len - 1] = '\0'; - - len = it->second.length() + 1; - max_len = 0; - ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); - if (len > max_len) { - ASSERT(false); - len = max_len; - } - strncpy(hashedName, it->second.c_str(), len); - // To be on the safe side in case the source is longer than expected. - hashedName[len - 1] = '\0'; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return &(compiler->getNameMap()); } const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle) @@ -515,11 +303,11 @@ const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handl return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK); } -int ShCheckVariablesWithinPackingLimits( - int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) +bool ShCheckVariablesWithinPackingLimits( + int maxVectors, ShVariableInfo *varInfoArray, size_t varInfoArraySize) { if (varInfoArraySize == 0) - return 1; + return true; ASSERT(varInfoArray); std::vector<sh::ShaderVariable> variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) @@ -528,24 +316,17 @@ int ShCheckVariablesWithinPackingLimits( variables.push_back(var); } VariablePacker packer; - return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; + return packer.CheckVariablesWithinPackingLimits(maxVectors, variables); } bool ShGetInterfaceBlockRegister(const ShHandle handle, - const char *interfaceBlockName, + const std::string &interfaceBlockName, unsigned int *indexOut) { - if (!handle || !interfaceBlockName || !indexOut) - { - return false; - } + ASSERT(indexOut); - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) - { - return false; - } + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); if (!translator->hasInterfaceBlock(interfaceBlockName)) { @@ -557,20 +338,12 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle, } bool ShGetUniformRegister(const ShHandle handle, - const char *uniformName, + const std::string &uniformName, unsigned int *indexOut) { - if (!handle || !uniformName || !indexOut) - { - return false; - } - - TShHandleBase* base = static_cast<TShHandleBase*>(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) - { - return false; - } + ASSERT(indexOut); + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); if (!translator->hasUniform(uniformName)) { diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp index 822c558c9b..3098a7f0c9 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -9,6 +9,8 @@ #include <GLSLANG/ShaderLang.h> +#include "compiler/translator/compilerdebug.h" + namespace sh { @@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) return *this; } +bool ShaderVariable::operator==(const ShaderVariable &other) const +{ + if (type != other.type || + precision != other.precision || + name != other.name || + mappedName != other.mappedName || + arraySize != other.arraySize || + staticUse != other.staticUse || + fields.size() != other.fields.size() || + structName != other.structName) + { + return false; + } + for (size_t ii = 0; ii < fields.size(); ++ii) + { + if (fields[ii] != other.fields[ii]) + return false; + } + return true; +} + +bool ShaderVariable::findInfoByMappedName( + const std::string &mappedFullName, + const ShaderVariable **leafVar, std::string *originalFullName) const +{ + ASSERT(leafVar && originalFullName); + // There are three cases: + // 1) the top variable is of struct type; + // 2) the top variable is an array; + // 3) otherwise. + size_t pos = mappedFullName.find_first_of(".["); + std::string topName; + + if (pos == std::string::npos) + { + // Case 3. + if (mappedFullName != this->mappedName) + return false; + *originalFullName = this->name; + *leafVar = this; + return true; + } + else + { + std::string topName = mappedFullName.substr(0, pos); + if (topName != this->mappedName) + return false; + std::string originalName = this->name; + std::string remaining; + if (mappedFullName[pos] == '[') + { + // Case 2. + size_t closePos = mappedFullName.find_first_of(']'); + if (closePos < pos || closePos == std::string::npos) + return false; + // Append '[index]'. + originalName += mappedFullName.substr(pos, closePos - pos + 1); + if (closePos + 1 == mappedFullName.size()) + { + *originalFullName = originalName; + *leafVar = this; + return true; + } + else + { + // In the form of 'a[0].b', so after ']', '.' is expected. + if (mappedFullName[closePos + 1] != '.') + return false; + remaining = mappedFullName.substr(closePos + 2); // Skip "]." + } + } + else + { + // Case 1. + remaining = mappedFullName.substr(pos + 1); // Skip "." + } + for (size_t ii = 0; ii < this->fields.size(); ++ii) + { + const ShaderVariable *fieldVar = NULL; + std::string originalFieldName; + bool found = fields[ii].findInfoByMappedName( + remaining, &fieldVar, &originalFieldName); + if (found) + { + *originalFullName = originalName + "." + originalFieldName; + *leafVar = fieldVar; + return true; + } + } + return false; + } +} + +bool ShaderVariable::isSameVariableAtLinkTime( + const ShaderVariable &other, bool matchPrecision) const +{ + if (type != other.type) + return false; + if (matchPrecision && precision != other.precision) + return false; + if (name != other.name) + return false; + ASSERT(mappedName == other.mappedName); + if (arraySize != other.arraySize) + return false; + if (fields.size() != other.fields.size()) + return false; + for (size_t ii = 0; ii < fields.size(); ++ii) + { + if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], + matchPrecision)) + { + return false; + } + } + if (structName != other.structName) + return false; + return true; +} + Uniform::Uniform() {} @@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other) return *this; } +bool Uniform::operator==(const Uniform &other) const +{ + return ShaderVariable::operator==(other); +} + +bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const +{ + return ShaderVariable::isSameVariableAtLinkTime(other, true); +} + Attribute::Attribute() : location(-1) {} @@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other) return *this; } +bool Attribute::operator==(const Attribute &other) const +{ + return (ShaderVariable::operator==(other) && + location == other.location); +} + InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false) {} @@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o return *this; } +bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const +{ + return (ShaderVariable::operator==(other) && + isRowMajorLayout == other.isRowMajorLayout); +} + +bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime( + const InterfaceBlockField &other) const +{ + return (ShaderVariable::isSameVariableAtLinkTime(other, true) && + isRowMajorLayout == other.isRowMajorLayout); +} + Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false) @@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other) return *this; } +bool Varying::operator==(const Varying &other) const +{ + return (ShaderVariable::operator==(other) && + interpolation == other.interpolation && + isInvariant == other.isInvariant); +} + +bool Varying::isSameVaryingAtLinkTime(const Varying &other) const +{ + return (ShaderVariable::isSameVariableAtLinkTime(other, false) && + interpolation == other.interpolation && + isInvariant == other.isInvariant); +} + InterfaceBlock::InterfaceBlock() : arraySize(0), layout(BLOCKLAYOUT_PACKED), diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index 6b0e0c0a03..9cd74218dc 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -31,6 +31,7 @@ // #include <assert.h> +#include <set> #include "common/angleutils.h" #include "compiler/translator/InfoSink.h" @@ -299,19 +300,21 @@ class TSymbolTableLevel tLevel level; }; -enum ESymbolLevel -{ - COMMON_BUILTINS = 0, - ESSL1_BUILTINS = 1, - ESSL3_BUILTINS = 2, - LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, - GLOBAL_LEVEL = 3 -}; +// Define ESymbolLevel as int rather than an enum since level can go +// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the +// compiler optimizes the >= of the last element to ==. +typedef int ESymbolLevel; +const int COMMON_BUILTINS = 0; +const int ESSL1_BUILTINS = 1; +const int ESSL3_BUILTINS = 2; +const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS; +const int GLOBAL_LEVEL = 3; class TSymbolTable { public: TSymbolTable() + : mGlobalInvariant(false) { // The symbol table cannot be used until push() is called, but // the lack of an initial call to push() can be used to detect @@ -408,6 +411,25 @@ class TSymbolTable // for the specified TBasicType TPrecision getDefaultPrecision(TBasicType type) const; + // This records invariant varyings declared through + // "invariant varying_name;". + void addInvariantVarying(const TString &originalName) + { + mInvariantVaryings.insert(originalName); + } + // If this returns false, the varying could still be invariant + // if it is set as invariant during the varying variable + // declaration - this piece of information is stored in the + // variable's type, not here. + bool isVaryingInvariant(const TString &originalName) const + { + return (mGlobalInvariant || + mInvariantVaryings.count(originalName) > 0); + } + + void setGlobalInvariant() { mGlobalInvariant = true; } + bool getGlobalInvariant() const { return mGlobalInvariant; } + static int nextUniqueId() { return ++uniqueIdCounter; @@ -423,6 +445,9 @@ class TSymbolTable typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; std::vector< PrecisionStackLevel *> precisionStack; + std::set<TString> mInvariantVaryings; + bool mGlobalInvariant; + static int uniqueIdCounter; }; diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp index 5b99fea948..dcbf3cea1d 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -16,6 +16,8 @@ TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) void TranslatorESSL::translate(TIntermNode* root) { TInfoSinkBase& sink = getInfoSink().obj; + writePragma(); + // Write built-in extension behaviors. writeExtensionBehavior(); @@ -37,8 +39,13 @@ void TranslatorESSL::writeExtensionBehavior() { for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter) { if (iter->second != EBhUndefined) { - sink << "#extension " << iter->first << " : " - << getBehaviorString(iter->second) << "\n"; + if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") { + sink << "#extension GL_NV_draw_buffers : " + << getBehaviorString(iter->second) << "\n"; + } else { + sink << "#extension " << iter->first << " : " + << getBehaviorString(iter->second) << "\n"; + } } } } diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp index 4b2aecab33..6acbf7c5a8 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -9,18 +9,6 @@ #include "compiler/translator/OutputGLSL.h" #include "compiler/translator/VersionGLSL.h" -static void writeVersion(sh::GLenum type, TIntermNode* root, - TInfoSinkBase& sink) { - TVersionGLSL versionGLSL(type); - root->traverse(&versionGLSL); - int version = versionGLSL.getVersion(); - // We need to write version directive only if it is greater than 110. - // If there is no version directive in the shader, 110 is implied. - if (version > 110) { - sink << "#version " << version << "\n"; - } -} - TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec) : TCompiler(type, spec, SH_GLSL_OUTPUT) { } @@ -29,7 +17,9 @@ void TranslatorGLSL::translate(TIntermNode* root) { TInfoSinkBase& sink = getInfoSink().obj; // Write GLSL version. - writeVersion(getShaderType(), root, sink); + writeVersion(root); + + writePragma(); // Write extension behaviour as needed writeExtensionBehavior(); @@ -46,6 +36,20 @@ void TranslatorGLSL::translate(TIntermNode* root) { root->traverse(&outputGLSL); } +void TranslatorGLSL::writeVersion(TIntermNode *root) +{ + TVersionGLSL versionGLSL(getShaderType(), getPragma()); + root->traverse(&versionGLSL); + int version = versionGLSL.getVersion(); + // We need to write version directive only if it is greater than 110. + // If there is no version directive in the shader, 110 is implied. + if (version > 110) + { + TInfoSinkBase& sink = getInfoSink().obj; + sink << "#version " << version << "\n"; + } +} + void TranslatorGLSL::writeExtensionBehavior() { TInfoSinkBase& sink = getInfoSink().obj; const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h index 3c6c2e426a..766d8d910e 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -9,14 +9,16 @@ #include "compiler/translator/Compiler.h" -class TranslatorGLSL : public TCompiler { -public: +class TranslatorGLSL : public TCompiler +{ + public: TranslatorGLSL(sh::GLenum type, ShShaderSpec spec); -protected: - virtual void translate(TIntermNode* root); + protected: + virtual void translate(TIntermNode *root); -private: + private: + void writeVersion(TIntermNode *root); void writeExtensionBehavior(); }; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp index c1a7b7524f..896e1cd7a0 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -94,6 +94,7 @@ const char *GetOperatorString(TOperator op) case EOpLogicalXor: return "^^"; case EOpLogicalAnd: return "&&"; case EOpNegative: return "-"; + case EOpPositive: return "+"; case EOpVectorLogicalNot: return "not"; case EOpLogicalNot: return "!"; case EOpPostIncrement: return "++"; diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index f26c1566ac..d8e13788b7 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -5,6 +5,7 @@ // #include "angle_gl.h" +#include "compiler/translator/SymbolTable.h" #include "compiler/translator/VariableInfo.h" #include "compiler/translator/util.h" #include "common/utilities.h" @@ -131,7 +132,8 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs, std::vector<sh::Uniform> *uniforms, std::vector<sh::Varying> *varyings, std::vector<sh::InterfaceBlock> *interfaceBlocks, - ShHashFunction64 hashFunction) + ShHashFunction64 hashFunction, + const TSymbolTable &symbolTable) : mAttribs(attribs), mOutputVariables(outputVariables), mUniforms(uniforms), @@ -140,7 +142,10 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs, mPointCoordAdded(false), mFrontFacingAdded(false), mFragCoordAdded(false), - mHashFunction(hashFunction) + mPositionAdded(false), + mPointSizeAdded(false), + mHashFunction(hashFunction), + mSymbolTable(symbolTable) { } @@ -200,12 +205,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) if (!mFragCoordAdded) { Varying info; - info.name = "gl_FragCoord"; - info.mappedName = "gl_FragCoord"; + const char kName[] = "gl_FragCoord"; + info.name = kName; + info.mappedName = kName; info.type = GL_FLOAT_VEC4; info.arraySize = 0; - info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); mVaryings->push_back(info); mFragCoordAdded = true; } @@ -214,12 +221,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) if (!mFrontFacingAdded) { Varying info; - info.name = "gl_FrontFacing"; - info.mappedName = "gl_FrontFacing"; + const char kName[] = "gl_FrontFacing"; + info.name = kName; + info.mappedName = kName; info.type = GL_BOOL; info.arraySize = 0; info.precision = GL_NONE; info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); mVaryings->push_back(info); mFrontFacingAdded = true; } @@ -228,16 +237,50 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) if (!mPointCoordAdded) { Varying info; - info.name = "gl_PointCoord"; - info.mappedName = "gl_PointCoord"; + const char kName[] = "gl_PointCoord"; + info.name = kName; + info.mappedName = kName; info.type = GL_FLOAT_VEC2; info.arraySize = 0; - info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); mVaryings->push_back(info); mPointCoordAdded = true; } return; + case EvqPosition: + if (!mPositionAdded) + { + Varying info; + const char kName[] = "gl_Position"; + info.name = kName; + info.mappedName = kName; + info.type = GL_FLOAT_VEC4; + info.arraySize = 0; + info.precision = GL_HIGH_FLOAT; // Defined by spec. + info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); + mVaryings->push_back(info); + mPositionAdded = true; + } + return; + case EvqPointSize: + if (!mPointSizeAdded) + { + Varying info; + const char kName[] = "gl_PointSize"; + info.name = kName; + info.mappedName = kName; + info.type = GL_FLOAT; + info.arraySize = 0; + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. + info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); + mVaryings->push_back(info); + mPointSizeAdded = true; + } + return; default: break; } @@ -251,8 +294,10 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) class NameHashingTraverser : public GetVariableTraverser { public: - NameHashingTraverser(ShHashFunction64 hashFunction) - : mHashFunction(hashFunction) + NameHashingTraverser(ShHashFunction64 hashFunction, + const TSymbolTable &symbolTable) + : GetVariableTraverser(symbolTable), + mHashFunction(hashFunction) {} private: @@ -312,7 +357,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field); const TType &fieldType = *field.type(); - GetVariableTraverser traverser; + GetVariableTraverser traverser(mSymbolTable); traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields); interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); @@ -325,7 +370,7 @@ template <typename VarT> void CollectVariables::visitVariable(const TIntermSymbol *variable, std::vector<VarT> *infoList) const { - NameHashingTraverser traverser(mHashFunction); + NameHashingTraverser traverser(mHashFunction, mSymbolTable); traverser.traverse(variable->getType(), variable->getSymbol(), infoList); } @@ -421,9 +466,8 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) return true; } -template <typename VarT> -void ExpandVariables(const std::vector<VarT> &compact, - std::vector<ShaderVariable> *expanded) +void ExpandUniforms(const std::vector<Uniform> &compact, + std::vector<ShaderVariable> *expanded) { for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) { @@ -432,7 +476,4 @@ void ExpandVariables(const std::vector<VarT> &compact, } } -template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *); -template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *); - } diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 5ac4c46baa..92d376d879 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -11,6 +11,8 @@ #include "compiler/translator/IntermNode.h" +class TSymbolTable; + namespace sh { @@ -23,7 +25,8 @@ class CollectVariables : public TIntermTraverser std::vector<Uniform> *uniforms, std::vector<Varying> *varyings, std::vector<InterfaceBlock> *interfaceBlocks, - ShHashFunction64 hashFunction); + ShHashFunction64 hashFunction, + const TSymbolTable &symbolTable); virtual void visitSymbol(TIntermSymbol *symbol); virtual bool visitAggregate(Visit, TIntermAggregate *node); @@ -48,13 +51,17 @@ class CollectVariables : public TIntermTraverser bool mFrontFacingAdded; bool mFragCoordAdded; + bool mPositionAdded; + bool mPointSizeAdded; + ShHashFunction64 mHashFunction; + + const TSymbolTable &mSymbolTable; }; -// Expand struct variables to flattened lists of split variables -template <typename VarT> -void ExpandVariables(const std::vector<VarT> &compact, - std::vector<ShaderVariable> *expanded); +// Expand struct uniforms to flattened lists of split variables +void ExpandUniforms(const std::vector<Uniform> &compact, + std::vector<ShaderVariable> *expanded); } diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 8edbd009b0..05b111a7a7 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -26,18 +26,12 @@ static const int GLSL_VERSION_120 = 120; // GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that // are built-in types, entire structures or arrays... are all l-values." // -// TODO(alokp): The following two cases of invariant decalaration get lost -// during parsing - they do not get carried over to the intermediate tree. -// Handle these cases: -// 1. When a pragma is used to force all output variables to be invariant: -// - #pragma STDGL invariant(all) -// 2. When a previously decalared or built-in variable is marked invariant: -// - invariant gl_Position; -// - varying vec3 color; invariant color; -// -TVersionGLSL::TVersionGLSL(sh::GLenum type) - : mVersion(GLSL_VERSION_110) +TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma) { + if (pragma.stdgl.invariantAll) + mVersion = GLSL_VERSION_120; + else + mVersion = GLSL_VERSION_110; } void TVersionGLSL::visitSymbol(TIntermSymbol *node) diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index 30f5a138a0..72368e39d6 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -9,6 +9,8 @@ #include "compiler/translator/IntermNode.h" +#include "compiler/translator/Pragma.h" + // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. // GLSL 1.1 which is mandated by OpenGL 2.0 provides: @@ -27,7 +29,7 @@ class TVersionGLSL : public TIntermTraverser { public: - TVersionGLSL(sh::GLenum type); + TVersionGLSL(sh::GLenum type, const TPragma &pragma); // Returns 120 if the following is used the shader: // - "invariant", diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index 5c945ad5ad..e271de978c 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -354,6 +354,15 @@ function_call // Treat it like a built-in unary operator. // $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1); + const TType& returnType = fnCandidate->getReturnType(); + if (returnType.getBasicType() == EbtBool) { + // Bool types should not have precision, so we'll override any precision + // that might have been set by addUnaryMath. + $$->setType(returnType); + } else { + // addUnaryMath has set the precision of the node based on the operand. + $$->setTypePreservePrecision(returnType); + } if ($$ == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString(); @@ -362,20 +371,29 @@ function_call YYERROR; } } else { - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); + TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); + aggregate->setType(fnCandidate->getReturnType()); + aggregate->setPrecisionFromChildren(); + $$ = aggregate; } } else { // This is a real function call - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); - $$->setType(fnCandidate->getReturnType()); + TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); + aggregate->setType(fnCandidate->getReturnType()); // this is how we know whether the given function is a builtIn function or a user defined function // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also // if builtIn == true, it's definitely a builtIn function with EOpNull if (!builtIn) - $$->getAsAggregate()->setUserDefined(); - $$->getAsAggregate()->setName(fnCandidate->getMangledName()); + aggregate->setUserDefined(); + aggregate->setName(fnCandidate->getMangledName()); + + // This needs to happen after the name is set + if (builtIn) + aggregate->setBuiltInFunctionPrecision(); + + $$ = aggregate; TQualifier qual; for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { @@ -388,7 +406,6 @@ function_call } } } - $$->setType(fnCandidate->getReturnType()); } else { // error message was put out by PaFindFunction() // Put on a dummy node for error recovery @@ -500,6 +517,7 @@ unary_expression const char* errorOp = ""; switch($1.op) { case EOpNegative: errorOp = "-"; break; + case EOpPositive: errorOp = "+"; break; case EOpLogicalNot: errorOp = "!"; break; default: break; } @@ -514,7 +532,7 @@ unary_expression // Grammar Note: No traditional style type casts. unary_operator - : PLUS { $$.op = EOpNull; } + : PLUS { $$.op = EOpPositive; } | DASH { $$.op = EOpNegative; } | BANG { $$.op = EOpLogicalNot; } ; @@ -762,7 +780,7 @@ declaration TIntermAggregate *prototype = new TIntermAggregate; prototype->setType(function.getReturnType()); - prototype->setName(function.getName()); + prototype->setName(function.getMangledName()); for (size_t i = 0; i < function.getParamCount(); i++) { diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index 56340c6f9e..00780f0454 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -62,7 +62,9 @@ TString TType::getCompleteString() const TStringStream stream; if (qualifier != EvqTemporary && qualifier != EvqGlobal) - stream << getQualifierString() << " " << getPrecisionString() << " "; + stream << getQualifierString() << " "; + if (precision != EbpUndefined) + stream << getPrecisionString() << " "; if (array) stream << "array[" << getArraySize() << "] of "; if (isMatrix()) @@ -221,6 +223,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) switch (node->getOp()) { case EOpNegative: out << "Negate value"; break; + case EOpPositive: out << "Positive sign"; break; case EOpVectorLogicalNot: case EOpLogicalNot: out << "Negate conditional"; break; @@ -292,6 +295,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpFunction: out << "Function Definition: " << node->getName(); break; case EOpFunctionCall: out << "Function Call: " << node->getName(); break; case EOpParameters: out << "Function Parameters: "; break; + case EOpPrototype: out << "Function Prototype: " << node->getName(); break; case EOpConstructFloat: out << "Construct float"; break; case EOpConstructVec2: out << "Construct vec2"; break; diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index f74c7d1173..8cc06a658a 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -9,6 +9,7 @@ #include <limits> #include "compiler/preprocessor/numeric_lex.h" +#include "compiler/translator/SymbolTable.h" #include "common/utilities.h" bool atof_clamp(const char *str, float *value) @@ -281,8 +282,47 @@ InterpolationType GetInterpolationType(TQualifier qualifier) } } +GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable) + : mSymbolTable(symbolTable) +{ +} + +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, InterfaceBlockField *variable); +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, ShaderVariable *variable); +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, Uniform *variable); + +template<> +void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, Varying *variable) +{ + ASSERT(variable); + switch (type.getQualifier()) + { + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: + variable->isInvariant = true; + break; + case EvqVaryingIn: + case EvqVaryingOut: + if (mSymbolTable.isVaryingInvariant(name)) + { + variable->isInvariant = true; + } + break; + default: + break; + } + + variable->interpolation = GetInterpolationType(type.getQualifier()); +} + template <typename VarT> -void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output) +void GetVariableTraverser::traverse(const TType &type, + const TString &name, + std::vector<VarT> *output) { const TStructure *structure = type.getStruct(); @@ -309,15 +349,16 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name, std: traverse(*field->type(), field->name(), &variable.fields); } } - + setTypeSpecificInfo(type, name, &variable); visitVariable(&variable); ASSERT(output); output->push_back(variable); } +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *); -template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *); } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index 241e2cc1c2..fb5308759e 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -24,6 +24,8 @@ extern bool atof_clamp(const char *str, float *value); // Return false if overflow happens. extern bool atoi_clamp(const char *str, int *value); +class TSymbolTable; + namespace sh { @@ -38,7 +40,7 @@ TString ArrayString(const TType &type); class GetVariableTraverser { public: - GetVariableTraverser() {} + GetVariableTraverser(const TSymbolTable &symbolTable); template <typename VarT> void traverse(const TType &type, const TString &name, std::vector<VarT> *output); @@ -48,6 +50,14 @@ class GetVariableTraverser virtual void visitVariable(ShaderVariable *newVar) {} private: + // Helper function called by traverse() to fill specific fields + // for attributes/varyings/uniforms. + template <typename VarT> + void setTypeSpecificInfo( + const TType &type, const TString &name, VarT *variable) {} + + const TSymbolTable &mSymbolTable; + DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp new file mode 100644 index 0000000000..28dd3d842e --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libEGL/AttributeMap.h" + +namespace egl +{ + +AttributeMap::AttributeMap() +{ +} + +AttributeMap::AttributeMap(const EGLint *attributes) +{ + for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + insert(curAttrib[0], curAttrib[1]); + } +} + +void AttributeMap::insert(EGLint key, EGLint value) +{ + mAttributes[key] = value; +} + +bool AttributeMap::contains(EGLint key) const +{ + return (mAttributes.find(key) != mAttributes.end()); +} + +EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const +{ + std::map<EGLint, EGLint>::const_iterator iter = mAttributes.find(key); + return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue; +} + +} diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.h b/src/3rdparty/angle/src/libEGL/AttributeMap.h new file mode 100644 index 0000000000..f2f082fe21 --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/AttributeMap.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBEGL_ATTRIBUTEMAP_H_ +#define LIBEGL_ATTRIBUTEMAP_H_ + +#include <EGL/egl.h> + +#include <map> + +namespace egl +{ + +class AttributeMap +{ + public: + AttributeMap(); + explicit AttributeMap(const EGLint *attributes); + + virtual void insert(EGLint key, EGLint value); + virtual bool contains(EGLint key) const; + virtual EGLint get(EGLint key, EGLint defaultValue) const; + + private: + std::map<EGLint, EGLint> mAttributes; +}; + +} + +#endif // LIBEGL_ATTRIBUTEMAP_H_ diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index 5a50e4baf5..eea93b1d87 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -35,32 +35,36 @@ static DisplayMap *GetDisplayMap() return &displays; } -egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType) +egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap) { + Display *display = NULL; + DisplayMap *displays = GetDisplayMap(); DisplayMap::const_iterator iter = displays->find(displayId); if (iter != displays->end()) { - return iter->second; + display = iter->second; + } + else + { + display = new egl::Display(displayId); + displays->insert(std::make_pair(displayId, display)); } - - // FIXME: Check if displayId is a valid display device context - egl::Display *display = new egl::Display(displayId, displayType); - displays->insert(std::make_pair(displayId, display)); + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + display->setAttributes(attribMap); + } return display; } -Display::Display(EGLNativeDisplayType displayId, EGLint displayType) +Display::Display(EGLNativeDisplayType displayId) : mDisplayId(displayId), - mRequestedDisplayType(displayType), + mAttributeMap(), mRenderer(NULL) { -#if defined(ANGLE_PLATFORM_WINRT) - if (mDisplayId) - mDisplayId->AddRef(); -#endif } Display::~Display() @@ -73,28 +77,29 @@ Display::~Display() { displays->erase(iter); } +} -#if defined(ANGLE_PLATFORM_WINRT) - if (mDisplayId) - mDisplayId->Release(); -#endif +void Display::setAttributes(const AttributeMap &attribMap) +{ + mAttributeMap = attribMap; } -bool Display::initialize() +Error Display::initialize() { if (isInitialized()) { - return true; + return Error(EGL_SUCCESS); } - mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType); + mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap); if (!mRenderer) { terminate(); - return error(EGL_NOT_INITIALIZED, false); + return Error(EGL_NOT_INITIALIZED); } + //TODO(jmadill): should be part of caps? EGLint minSwapInterval = mRenderer->getMinSwapInterval(); EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize; @@ -125,13 +130,13 @@ bool Display::initialize() if (!isInitialized()) { terminate(); - return false; + return Error(EGL_NOT_INITIALIZED); } initDisplayExtensionString(); initVendorString(); - return true; + return Error(EGL_SUCCESS); } void Display::terminate() @@ -148,6 +153,8 @@ void Display::terminate() glDestroyRenderer(mRenderer); mRenderer = NULL; + + mConfigSet.mSet.clear(); } bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) @@ -202,7 +209,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) -EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList) +Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface) { const Config *configuration = mConfigSet.get(config); EGLint postSubBufferSupported = EGL_FALSE; @@ -223,9 +230,9 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co case EGL_BACK_BUFFER: break; case EGL_SINGLE_BUFFER: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported + return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } break; case EGL_POST_SUB_BUFFER_SUPPORTED_NV: @@ -241,11 +248,11 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co fixedSize = attribList[1]; break; case EGL_VG_COLORSPACE: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); case EGL_VG_ALPHA_FORMAT: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } attribList += 2; @@ -254,7 +261,7 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co if (width < 0 || height < 0) { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return Error(EGL_BAD_PARAMETER); } if (!fixedSize) @@ -265,29 +272,33 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co if (hasExistingWindowSurface(window)) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return Error(EGL_BAD_ALLOC); } if (mRenderer->testDeviceLost(false)) { - if (!restoreLostDevice()) - return EGL_NO_SURFACE; + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } } Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported); - - if (!surface->initialize()) + Error error = surface->initialize(); + if (error.isError()) { - delete surface; - return EGL_NO_SURFACE; + SafeDelete(surface); + return error; } mSurfaceSet.insert(surface); - return success(surface); + *outSurface = surface; + return Error(EGL_SUCCESS); } -EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList) +Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface) { EGLint width = 0, height = 0; EGLenum textureFormat = EGL_NO_TEXTURE; @@ -319,7 +330,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, textureFormat = attribList[1]; break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } break; case EGL_TEXTURE_TARGET: @@ -330,19 +341,19 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, textureTarget = attribList[1]; break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } break; case EGL_MIPMAP_TEXTURE: if (attribList[1] != EGL_FALSE) - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); break; case EGL_VG_COLORSPACE: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); case EGL_VG_ALPHA_FORMAT: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } attribList += 2; @@ -351,88 +362,100 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, if (width < 0 || height < 0) { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return Error(EGL_BAD_PARAMETER); } if (width == 0 || height == 0) { - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) { - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); } if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) { - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); } if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) { - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); } if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) || (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)) { - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } if (mRenderer->testDeviceLost(false)) { - if (!restoreLostDevice()) - return EGL_NO_SURFACE; + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } } Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); - - if (!surface->initialize()) + Error error = surface->initialize(); + if (error.isError()) { - delete surface; - return EGL_NO_SURFACE; + SafeDelete(surface); + return error; } mSurfaceSet.insert(surface); - return success(surface); + *outSurface = surface; + return Error(EGL_SUCCESS); } -EGLContext Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess) +Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, + bool robustAccess, EGLContext *outContext) { if (!mRenderer) { - return EGL_NO_CONTEXT; + *outContext = EGL_NO_CONTEXT; + return Error(EGL_SUCCESS); } else if (mRenderer->testDeviceLost(false)) // Lost device { - if (!restoreLostDevice()) + Error error = restoreLostDevice(); + if (error.isError()) { - return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); + return error; } } + //TODO(jmadill): shader model is not cross-platform if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4) { - return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + return Error(EGL_BAD_CONFIG); } gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess); mContextSet.insert(context); - return success(context); + *outContext = context; + return Error(EGL_SUCCESS); } -bool Display::restoreLostDevice() +Error Display::restoreLostDevice() { for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) { if ((*ctx)->isResetNotificationEnabled()) - return false; // If reset notifications have been requested, application must delete all contexts first + { + // If reset notifications have been requested, application must delete all contexts first + return Error(EGL_CONTEXT_LOST); + } } - + // Release surface resources to make the Reset() succeed for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) { @@ -441,16 +464,20 @@ bool Display::restoreLostDevice() if (!mRenderer->resetDevice()) { - return error(EGL_BAD_ALLOC, false); + return Error(EGL_BAD_ALLOC); } // Restore any surfaces that may have been lost for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) { - (*surface)->resetSwapChain(); + Error error = (*surface)->resetSwapChain(); + if (error.isError()) + { + return error; + } } - return true; + return Error(EGL_SUCCESS); } @@ -472,7 +499,6 @@ void Display::notifyDeviceLost() { (*context)->markContextLost(); } - egl::error(EGL_CONTEXT_LOST); } void Display::recreateSwapChains() @@ -604,10 +630,11 @@ void Display::initVendorString() LUID adapterLuid = {0}; + //TODO(jmadill): LUID is not cross-platform if (mRenderer && mRenderer->getLUID(&adapterLuid)) { char adapterLuidString[64]; - snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); mVendorString += adapterLuidString; } diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index 73ba7673ff..b3ffcc84c5 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -14,7 +14,9 @@ #include <set> #include <vector> +#include "libEGL/Error.h" #include "libEGL/Config.h" +#include "libEGL/AttributeMap.h" namespace gl { @@ -30,10 +32,10 @@ class Display public: ~Display(); - bool initialize(); + Error initialize(); void terminate(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType); + static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); static const char *getExtensionString(egl::Display *display); @@ -43,9 +45,10 @@ class Display bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); - EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList); - EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); - EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess); + Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface); + Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface); + Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, + bool robustAccess, EGLContext *outContext); void destroySurface(egl::Surface *surface); void destroyContext(gl::Context *context); @@ -64,18 +67,19 @@ class Display const char *getExtensionString() const; const char *getVendorString() const; - EGLNativeDisplayType getDisplayId() const { return mDisplayId; } private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId, EGLint displayType); + Display(EGLNativeDisplayType displayId); + + void setAttributes(const AttributeMap &attribMap); - bool restoreLostDevice(); + Error restoreLostDevice(); EGLNativeDisplayType mDisplayId; - EGLint mRequestedDisplayType; + AttributeMap mAttributeMap; typedef std::set<Surface*> SurfaceSet; SurfaceSet mSurfaceSet; diff --git a/src/3rdparty/angle/src/libEGL/Error.cpp b/src/3rdparty/angle/src/libEGL/Error.cpp new file mode 100644 index 0000000000..df5f163d32 --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/Error.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Error.cpp: Implements the egl::Error class which encapsulates an EGL error +// and optional error message. + +#include "libEGL/Error.h" + +#include "common/angleutils.h" + +#include <cstdarg> + +namespace egl +{ + +Error::Error(EGLint errorCode) + : mCode(errorCode), + mMessage() +{ +} + +Error::Error(EGLint errorCode, const char *msg, ...) + : mCode(errorCode), + mMessage() +{ + va_list vararg; + va_start(vararg, msg); + mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mMessage(other.mMessage) +{ +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + mMessage = other.mMessage; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/libEGL/Error.h b/src/3rdparty/angle/src/libEGL/Error.h new file mode 100644 index 0000000000..71805d2fb7 --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/Error.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Error.h: Defines the egl::Error class which encapsulates an EGL error +// and optional error message. + +#ifndef LIBEGL_ERROR_H_ +#define LIBEGL_ERROR_H_ + +#include <EGL/egl.h> + +#include <string> + +namespace egl +{ + +class Error +{ + public: + explicit Error(EGLint errorCode); + Error(EGLint errorCode, const char *msg, ...); + Error(const Error &other); + Error &operator=(const Error &other); + + EGLint getCode() const { return mCode; } + bool isError() const { return (mCode != EGL_SUCCESS); } + + const std::string &getMessage() const { return mMessage; } + + private: + EGLint mCode; + std::string mMessage; +}; + +} + +#endif // LIBEGL_ERROR_H_ diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index fa7996152a..b664a8530e 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -22,23 +22,19 @@ #include "libEGL/main.h" #include "libEGL/Display.h" -#if defined(ANGLE_PLATFORM_WINRT) -# include "wrl.h" -# include "windows.graphics.display.h" -# include "windows.ui.core.h" -using namespace ABI::Windows::Graphics::Display; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::UI::Core; -using namespace Microsoft::WRL; -#endif +#include "common/NativeWindow.h" + +//TODO(jmadill): phase this out +#include "libGLESv2/renderer/d3d/RendererD3D.h" namespace egl { -Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) - : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) + : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported) { - mRenderer = mDisplay->getRenderer(); + //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) + mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer()); mSwapChain = NULL; mShareHandle = NULL; mTexture = NULL; @@ -51,27 +47,19 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win mSwapInterval = -1; mWidth = width; mHeight = height; + mFixedWidth = mWidth; + mFixedHeight = mHeight; setSwapInterval(1); mFixedSize = fixedSize; - mSwapFlags = rx::SWAP_NORMAL; -#if defined(ANGLE_PLATFORM_WINRT) - if (mWindow) - mWindow->AddRef(); - mScaleFactor = 1.0; - mSizeToken.value = 0; - mDpiToken.value = 0; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - mOrientationToken.value = 0; -# endif -#endif subclassWindow(); } Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) - : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) + : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) { - mRenderer = mDisplay->getRenderer(); + //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) + mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer()); mSwapChain = NULL; mWindowSubclassed = false; mTexture = NULL; @@ -85,90 +73,33 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL setSwapInterval(1); // This constructor is for offscreen surfaces, which are always fixed-size. mFixedSize = EGL_TRUE; - mSwapFlags = rx::SWAP_NORMAL; -#if defined(ANGLE_PLATFORM_WINRT) - mScaleFactor = 1.0; - mSizeToken.value = 0; - mDpiToken.value = 0; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - mOrientationToken.value = 0; -# endif -#endif + mFixedWidth = mWidth; + mFixedHeight = mHeight; } Surface::~Surface() { -#if defined(ANGLE_PLATFORM_WINRT) - if (mSizeToken.value) { - ComPtr<ICoreWindow> coreWindow; - HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = coreWindow->remove_SizeChanged(mSizeToken); - ASSERT(SUCCEEDED(hr)); - } - if (mDpiToken.value) { - ComPtr<IDisplayInformation> displayInformation; - HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = displayInformation->remove_DpiChanged(mDpiToken); - ASSERT(SUCCEEDED(hr)); - } -# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP - if (mOrientationToken.value) { - ComPtr<IDisplayInformation> displayInformation; - HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = displayInformation->remove_OrientationChanged(mOrientationToken); - ASSERT(SUCCEEDED(hr)); - } -# endif -#endif unsubclassWindow(); release(); } -bool Surface::initialize() -{ -#if defined(ANGLE_PLATFORM_WINRT) - if (!mFixedSize) { - HRESULT hr; - ComPtr<IDisplayInformation> displayInformation; - hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - onDpiChanged(displayInformation.Get(), 0); - hr = displayInformation->add_DpiChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onDpiChanged).Get(), - &mDpiToken); - ASSERT(SUCCEEDED(hr)); - -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - onOrientationChanged(displayInformation.Get(), 0); - hr = displayInformation->add_OrientationChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onOrientationChanged).Get(), - &mOrientationToken); - ASSERT(SUCCEEDED(hr)); -# endif - - ComPtr<ICoreWindow> coreWindow; - hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - Rect rect; - hr = coreWindow->get_Bounds(&rect); - ASSERT(SUCCEEDED(hr)); - mWidth = rect.Width * mScaleFactor; - mHeight = rect.Height * mScaleFactor; - hr = coreWindow->add_SizeChanged(Callback<ITypedEventHandler<CoreWindow *, WindowSizeChangedEventArgs *>>(this, &Surface::onSizeChanged).Get(), - &mSizeToken); - ASSERT(SUCCEEDED(hr)); +Error Surface::initialize() +{ + if (mNativeWindow.getNativeWindow()) + { + if (!mNativeWindow.initialize()) + { + return Error(EGL_BAD_SURFACE); + } } -#endif - if (!resetSwapChain()) - return false; + Error error = resetSwapChain(); + if (error.isError()) + { + return error; + } - return true; + return Error(EGL_SUCCESS); } void Surface::release() @@ -181,85 +112,80 @@ void Surface::release() mTexture->releaseTexImage(); mTexture = NULL; } - -#if defined(ANGLE_PLATFORM_WINRT) - if (mWindow) - mWindow->Release(); -#endif } -bool Surface::resetSwapChain() +Error Surface::resetSwapChain() { ASSERT(!mSwapChain); int width; int height; -#if !defined(ANGLE_PLATFORM_WINRT) if (!mFixedSize) { RECT windowRect; - if (!GetClientRect(getWindowHandle(), &windowRect)) + if (!mNativeWindow.getClientRect(&windowRect)) { ASSERT(false); - ERR("Could not retrieve the window dimensions"); - return error(EGL_BAD_SURFACE, false); + return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); } width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; } else -#endif { // non-window surface - size is determined at creation width = mWidth; height = mHeight; } - mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle, + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mConfig->mRenderTargetFormat, mConfig->mDepthStencilFormat); if (!mSwapChain) { - return error(EGL_BAD_ALLOC, false); + return Error(EGL_BAD_ALLOC); } - if (!resetSwapChain(width, height)) + Error error = resetSwapChain(width, height); + if (error.isError()) { - delete mSwapChain; - mSwapChain = NULL; - return false; + SafeDelete(mSwapChain); + return error; } - return true; + return Error(EGL_SUCCESS); } -bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) +Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) { - ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + backbufferWidth = std::max(1, backbufferWidth); + backbufferHeight = std::max(1, backbufferHeight); +#endif + EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); if (status == EGL_CONTEXT_LOST) { mDisplay->notifyDeviceLost(); - return false; + return Error(status); } else if (status != EGL_SUCCESS) { - return error(status, false); + return Error(status); } mWidth = backbufferWidth; mHeight = backbufferHeight; - return true; + return Error(EGL_SUCCESS); } -bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) { ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); @@ -269,69 +195,71 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) if (status == EGL_CONTEXT_LOST) { mRenderer->notifyDeviceLost(); - return false; + return Error(status); } else if (status != EGL_SUCCESS) { - return error(status, false); + return Error(status); } mWidth = backbufferWidth; mHeight = backbufferHeight; mSwapIntervalDirty = false; - return true; + return Error(EGL_SUCCESS); } -bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { - return true; + return Error(EGL_SUCCESS); } - if (x + width > mWidth) + if (x + width > abs(mWidth)) { - width = mWidth - x; + width = abs(mWidth) - x; } - if (y + height > mHeight) + if (y + height > abs(mHeight)) { - height = mHeight - y; + height = abs(mHeight) - y; } if (width == 0 || height == 0) { - return true; + return Error(EGL_SUCCESS); } - EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags); + ASSERT(width > 0); + ASSERT(height > 0); + + EGLint status = mSwapChain->swapRect(x, y, width, height); if (status == EGL_CONTEXT_LOST) { mRenderer->notifyDeviceLost(); - return false; + return Error(status); } else if (status != EGL_SUCCESS) { - return error(status, false); + return Error(status); } checkForOutOfDateSwapChain(); - return true; + return Error(EGL_SUCCESS); } EGLNativeWindowType Surface::getWindowHandle() { - return mWindow; + return mNativeWindow.getNativeWindow(); } - +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") -#if !defined(ANGLE_PLATFORM_WINRT) static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (message == WM_SIZE) @@ -349,45 +277,50 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam void Surface::subclassWindow() { -#if !defined(ANGLE_PLATFORM_WINRT) - if (!mWindow) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) { return; } DWORD processId; - DWORD threadId = GetWindowThreadProcessId(mWindow, &processId); + DWORD threadId = GetWindowThreadProcessId(window, &processId); if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) { return; } SetLastError(0); - LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) { mWindowSubclassed = false; return; } - SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); - SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); + SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); + SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); mWindowSubclassed = true; -#else - mWindowSubclassed = false; #endif } void Surface::unsubclassWindow() { -#if !defined(ANGLE_PLATFORM_WINRT) if(!mWindowSubclassed) { return; } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + // un-subclass - LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc)); + LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc)); // Check the windowproc is still SurfaceWindowProc. // If this assert fails, then it is likely the application has subclassed the @@ -396,29 +329,28 @@ void Surface::unsubclassWindow() // EGL context, or to unsubclass before destroying the EGL context. if(parentWndFunc) { - LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc); + LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); UNUSED_ASSERTION_VARIABLE(prevWndFunc); ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); } - RemoveProp(mWindow, kSurfaceProperty); - RemoveProp(mWindow, kParentWndProc); - mWindowSubclassed = false; + RemoveProp(window, kSurfaceProperty); + RemoveProp(window, kParentWndProc); #endif + mWindowSubclassed = false; } bool Surface::checkForOutOfDateSwapChain() { + RECT client; int clientWidth = getWidth(); int clientHeight = getHeight(); bool sizeDirty = false; -#if !defined(ANGLE_PLATFORM_WINRT) - if (!mFixedSize && !IsIconic(getWindowHandle())) + if (!mFixedSize && !mNativeWindow.isIconic()) { - RECT client; // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized // because that's not a useful size to render to. - if (!GetClientRect(getWindowHandle(), &client)) + if (!mNativeWindow.getClientRect(&client)) { ASSERT(false); return false; @@ -429,7 +361,13 @@ bool Surface::checkForOutOfDateSwapChain() clientHeight = client.bottom - client.top; sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); } -#endif + + if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) + { + clientWidth = mFixedWidth; + clientHeight = mFixedHeight; + sizeDirty = true; + } bool wasDirty = (mSwapIntervalDirty || sizeDirty); @@ -455,17 +393,17 @@ bool Surface::checkForOutOfDateSwapChain() return false; } -bool Surface::swap() +Error Surface::swap() { - return swapRect(0, 0, mWidth, mHeight); + return swapRect(0, 0, abs(mWidth), abs(mHeight)); } -bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mPostSubBufferSupported) { // Spec is not clear about how this should be handled. - return true; + return Error(EGL_SUCCESS); } return swapRect(x, y, width, height); @@ -550,77 +488,18 @@ EGLint Surface::isFixedSize() const return mFixedSize; } -EGLenum Surface::getFormat() const +void Surface::setFixedWidth(EGLint width) { - return mConfig->mRenderTargetFormat; + mFixedWidth = width; } -#if defined(ANGLE_PLATFORM_WINRT) - -HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args) +void Surface::setFixedHeight(EGLint height) { - HRESULT hr; - Size size; - hr = args->get_Size(&size); - ASSERT(SUCCEEDED(hr)); - - resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5), - std::floor(size.Height * mScaleFactor + 0.5)); - - if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) - { - glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); - } - - return S_OK; -} - -HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *) -{ - HRESULT hr; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - ComPtr<IDisplayInformation2> displayInformation2; - hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); - ASSERT(SUCCEEDED(hr)); -# else - ResolutionScale resolutionScale; - hr = displayInformation->get_ResolutionScale(&resolutionScale); - ASSERT(SUCCEEDED(hr)); - - mScaleFactor = double(resolutionScale) / 100.0; -# endif - return S_OK; -} - -# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP -HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *) -{ - HRESULT hr; - DisplayOrientations orientation; - hr = displayInformation->get_CurrentOrientation(&orientation); - ASSERT(SUCCEEDED(hr)); - switch (orientation) { - default: - case DisplayOrientations_Portrait: - mSwapFlags = rx::SWAP_NORMAL; - break; - case DisplayOrientations_Landscape: - mSwapFlags = rx::SWAP_ROTATE_90; - break; - case DisplayOrientations_LandscapeFlipped: - mSwapFlags = rx::SWAP_ROTATE_270; - break; - case DisplayOrientations_PortraitFlipped: - mSwapFlags = rx::SWAP_ROTATE_180; - break; - } - return S_OK; + mFixedHeight = height; } -# endif - -#endif +EGLenum Surface::getFormat() const +{ + return mConfig->mRenderTargetFormat; +} } diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index ebffce8fed..46382d06e1 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h @@ -11,23 +11,12 @@ #ifndef LIBEGL_SURFACE_H_ #define LIBEGL_SURFACE_H_ +#include "libEGL/Error.h" + #include <EGL/egl.h> #include "common/angleutils.h" - -#if defined(ANGLE_PLATFORM_WINRT) -#include <EventToken.h> -namespace ABI { namespace Windows { - namespace UI { namespace Core { - struct ICoreWindow; - struct IWindowSizeChangedEventArgs; - } } - namespace Graphics { namespace Display { - struct IDisplayInformation; - } } -} } -struct IInspectable; -#endif +#include "common/NativeWindow.h" namespace gl { @@ -35,8 +24,8 @@ class Texture2D; } namespace rx { -class Renderer; class SwapChain; +class RendererD3D; //TODO(jmadill): remove this } namespace egl @@ -52,13 +41,13 @@ class Surface virtual ~Surface(); - bool initialize(); + Error initialize(); void release(); - bool resetSwapChain(); + Error resetSwapChain(); EGLNativeWindowType getWindowHandle(); - bool swap(); - bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); + Error swap(); + Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); virtual EGLint isPostSubBufferSupported() const; @@ -81,35 +70,31 @@ class Surface virtual gl::Texture2D *getBoundTexture() const; EGLint isFixedSize() const; + void setFixedWidth(EGLint width); + void setFixedHeight(EGLint height); -private: + private: DISALLOW_COPY_AND_ASSIGN(Surface); -#if defined(ANGLE_PLATFORM_WINRT) - HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); - HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); -# endif -#endif - Display *const mDisplay; - rx::Renderer *mRenderer; + rx::RendererD3D *mRenderer; HANDLE mShareHandle; rx::SwapChain *mSwapChain; void subclassWindow(); void unsubclassWindow(); - bool resizeSwapChain(int backbufferWidth, int backbufferHeight); - bool resetSwapChain(int backbufferWidth, int backbufferHeight); - bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + Error resizeSwapChain(int backbufferWidth, int backbufferHeight); + Error resetSwapChain(int backbufferWidth, int backbufferHeight); + Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const EGLNativeWindowType mWindow; // Window that the surface is created for. + rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking const egl::Config *mConfig; // EGL config surface was created with EGLint mHeight; // Height of surface EGLint mWidth; // Width of surface + EGLint mFixedHeight; // Pending height of the surface + EGLint mFixedWidth; // Pending width of the surface // EGLint horizontalResolution; // Horizontal dot pitch // EGLint verticalResolution; // Vertical dot pitch // EGLBoolean largestPBuffer; // If true, create largest pbuffer possible @@ -126,18 +111,9 @@ private: EGLint mSwapInterval; EGLint mPostSubBufferSupported; EGLint mFixedSize; - EGLint mSwapFlags; bool mSwapIntervalDirty; gl::Texture2D *mTexture; -#if defined(ANGLE_PLATFORM_WINRT) - double mScaleFactor; - EventRegistrationToken mSizeToken; - EventRegistrationToken mDpiToken; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - EventRegistrationToken mOrientationToken; -# endif -#endif }; } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index c2e0fd6d3d..68399d63a4 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -13,7 +13,6 @@ #include "common/debug.h" #include "common/version.h" -#include "common/platform.h" #include "libGLESv2/Context.h" #include "libGLESv2/Texture.h" #include "libGLESv2/main.h" @@ -26,16 +25,20 @@ #include "libEGL/Display.h" #include "libEGL/Surface.h" +#include "common/NativeWindow.h" + bool validateDisplay(egl::Display *display) { if (display == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_DISPLAY, false); + recordError(egl::Error(EGL_BAD_DISPLAY)); + return false; } if (!display->isInitialized()) { - return egl::error(EGL_NOT_INITIALIZED, false); + recordError(egl::Error(EGL_NOT_INITIALIZED)); + return false; } return true; @@ -50,7 +53,8 @@ bool validateConfig(egl::Display *display, EGLConfig config) if (!display->isValidConfig(config)) { - return egl::error(EGL_BAD_CONFIG, false); + recordError(egl::Error(EGL_BAD_CONFIG)); + return false; } return true; @@ -65,7 +69,8 @@ bool validateContext(egl::Display *display, gl::Context *context) if (!display->isValidContext(context)) { - return egl::error(EGL_BAD_CONTEXT, false); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return false; } return true; @@ -80,7 +85,8 @@ bool validateSurface(egl::Display *display, egl::Surface *surface) if (!display->isValidSurface(surface)) { - return egl::error(EGL_BAD_SURFACE, false); + recordError(egl::Error(EGL_BAD_SURFACE)); + return false; } return true; @@ -93,12 +99,7 @@ EGLint __stdcall eglGetError(void) EVENT("()"); EGLint error = egl::getCurrentError(); - - if (error != EGL_SUCCESS) - { - egl::setCurrentError(EGL_SUCCESS); - } - + recordError(egl::Error(EGL_SUCCESS)); return error; } @@ -106,7 +107,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) { EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); - return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + return egl::Display::getDisplay(display_id, egl::AttributeMap()); } EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) @@ -120,19 +121,26 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis break; default: - return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY); + recordError(egl::Error(EGL_BAD_CONFIG)); + return EGL_NO_DISPLAY; } EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display); -#if !defined(ANGLE_PLATFORM_WINRT) + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // Validate the display device context if (WindowFromDC(displayId) == NULL) { - return egl::success(EGL_NO_DISPLAY); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; } #endif - EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + bool majorVersionSpecified = false; + bool minorVersionSpecified = false; + bool requestedWARP = false; + if (attrib_list) { for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) @@ -140,7 +148,69 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis switch (curAttrib[0]) { case EGL_PLATFORM_ANGLE_TYPE_ANGLE: - requestedDisplayType = curAttrib[1]; + switch (curAttrib[1]) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: + if (!egl::Display::supportsPlatformD3D()) + { + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + if (!egl::Display::supportsPlatformOpenGL()) + { + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + break; + + default: + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + platformType = curAttrib[1]; + break; + + case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE: + if (curAttrib[1] != EGL_DONT_CARE) + { + majorVersionSpecified = true; + } + break; + + case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE: + if (curAttrib[1] != EGL_DONT_CARE) + { + minorVersionSpecified = true; + } + break; + + case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE: + if (!egl::Display::supportsPlatformD3D()) + { + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + + switch (curAttrib[1]) + { + case EGL_FALSE: + case EGL_TRUE: + break; + + default: + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + + requestedWARP = (curAttrib[1] == EGL_TRUE); break; default: @@ -149,33 +219,20 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis } } - switch (requestedDisplayType) + if (!majorVersionSpecified && minorVersionSpecified) { - case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: - break; - - case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE: - if (!egl::Display::supportsPlatformD3D()) - { - return egl::success(EGL_NO_DISPLAY); - } - break; - - case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: - if (!egl::Display::supportsPlatformOpenGL()) - { - return egl::success(EGL_NO_DISPLAY); - } - break; + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } - default: - return egl::success(EGL_NO_DISPLAY); + if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP) + { + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; } - return egl::Display::getDisplay(displayId, requestedDisplayType); + recordError(egl::Error(EGL_SUCCESS)); + return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list)); } EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) @@ -185,20 +242,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) if (dpy == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); + recordError(egl::Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; } egl::Display *display = static_cast<egl::Display*>(dpy); - if (!display->initialize()) + egl::Error error = display->initialize(); + if (error.isError()) { - return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); + recordError(error); + return EGL_FALSE; } if (major) *major = 1; if (minor) *minor = 4; - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) @@ -207,14 +268,16 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) if (dpy == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); + recordError(egl::Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; } egl::Display *display = static_cast<egl::Display*>(dpy); display->terminate(); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) @@ -227,19 +290,28 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) return NULL; } + const char *result; switch (name) { case EGL_CLIENT_APIS: - return egl::success("OpenGL_ES"); + result = "OpenGL_ES"; + break; case EGL_EXTENSIONS: - return egl::success(egl::Display::getExtensionString(display)); + result = egl::Display::getExtensionString(display); + break; case EGL_VENDOR: - return egl::success(display->getVendorString()); + result = display->getVendorString(); + break; case EGL_VERSION: - return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); + result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")"; + break; default: - return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return NULL; } + + recordError(egl::Error(EGL_SUCCESS)); + return result; } EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) @@ -257,17 +329,20 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co if (!num_config) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } const EGLint attribList[] = {EGL_NONE}; if (!display->getConfigs(configs, attribList, config_size, num_config)) { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) @@ -285,7 +360,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, if (!num_config) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } const EGLint attribList[] = {EGL_NONE}; @@ -297,7 +373,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, display->getConfigs(configs, attrib_list, config_size, num_config); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) @@ -314,10 +391,12 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint if (!display->getConfigAttrib(config, attribute, value)) { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) @@ -332,16 +411,21 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG return EGL_NO_SURFACE; } -#if !defined(ANGLE_PLATFORM_WINRT) - HWND window = (HWND)win; + if (!rx::IsValidEGLNativeWindowType(win)) + { + recordError(egl::Error(EGL_BAD_NATIVE_WINDOW)); + return EGL_NO_SURFACE; + } - if (!IsWindow(window)) + EGLSurface surface = EGL_NO_SURFACE; + egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface); + if (error.isError()) { - return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + recordError(error); + return EGL_NO_SURFACE; } -#endif - return display->createWindowSurface(win, config, attrib_list); + return surface; } EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) @@ -356,7 +440,15 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c return EGL_NO_SURFACE; } - return display->createOffscreenSurface(config, NULL, attrib_list); + EGLSurface surface = EGL_NO_SURFACE; + egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface); + if (error.isError()) + { + recordError(error); + return EGL_NO_SURFACE; + } + + return surface; } EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) @@ -373,7 +465,8 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG UNIMPLEMENTED(); // FIXME - return egl::success(EGL_NO_SURFACE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_SURFACE; } EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) @@ -390,12 +483,14 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } display->destroySurface((egl::Surface*)surface); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) @@ -413,7 +508,8 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } switch (attribute) @@ -473,10 +569,12 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint *value = eglSurface->isFixedSize(); break; default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) @@ -498,7 +596,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } rx::SwapChain *swapchain = eglSurface->getSwapChain(); @@ -522,7 +621,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf if (renderer->getMajorShaderModel() < 4) { - return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return EGL_FALSE; } *value = static_cast<rx::Renderer11*>(renderer)->getDevice(); @@ -530,10 +630,12 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf break; #endif default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglBindAPI(EGLenum api) @@ -544,16 +646,19 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api) { case EGL_OPENGL_API: case EGL_OPENVG_API: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; // Not supported by this implementation case EGL_OPENGL_ES_API: break; default: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } egl::setCurrentAPI(api); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLenum __stdcall eglQueryAPI(void) @@ -562,7 +667,8 @@ EGLenum __stdcall eglQueryAPI(void) EGLenum API = egl::getCurrentAPI(); - return egl::success(API); + recordError(egl::Error(EGL_SUCCESS)); + return API; } EGLBoolean __stdcall eglWaitClient(void) @@ -571,7 +677,8 @@ EGLBoolean __stdcall eglWaitClient(void) UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglReleaseThread(void) @@ -580,7 +687,8 @@ EGLBoolean __stdcall eglReleaseThread(void) eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) @@ -598,10 +706,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_NO_SURFACE; + } + + EGLSurface surface = EGL_NO_SURFACE; + egl::Error error = display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list, &surface); + if (error.isError()) + { + recordError(error); + return EGL_NO_SURFACE; } - return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); + return surface; } EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) @@ -617,9 +734,30 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint return EGL_FALSE; } + switch (attribute) + { + case EGL_WIDTH: + if (!eglSurface->isFixedSize() || !value) { + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + eglSurface->setFixedWidth(value); + return EGL_TRUE; + case EGL_HEIGHT: + if (!eglSurface->isFixedSize() || !value) { + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + eglSurface->setFixedHeight(value); + return EGL_TRUE; + default: + break; + } + UNIMPLEMENTED(); // FIXME - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) @@ -636,30 +774,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint if (buffer != EGL_BACK_BUFFER) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } if (eglSurface->getBoundTexture()) { - return egl::error(EGL_BAD_ACCESS, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ACCESS)); + return EGL_FALSE; } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } if (!glBindTexImage(eglSurface)) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) @@ -676,17 +820,20 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi if (buffer != EGL_BACK_BUFFER) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } gl::Texture2D *texture = eglSurface->getBoundTexture(); @@ -696,7 +843,8 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi texture->releaseTexImage(); } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) @@ -714,12 +862,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) if (draw_surface == NULL) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } draw_surface->setSwapInterval(interval); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) @@ -744,27 +894,38 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: if (attribute[1] == EGL_TRUE) { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented + recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented + return EGL_NO_CONTEXT; // robust_access = true; } else if (attribute[1] != EGL_FALSE) - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + { + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_CONTEXT; + } break; case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) + { reset_notification = true; + } else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + { + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_CONTEXT; + } break; default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_CONTEXT; } } } if (client_version != 2 && client_version != 3) { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_CONFIG)); + return EGL_NO_CONTEXT; } egl::Display *display = static_cast<egl::Display*>(dpy); @@ -775,18 +936,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte if (sharedGLContext->isResetNotificationEnabled() != reset_notification) { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_NO_CONTEXT; } if (sharedGLContext->getClientVersion() != client_version) { - return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return EGL_NO_CONTEXT; } // Can not share contexts between displays if (sharedGLContext->getRenderer() != display->getRenderer()) { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_NO_CONTEXT; } } @@ -795,7 +959,16 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte return EGL_NO_CONTEXT; } - return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access); + EGLContext context = EGL_NO_CONTEXT; + egl::Error error = display->createContext(config, client_version, static_cast<gl::Context*>(share_context), + reset_notification, robust_access, &context); + if (error.isError()) + { + recordError(error); + return EGL_NO_CONTEXT; + } + + return context; } EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) @@ -812,12 +985,14 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) if (ctx == EGL_NO_CONTEXT) { - return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return EGL_FALSE; } display->destroyContext(context); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) @@ -832,7 +1007,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); if (noContext != noSurface) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) @@ -850,7 +1026,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface if (renderer->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } } @@ -871,7 +1048,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface glMakeCurrent(context, display, static_cast<egl::Surface*>(draw)); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLContext __stdcall eglGetCurrentContext(void) @@ -880,7 +1058,8 @@ EGLContext __stdcall eglGetCurrentContext(void) EGLContext context = glGetCurrentContext(); - return egl::success(context); + recordError(egl::Error(EGL_SUCCESS)); + return context; } EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) @@ -889,17 +1068,18 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) if (readdraw == EGL_READ) { - EGLSurface read = egl::getCurrentReadSurface(); - return egl::success(read); + recordError(egl::Error(EGL_SUCCESS)); + return egl::getCurrentReadSurface(); } else if (readdraw == EGL_DRAW) { - EGLSurface draw = egl::getCurrentDrawSurface(); - return egl::success(draw); + recordError(egl::Error(EGL_SUCCESS)); + return egl::getCurrentDrawSurface(); } else { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_NO_SURFACE; } } @@ -909,7 +1089,8 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void) EGLDisplay dpy = egl::getCurrentDisplay(); - return egl::success(dpy); + recordError(egl::Error(EGL_SUCCESS)); + return dpy; } EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) @@ -927,7 +1108,8 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglWaitGL(void) @@ -936,7 +1118,8 @@ EGLBoolean __stdcall eglWaitGL(void) UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglWaitNative(EGLint engine) @@ -945,7 +1128,8 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine) UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) @@ -962,20 +1146,25 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } - if (eglSurface->swap()) + egl::Error error = eglSurface->swap(); + if (error.isError()) { - return egl::success(EGL_TRUE); + recordError(error); + return EGL_FALSE; } - return EGL_FALSE; + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) @@ -992,12 +1181,14 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) @@ -1006,7 +1197,8 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi if (x < 0 || y < 0 || width < 0 || height < 0) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } egl::Display *display = static_cast<egl::Display*>(dpy); @@ -1019,20 +1211,25 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } - if (eglSurface->postSubBuffer(x, y, width, height)) + egl::Error error = eglSurface->postSubBuffer(x, y, width, height); + if (error.isError()) { - return egl::success(EGL_TRUE); + recordError(error); + return EGL_FALSE; } - return EGL_FALSE; + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index e74737eaba..e88cad775f 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -11,9 +11,6 @@ #include "common/debug.h" #include "common/tls.h" -#if defined(ANGLE_PLATFORM_WINRT) -__declspec(thread) -#endif static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; namespace egl @@ -21,12 +18,6 @@ namespace egl Current *AllocateCurrent() { -#if defined(ANGLE_PLATFORM_WINRT) - if (currentTLS == TLS_OUT_OF_INDEXES) - { - currentTLS = CreateTLSIndex(); - } -#endif ASSERT(currentTLS != TLS_OUT_OF_INDEXES); if (currentTLS == TLS_OUT_OF_INDEXES) { @@ -51,12 +42,6 @@ Current *AllocateCurrent() void DeallocateCurrent() { -#if defined(ANGLE_PLATFORM_WINRT) - if (currentTLS == TLS_OUT_OF_INDEXES) - { - return; - } -#endif Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); SafeDelete(current); SetTLSValue(currentTLS, NULL); @@ -72,7 +57,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { -#if defined(ANGLE_ENABLE_TRACE) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); if (debug) @@ -87,15 +72,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } #endif -#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain - return DisableThreadLibraryCalls(instance); -#endif - currentTLS = CreateTLSIndex(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } + +#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS + gl::InitializeDebugAnnotations(); +#endif } // Fall through to initialize index case DLL_THREAD_ATTACH: @@ -105,15 +90,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_THREAD_DETACH: { -#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); -#endif } break; case DLL_PROCESS_DETACH: { egl::DeallocateCurrent(); DestroyTLSIndex(currentTLS); + +#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS + gl::UninitializeDebugAnnotations(); +#endif } break; default: @@ -143,11 +130,11 @@ Current *GetCurrentData() #endif } -void setCurrentError(EGLint error) +void recordError(const Error &error) { Current *current = GetCurrentData(); - current->error = error; + current->error = error.getCode(); } EGLint getCurrentError() @@ -213,9 +200,4 @@ EGLSurface getCurrentReadSurface() return current->readSurface; } -void error(EGLint errorCode) -{ - egl::setCurrentError(errorCode); -} - } diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h index 07f5b9e675..e5361a4a5e 100644 --- a/src/3rdparty/angle/src/libEGL/main.h +++ b/src/3rdparty/angle/src/libEGL/main.h @@ -9,6 +9,8 @@ #ifndef LIBEGL_MAIN_H_ #define LIBEGL_MAIN_H_ +#include "libEGL/Error.h" + #include <EGL/egl.h> #include <EGL/eglext.h> @@ -23,7 +25,7 @@ struct Current EGLSurface readSurface; }; -void setCurrentError(EGLint error); +void recordError(const Error &error); EGLint getCurrentError(); void setCurrentAPI(EGLenum API); @@ -38,24 +40,6 @@ EGLSurface getCurrentDrawSurface(); void setCurrentReadSurface(EGLSurface surface); EGLSurface getCurrentReadSurface(); -void error(EGLint errorCode); - -template<class T> -const T &error(EGLint errorCode, const T &returnValue) -{ - error(errorCode); - - return returnValue; -} - -template<class T> -const T &success(const T &returnValue) -{ - egl::setCurrentError(EGL_SUCCESS); - - return returnValue; -} - } #endif // LIBEGL_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h index 4d7dde04e1..4f7f5f2c85 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h @@ -15,6 +15,7 @@ #include <cstddef> #include <string> #include <vector> +#include <stdint.h> namespace gl { @@ -26,7 +27,7 @@ class BinaryInputStream { mError = false; mOffset = 0; - mData = static_cast<const char*>(data); + mData = static_cast<const uint8_t*>(data); mLength = length; } @@ -85,7 +86,7 @@ class BinaryInputStream return; } - v->assign(mData + mOffset, length); + v->assign(reinterpret_cast<const char *>(mData) + mOffset, length); mOffset += length; } @@ -115,11 +116,16 @@ class BinaryInputStream return mOffset == mLength; } + const uint8_t *data() + { + return mData; + } + private: DISALLOW_COPY_AND_ASSIGN(BinaryInputStream); bool mError; size_t mOffset; - const char *mData; + const uint8_t *mData; size_t mLength; template <typename T> diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 35a6767502..daa862ca0d 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -19,7 +19,6 @@ namespace rx { -class Renderer; class BufferImpl; }; diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 5342de1331..b87689cd3f 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -9,10 +9,8 @@ #include "libGLESv2/Context.h" -#include "libGLESv2/main.h" #include "common/utilities.h" #include "common/platform.h" -#include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" @@ -21,14 +19,15 @@ #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" -#include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/VertexArray.h" #include "libGLESv2/Sampler.h" -#include "libGLESv2/validationES.h" +#include "libGLESv2/Texture.h" #include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/main.h" +#include "libGLESv2/validationES.h" +#include "libGLESv2/renderer/Renderer.h" #include "libEGL/Surface.h" @@ -38,7 +37,7 @@ namespace gl { -Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) +Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented @@ -66,22 +65,24 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0)); - bindTexture(GL_TEXTURE_2D, 0); + Texture2D *zeroTexture2D = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0); + mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D); - mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0)); - bindTexture(GL_TEXTURE_CUBE_MAP, 0); + TextureCubeMap *zeroTextureCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0); + mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube); if (mClientVersion >= 3) { // TODO: These could also be enabled via extension - mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0)); - bindTexture(GL_TEXTURE_3D, 0); + Texture3D *zeroTexture3D = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0); + mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D); - mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0)); - bindTexture(GL_TEXTURE_2D_ARRAY, 0); + Texture2DArray *zeroTexture2DArray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0); + mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray); } + mState.initializeZeroTextures(mZeroTextures); + bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); @@ -91,13 +92,13 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere bindRenderbuffer(0); bindGenericUniformBuffer(0); - for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++) { bindIndexedUniformBuffer(0, i, 0, -1); } bindGenericTransformFeedbackBuffer(0); - for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++) { bindIndexedTransformFeedbackBuffer(0, i, 0, -1); } @@ -119,8 +120,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere mResetStatus = GL_NO_ERROR; mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; - - mState.setContext(this); } Context::~Context() @@ -175,7 +174,10 @@ Context::~Context() } mZeroTextures.clear(); - mResourceManager->release(); + if (mResourceManager) + { + mResourceManager->release(); + } } void Context::makeCurrent(egl::Surface *surface) @@ -194,14 +196,11 @@ void Context::makeCurrent(egl::Surface *surface) // Wrap the existing swapchain resources into GL objects and assign them to the '0' names rx::SwapChain *swapchain = surface->getSwapChain(); - Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain); - DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain); - Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero); + rx::RenderbufferImpl *colorbufferZero = mRenderer->createRenderbuffer(swapchain, false); + rx::RenderbufferImpl *depthStencilbufferZero = mRenderer->createRenderbuffer(swapchain, true); + Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); setFramebufferZero(framebufferZero); - - // Store the current client version in the renderer - mRenderer->setCurrentClientVersion(mClientVersion); } // NOTE: this function should not assume that this context is current! @@ -229,7 +228,7 @@ GLuint Context::createProgram() GLuint Context::createShader(GLenum type) { - return mResourceManager->createShader(type); + return mResourceManager->createShader(getData(), type); } GLuint Context::createTexture() @@ -242,15 +241,10 @@ GLuint Context::createRenderbuffer() return mResourceManager->createRenderbuffer(); } -GLsync Context::createFenceSync(GLenum condition) +GLsync Context::createFenceSync() { GLuint handle = mResourceManager->createFenceSync(); - gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle); - ASSERT(fenceSync); - - fenceSync->set(condition); - return reinterpret_cast<GLsync>(handle); } @@ -294,7 +288,7 @@ GLuint Context::createFenceNV() { GLuint handle = mFenceNVHandleAllocator.allocate(); - mFenceNVMap[handle] = new FenceNV(mRenderer); + mFenceNVMap[handle] = new FenceNV(mRenderer->createFenceNV()); return handle; } @@ -355,12 +349,12 @@ void Context::deleteFenceSync(GLsync fenceSync) // wait commands finish. However, since the name becomes invalid, we cannot query the fence, // and since our API is currently designed for being called from a single thread, we can delete // the fence immediately. - mResourceManager->deleteFenceSync(uintptr_t(fenceSync)); + mResourceManager->deleteFenceSync(reinterpret_cast<uintptr_t>(fenceSync)); } void Context::deleteVertexArray(GLuint vertexArray) { - auto vertexArrayObject = mVertexArrayMap.find(vertexArray); + VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray); if (vertexArrayObject != mVertexArrayMap.end()) { @@ -461,12 +455,12 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle) FenceSync *Context::getFenceSync(GLsync handle) const { - return mResourceManager->getFenceSync(uintptr_t(handle)); + return mResourceManager->getFenceSync(reinterpret_cast<uintptr_t>(handle)); } VertexArray *Context::getVertexArray(GLuint handle) const { - auto vertexArray = mVertexArrayMap.find(handle); + VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle); if (vertexArray == mVertexArrayMap.end()) { @@ -515,18 +509,30 @@ void Context::bindElementArrayBuffer(unsigned int buffer) mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } -void Context::bindTexture(GLenum target, GLuint texture) +void Context::bindTexture(GLenum target, GLuint handle) { - mResourceManager->checkTextureAllocation(texture, target); + Texture *texture = NULL; + + if (handle == 0) + { + texture = mZeroTextures[target].get(); + } + else + { + mResourceManager->checkTextureAllocation(handle, target); + texture = getTexture(handle); + } - mState.setSamplerTexture(target, getTexture(texture)); + ASSERT(texture); + + mState.setSamplerTexture(target, texture); } void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); + mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); } mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); @@ -536,7 +542,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); + mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); } mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); @@ -640,33 +646,44 @@ void Context::useProgram(GLuint program) } } -void Context::linkProgram(GLuint program) +Error Context::linkProgram(GLuint program) { Program *programObject = mResourceManager->getProgram(program); - bool linked = programObject->link(getCaps()); + Error error = programObject->link(getData()); + if (error.isError()) + { + return error; + } // if the current program was relinked successfully we // need to install the new executables - if (linked && program == mState.getCurrentProgramId()) + if (programObject->isLinked() && program == mState.getCurrentProgramId()) { mState.setCurrentProgramBinary(programObject->getProgramBinary()); } + + return Error(GL_NO_ERROR); } -void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) +Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { Program *programObject = mResourceManager->getProgram(program); - bool loaded = programObject->setProgramBinary(binaryFormat, binary, length); + Error error = programObject->setProgramBinary(binaryFormat, binary, length); + if (error.isError()) + { + return error; + } // if the current program was reloaded successfully we // need to install the new executables - if (loaded && program == mState.getCurrentProgramId()) + if (programObject->isLinked() && program == mState.getCurrentProgramId()) { mState.setCurrentProgramBinary(programObject->getProgramBinary()); } + return Error(GL_NO_ERROR); } void Context::bindTransformFeedback(GLuint transformFeedback) @@ -724,33 +741,6 @@ void Context::setFramebufferZero(Framebuffer *buffer) mFramebufferMap[0] = buffer; } -void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) -{ - ASSERT(getTextureCaps().get(internalformat).renderable); - - RenderbufferStorage *renderbuffer = NULL; - - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0) - { - renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); - } - else if (formatInfo.depthBits > 0) - { - renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); - } - else if (formatInfo.stencilBits > 0) - { - renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); - } - else - { - renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples); - } - - mState.getCurrentRenderbuffer()->setStorage(renderbuffer); -} - Framebuffer *Context::getFramebuffer(unsigned int handle) const { FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle); @@ -837,14 +827,7 @@ Texture2DArray *Context::getTexture2DArray() const Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const { - if (mState.getSamplerTextureId(sampler, type) == 0) - { - return mZeroTextures.at(type).get(); - } - else - { - return mState.getSamplerTexture(sampler, type); - } + return mState.getSamplerTexture(sampler, type); } void Context::getBooleanv(GLenum pname, GLboolean *params) @@ -962,7 +945,7 @@ void Context::getIntegerv(GLenum pname, GLint *params) *params = static_cast<GLint>(mExtensionStrings.size()); break; default: - mState.getIntegerv(pname, params); + mState.getIntegerv(getData(), pname, params); break; } } @@ -1309,309 +1292,6 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned return false; } -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) -{ - Framebuffer *framebufferObject = mState.getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); - - gl::Error error = mRenderer->applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } - - float nearZ, farZ; - mState.getDepthRange(&nearZ, &farZ); - mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, - ignoreViewport); - - mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); - - return gl::Error(GL_NO_ERROR); -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device -Error Context::applyState(GLenum drawMode) -{ - Framebuffer *framebufferObject = mState.getDrawFramebuffer(); - int samples = framebufferObject->getSamples(); - - RasterizerState rasterizer = mState.getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - Error error = mRenderer->setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - - unsigned int mask = 0; - if (mState.isSampleCoverageEnabled()) - { - GLclampf coverageValue; - bool coverageInvert = false; - mState.getSampleCoverageParams(&coverageValue, &coverageInvert); - if (coverageValue != 0) - { - float threshold = 0.5f; - - for (int i = 0; i < samples; ++i) - { - mask <<= 1; - - if ((i + 1) * coverageValue >= threshold) - { - threshold += 1.0f; - mask |= 1; - } - } - } - - if (coverageInvert) - { - mask = ~mask; - } - } - else - { - mask = 0xFFFFFFFF; - } - error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), - rasterizer.frontFace == GL_CCW); - if (error.isError()) - { - return error; - } - - return Error(GL_NO_ERROR); -} - -// Applies the shaders and shader constants to the Direct3D 9 device -Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) -{ - const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); - - VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; - VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); - - const Framebuffer *fbo = mState.getDrawFramebuffer(); - - Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - return programBinary->applyUniforms(); -} - -Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type) -{ - size_t samplerRange = programBinary->getUsedSamplerRange(type); - - for (size_t i = 0; i < samplerRange; i++) - { - GLenum textureType = programBinary->getSamplerTextureType(type, i); - GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps()); - if (textureUnit != -1) - { - Texture* texture = getSamplerTexture(textureUnit, textureType); - if (texture->getSamplerState().swizzleRequired()) - { - Error error = mRenderer->generateSwizzle(texture); - if (error.isError()) - { - return error; - } - } - } - } - - return Error(GL_NO_ERROR); -} - -Error Context::generateSwizzles(ProgramBinary *programBinary) -{ - Error error = generateSwizzles(programBinary, SAMPLER_VERTEX); - if (error.isError()) - { - return error; - } - - error = generateSwizzles(programBinary, SAMPLER_PIXEL); - if (error.isError()) - { - return error; - } - - return Error(GL_NO_ERROR); -} - -// For each Direct3D sampler of either the pixel or vertex stage, -// looks up the corresponding OpenGL texture image unit and texture type, -// and sets the texture and its addressing/filtering state (or NULL when inactive). -Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) -{ - size_t samplerRange = programBinary->getUsedSamplerRange(shaderType); - for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) - { - GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex); - GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps()); - if (textureUnit != -1) - { - SamplerState sampler; - Texture* texture = getSamplerTexture(textureUnit, textureType); - texture->getSamplerStateWithNativeOffset(&sampler); - - Sampler *samplerObject = mState.getSampler(textureUnit); - if (samplerObject) - { - samplerObject->getState(&sampler); - } - - // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) && - !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) - { - Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler); - if (error.isError()) - { - return error; - } - - error = mRenderer->setTexture(shaderType, samplerIndex, texture); - if (error.isError()) - { - return error; - } - } - else - { - // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. - Texture *incompleteTexture = getIncompleteTexture(textureType); - gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); - if (error.isError()) - { - return error; - } - } - } - else - { - // No texture bound to this slot even though it is used by the shader, bind a NULL texture - Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - } - - // Set all the remaining textures to NULL - size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits - : mCaps.maxVertexTextureImageUnits; - for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) - { - Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - - return Error(GL_NO_ERROR); -} - -Error Context::applyTextures(ProgramBinary *programBinary) -{ - FramebufferTextureSerialArray framebufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials); - - Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - return Error(GL_NO_ERROR); -} - -Error Context::applyUniformBuffers() -{ - Program *programObject = getProgram(mState.getCurrentProgramId()); - ProgramBinary *programBinary = programObject->getProgramBinary(); - - std::vector<Buffer*> boundBuffers; - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) - { - GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); - - if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) - { - // undefined behaviour - return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."); - } - else - { - Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding); - ASSERT(uniformBuffer); - boundBuffers.push_back(uniformBuffer); - } - } - - return programBinary->applyUniformBuffers(boundBuffers, getCaps()); -} - -bool Context::applyTransformFeedbackBuffers() -{ - TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i); - transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i); - } - mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets); - return true; - } - else - { - return false; - } -} - -void Context::markTransformFeedbackUsage() -{ - for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i); - if (buffer) - { - buffer->markTransformFeedbackUsage(); - } - } -} - Error Context::clear(GLbitfield mask) { if (mState.isRasterizerDiscardEnabled()) @@ -1619,290 +1299,71 @@ Error Context::clear(GLbitfield mask) return Error(GL_NO_ERROR); } - ClearParameters clearParams = mState.getClearParameters(mask); - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(getData(), mask); } -Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) +Error Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = mState.getClearParameters(0); - - if (buffer == GL_COLOR) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); - } - clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_FLOAT; - } - - if (buffer == GL_DEPTH) - { - clearParams.clearDepth = true; - clearParams.depthClearValue = values[0]; - } - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferfv(getData(), buffer, drawbuffer, values); } -Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) +Error Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferuv can only be called to clear a color buffer - ClearParameters clearParams = mState.getClearParameters(0); - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); - } - clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_UNSIGNED_INT; - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferuiv(getData(), buffer, drawbuffer, values); } -Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) +Error Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferfv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = mState.getClearParameters(0); - - if (buffer == GL_COLOR) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); - } - clearParams.colorIClearValue = ColorI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_INT; - } - - if (buffer == GL_STENCIL) - { - clearParams.clearStencil = true; - clearParams.stencilClearValue = values[1]; - } - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferiv(getData(), buffer, drawbuffer, values); } -Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) +Error Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = mState.getClearParameters(0); - clearParams.clearDepth = true; - clearParams.depthClearValue = depth; - clearParams.clearStencil = true; - clearParams.stencilClearValue = stencil; - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferfi(getData(), buffer, drawbuffer, depth, stencil); } Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - Framebuffer *framebuffer = mState.getReadFramebuffer(); - - GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); - const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment()); - - return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), - reinterpret_cast<uint8_t*>(pixels)); + return mRenderer->readPixels(getData(), x, y, width, height, format, type, bufSize, pixels); } Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { - ASSERT(mState.getCurrentProgramId() != 0); - - ProgramBinary *programBinary = mState.getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - Error error = generateSwizzles(programBinary); - if (error.isError()) - { - return error; - } - - if (!mRenderer->applyPrimitiveType(mode, count)) - { - return Error(GL_NO_ERROR); - } - - error = applyRenderTarget(mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(mode); - if (error.isError()) - { - return error; - } - - error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(); - - error = applyShaders(programBinary, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(programBinary); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(); - if (error.isError()) - { - return error; - } - - if (!skipDraw(mode)) - { - error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - if (transformFeedbackActive) - { - markTransformFeedbackUsage(); - } - } - - return gl::Error(GL_NO_ERROR); + return mRenderer->drawArrays(getData(), mode, first, count, instances); } Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances, const rx::RangeUI &indexRange) { - ASSERT(mState.getCurrentProgramId() != 0); - - ProgramBinary *programBinary = mState.getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - Error error = generateSwizzles(programBinary); - if (error.isError()) - { - return error; - } - - if (!mRenderer->applyPrimitiveType(mode, count)) - { - return Error(GL_NO_ERROR); - } - - error = applyRenderTarget(mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(mode); - if (error.isError()) - { - return error; - } - - VertexArray *vao = mState.getVertexArray(); - rx::TranslatedIndexData indexInfo; - indexInfo.indexRange = indexRange; - error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); - if (error.isError()) - { - return error; - } - - GLsizei vertexCount = indexInfo.indexRange.length() + 1; - error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), - mState.getVertexAttribCurrentValues(), - indexInfo.indexRange.start, vertexCount, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(); - // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation - // layer. - ASSERT(!transformFeedbackActive); - - error = applyShaders(programBinary, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(programBinary); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(); - if (error.isError()) - { - return error; - } - - if (!skipDraw(mode)) - { - error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); - if (error.isError()) - { - return error; - } - } - - return Error(GL_NO_ERROR); + return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange); } // Implements glFlush when block is false, glFinish when block is true -void Context::sync(bool block) +Error Context::sync(bool block) { - mRenderer->sync(block); + return mRenderer->sync(block); } void Context::recordError(const Error &error) @@ -1931,6 +1392,7 @@ GLenum Context::getError() GLenum Context::getResetStatus() { + //TODO(jmadill): needs MANGLE reworking if (mResetStatus == GL_NO_ERROR && !mContextLost) { // mResetStatus will be set by the markContextLost callback @@ -1981,7 +1443,7 @@ const Extensions &Context::getExtensions() const void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { Framebuffer *framebuffer = mState.getReadFramebuffer(); - ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE); + ASSERT(framebuffer && framebuffer->completeness(getData()) == GL_FRAMEBUFFER_COMPLETE); FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); ASSERT(attachment); @@ -2000,7 +1462,7 @@ void Context::detachTexture(GLuint texture) // allocation map management either here or in the resource manager at detach time. // Zero textures are held by the Context, and we don't attempt to request them from // the State. - mState.detachTexture(texture); + mState.detachTexture(mZeroTextures, texture); } void Context::detachBuffer(GLuint buffer) @@ -2072,95 +1534,6 @@ void Context::detachSampler(GLuint sampler) mState.detachSampler(sampler); } -Texture *Context::getIncompleteTexture(GLenum type) -{ - if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) - { - const GLubyte color[] = { 0, 0, 0, 255 }; - const PixelUnpackState incompleteUnpackState(1); - - Texture* t = NULL; - switch (type) - { - default: - UNREACHABLE(); - // default falls through to TEXTURE_2D - - case GL_TEXTURE_2D: - { - Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID); - incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - t = incomplete2d; - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID); - - incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incompleteCube; - } - break; - - case GL_TEXTURE_3D: - { - Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID); - incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incomplete3d; - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID); - incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incomplete2darray; - } - break; - } - - mIncompleteTextures[type].set(t); - } - - return mIncompleteTextures[type].get(); -} - -bool Context::skipDraw(GLenum drawMode) -{ - if (drawMode == GL_POINTS) - { - // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, - // which affects varying interpolation. Since the value of gl_PointSize is - // undefined when not written, just skip drawing to avoid unexpected results. - if (!mState.getCurrentProgramBinary()->usesPointSize()) - { - // This is stictly speaking not an error, but developers should be - // notified of risking undefined behavior. - ERR("Point rendering without writing to gl_PointSize."); - - return true; - } - } - else if (IsTriangleMode(drawMode)) - { - if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK) - { - return true; - } - } - - return false; -} - void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) { mState.getVertexArray()->setVertexAttribDivisor(index, divisor); @@ -2293,63 +1666,12 @@ size_t Context::getExtensionStringCount() const return mExtensionStrings.size(); } -size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray) +Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) { - size_t serialCount = 0; - - Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) - { - FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); - if (attachment && attachment->isTexture()) - { - Texture *texture = attachment->getTexture(); - (*outSerialArray)[serialCount++] = texture->getTextureSerial(); - } - } - - FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilAttachment && depthStencilAttachment->isTexture()) - { - Texture *depthStencilTexture = depthStencilAttachment->getTexture(); - (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); - } - - std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); - - return serialCount; -} - -void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - Framebuffer *readFramebuffer = mState.getReadFramebuffer(); - Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); - - bool blitRenderTarget = false; - bool blitDepth = false; - bool blitStencil = false; - if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer()) - { - blitRenderTarget = true; - } - if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) - { - blitStencil = true; - } - if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) - { - blitDepth = true; - } - - Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); - Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); - if (blitRenderTarget || blitDepth || blitStencil) - { - const Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; - mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, - blitRenderTarget, blitDepth, blitStencil, filter); - } + return mRenderer->blitFramebuffer(getData(), srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); } void Context::releaseShaderCompiler() @@ -2416,6 +1738,11 @@ void Context::initCaps(GLuint clientVersion) mExtensions.maxSamples = maxSamples; } +Data Context::getData() const +{ + return Data(mClientVersion, mState, mCaps, mTextureCaps, mExtensions, mResourceManager); +} + } extern "C" diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 1b888aec83..1e890de3ef 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -13,12 +13,12 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Constants.h" +#include "libGLESv2/Data.h" #include "libGLESv2/Error.h" #include "libGLESv2/HandleAllocator.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/State.h" +#include "libGLESv2/angletypes.h" #include "angle_gl.h" @@ -50,11 +50,6 @@ class Texture3D; class Texture2DArray; class Framebuffer; class Renderbuffer; -class RenderbufferStorage; -class Colorbuffer; -class Depthbuffer; -class Stencilbuffer; -class DepthStencilbuffer; class FenceNV; class FenceSync; class Query; @@ -68,7 +63,7 @@ class TransformFeedback; class Context { public: - Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); + Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); virtual ~Context(); @@ -86,7 +81,7 @@ class Context GLuint createRenderbuffer(); GLuint createSampler(); GLuint createTransformFeedback(); - GLsync createFenceSync(GLenum condition); + GLsync createFenceSync(); void deleteBuffer(GLuint buffer); void deleteShader(GLuint shader); @@ -115,7 +110,7 @@ class Context void bindArrayBuffer(GLuint buffer); void bindElementArrayBuffer(GLuint buffer); - void bindTexture(GLenum target, GLuint texture); + void bindTexture(GLenum target, GLuint handle); void bindReadFramebuffer(GLuint framebuffer); void bindDrawFramebuffer(GLuint framebuffer); void bindRenderbuffer(GLuint renderbuffer); @@ -130,8 +125,8 @@ class Context void bindPixelPackBuffer(GLuint buffer); void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); - void linkProgram(GLuint program); - void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); + Error linkProgram(GLuint program); + Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); void bindTransformFeedback(GLuint transformFeedback); Error beginQuery(GLenum target, GLuint query); @@ -139,8 +134,6 @@ class Context void setFramebufferZero(Framebuffer *framebuffer); - void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - void setVertexAttribDivisor(GLuint index, GLuint divisor); void samplerParameteri(GLuint sampler, GLenum pname, GLint param); @@ -183,17 +176,17 @@ class Context bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); Error clear(GLbitfield mask); - Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values); - Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values); - Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values); - Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil); + Error clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values); + Error clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values); + Error clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values); + Error clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances, const rx::RangeUI &indexRange); - void sync(bool block); // flush/finish + Error sync(bool block); // flush/finish void recordError(const Error &error); @@ -215,32 +208,21 @@ class Context void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type); - void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); + Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); rx::Renderer *getRenderer() { return mRenderer; } State &getState() { return mState; } const State &getState() const { return mState; } + Data getData() const; + void releaseShaderCompiler(); private: DISALLOW_COPY_AND_ASSIGN(Context); - // TODO: std::array may become unavailable using older versions of GCC - typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray; - - Error applyRenderTarget(GLenum drawMode, bool ignoreViewport); - Error applyState(GLenum drawMode); - Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); - Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials, - size_t framebufferSerialCount); - Error applyTextures(ProgramBinary *programBinary); - Error applyUniformBuffers(); - bool applyTransformFeedbackBuffers(); - void markTransformFeedbackUsage(); - void detachBuffer(GLuint buffer); void detachTexture(GLuint texture); void detachFramebuffer(GLuint framebuffer); @@ -249,18 +231,9 @@ class Context void detachTransformFeedback(GLuint transformFeedback); void detachSampler(GLuint sampler); - Error generateSwizzles(ProgramBinary *programBinary, SamplerType type); - Error generateSwizzles(ProgramBinary *programBinary); - - Texture *getIncompleteTexture(GLenum type); - - bool skipDraw(GLenum drawMode); - void initRendererString(); void initExtensionStrings(); - size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray); - void initCaps(GLuint clientVersion); // Caps to use for validation @@ -273,7 +246,6 @@ class Context int mClientVersion; - typedef std::map< GLenum, BindingPointer<Texture> > TextureMap; TextureMap mZeroTextures; TextureMap mIncompleteTextures; diff --git a/src/3rdparty/angle/src/libGLESv2/Data.cpp b/src/3rdparty/angle/src/libGLESv2/Data.cpp new file mode 100644 index 0000000000..3ddf591d77 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Data.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Data.cpp: Container class for all GL relevant state, caps and objects + +#include "libGLESv2/Data.h" +#include "libGLESv2/ResourceManager.h" + +namespace gl +{ + +Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn, + const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn, + const ResourceManager *resourceManagerIn) + : clientVersion(clientVersionIn), + state(&stateIn), + caps(&capsIn), + textureCaps(&textureCapsIn), + extensions(&extensionsIn), + resourceManager(resourceManagerIn) +{} + +Data::~Data() +{ +} + +Data::Data(const Data &other) + : clientVersion(other.clientVersion), + state(other.state), + caps(other.caps), + textureCaps(other.textureCaps), + extensions(other.extensions), + resourceManager(other.resourceManager) +{ +} + +Data &Data::operator=(const Data &other) +{ + clientVersion = other.clientVersion; + state = other.state; + caps = other.caps; + textureCaps = other.textureCaps; + extensions = other.extensions; + resourceManager = other.resourceManager; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h new file mode 100644 index 0000000000..9234403e13 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Data.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Data.h: Container class for all GL relevant state, caps and objects + +#ifndef LIBGLESV2_DATA_H_ +#define LIBGLESV2_DATA_H_ + +#include "libGLESv2/State.h" + +namespace gl +{ + +struct Data +{ + public: + Data(GLint clientVersion, const State &state, const Caps &caps, + const TextureCapsMap &textureCaps, const Extensions &extensions, + const ResourceManager *resourceManager); + ~Data(); + + Data(const Data &other); + Data &operator=(const Data &other); + + GLint clientVersion; + const State *state; + const Caps *caps; + const TextureCapsMap *textureCaps; + const Extensions *extensions; + const ResourceManager *resourceManager; +}; + +} + +#endif // LIBGLESV2_DATA_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp index ee9a07a5c4..966a327de5 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp @@ -4,191 +4,113 @@ // found in the LICENSE file. // -// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. - -// Important note on accurate timers in Windows: -// -// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call -// as timeGetTime on laptops and "jumping" during certain hardware events. -// -// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" -// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc -// -// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer -// from buggy implementations. +// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence +// extension and GLES3 sync objects. #include "libGLESv2/Fence.h" #include "libGLESv2/renderer/FenceImpl.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" +#include "common/utilities.h" #include "angle_gl.h" namespace gl { -FenceNV::FenceNV(rx::Renderer *renderer) +FenceNV::FenceNV(rx::FenceNVImpl *impl) + : mFence(impl), + mIsSet(false), + mStatus(GL_FALSE), + mCondition(GL_NONE) { - mFence = renderer->createFence(); } FenceNV::~FenceNV() { - delete mFence; + SafeDelete(mFence); } GLboolean FenceNV::isFence() const { // GL_NV_fence spec: // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return (mFence->isSet() ? GL_TRUE : GL_FALSE); + return (mIsSet ? GL_TRUE : GL_FALSE); } -void FenceNV::setFence(GLenum condition) +Error FenceNV::setFence(GLenum condition) { - mFence->set(); + Error error = mFence->set(); + if (error.isError()) + { + return error; + } mCondition = condition; mStatus = GL_FALSE; -} - -GLboolean FenceNV::testFence() -{ - // Flush the command buffer by default - bool result = mFence->test(true); + mIsSet = true; - mStatus = (result ? GL_TRUE : GL_FALSE); - return mStatus; + return Error(GL_NO_ERROR); } -void FenceNV::finishFence() +Error FenceNV::testFence(GLboolean *outResult) { - ASSERT(mFence->isSet()); - - while (!mFence->test(true)) + // Flush the command buffer by default + Error error = mFence->test(true, &mStatus); + if (error.isError()) { - Sleep(0); + return error; } -} - -GLint FenceNV::getFencei(GLenum pname) -{ - ASSERT(mFence->isSet()); - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (mStatus == GL_TRUE) - { - return GL_TRUE; - } - - mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE); - return mStatus; - } - - case GL_FENCE_CONDITION_NV: - return mCondition; - - default: UNREACHABLE(); return 0; - } + *outResult = mStatus; + return Error(GL_NO_ERROR); } -FenceSync::FenceSync(rx::Renderer *renderer, GLuint id) - : RefCountObject(id) +Error FenceNV::finishFence() { - mFence = renderer->createFence(); - - LARGE_INTEGER counterFreqency = { 0 }; - BOOL success = QueryPerformanceFrequency(&counterFreqency); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); + ASSERT(mIsSet); - mCounterFrequency = counterFreqency.QuadPart; + return mFence->finishFence(&mStatus); } -FenceSync::~FenceSync() +FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id) + : RefCountObject(id), + mFence(impl), + mCondition(GL_NONE) { - delete mFence; } -void FenceSync::set(GLenum condition) +FenceSync::~FenceSync() { - mCondition = condition; - mFence->set(); + SafeDelete(mFence); } -GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout) +Error FenceSync::set(GLenum condition) { - ASSERT(mFence->isSet()); - - bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); - - if (mFence->test(flushCommandBuffer)) + Error error = mFence->set(); + if (error.isError()) { - return GL_ALREADY_SIGNALED; + return error; } - if (mFence->hasError()) - { - return GL_WAIT_FAILED; - } - - if (timeout == 0) - { - return GL_TIMEOUT_EXPIRED; - } - - LARGE_INTEGER currentCounter = { 0 }; - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - - LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll); - LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; - - while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer)) - { - Sleep(0); - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - } - - if (mFence->hasError()) - { - return GL_WAIT_FAILED; - } - - if (currentCounter.QuadPart >= endCounter) - { - return GL_TIMEOUT_EXPIRED; - } - - return GL_CONDITION_SATISFIED; + mCondition = condition; + return Error(GL_NO_ERROR); } -void FenceSync::serverWait() +Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) { - // Because our API is currently designed to be called from a single thread, we don't need to do - // extra work for a server-side fence. GPU commands issued after the fence is created will always - // be processed after the fence is signaled. + ASSERT(mCondition != GL_NONE); + return mFence->clientWait(flags, timeout, outResult); } -GLenum FenceSync::getStatus() const +Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout) { - if (mFence->test(false)) - { - // The spec does not specify any way to report errors during the status test (e.g. device lost) - // so we report the fence is unblocked in case of error or signaled. - return GL_SIGNALED; - } + return mFence->serverWait(flags, timeout); +} - return GL_UNSIGNALED; +Error FenceSync::getStatus(GLint *outResult) const +{ + return mFence->getStatus(outResult); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h index 291edb3de1..fd565e96a6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.h +++ b/src/3rdparty/angle/src/libGLESv2/Fence.h @@ -4,18 +4,21 @@ // found in the LICENSE file. // -// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension. +// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence +// extension and GLES3 sync objects. #ifndef LIBGLESV2_FENCE_H_ #define LIBGLESV2_FENCE_H_ +#include "libGLESv2/Error.h" + #include "common/angleutils.h" #include "common/RefCountObject.h" namespace rx { -class Renderer; -class FenceImpl; +class FenceNVImpl; +class FenceSyncImpl; } namespace gl @@ -24,14 +27,13 @@ namespace gl class FenceNV { public: - explicit FenceNV(rx::Renderer *renderer); + explicit FenceNV(rx::FenceNVImpl *impl); virtual ~FenceNV(); GLboolean isFence() const; - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - GLint getFencei(GLenum pname); + Error setFence(GLenum condition); + Error testFence(GLboolean *outResult); + Error finishFence(); GLboolean getStatus() const { return mStatus; } GLuint getCondition() const { return mCondition; } @@ -39,7 +41,9 @@ class FenceNV private: DISALLOW_COPY_AND_ASSIGN(FenceNV); - rx::FenceImpl *mFence; + rx::FenceNVImpl *mFence; + + bool mIsSet; GLboolean mStatus; GLenum mCondition; @@ -48,21 +52,20 @@ class FenceNV class FenceSync : public RefCountObject { public: - explicit FenceSync(rx::Renderer *renderer, GLuint id); + explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id); virtual ~FenceSync(); - void set(GLenum condition); - GLenum clientWait(GLbitfield flags, GLuint64 timeout); - void serverWait(); - GLenum getStatus() const; + Error set(GLenum condition); + Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); + Error serverWait(GLbitfield flags, GLuint64 timeout); + Error getStatus(GLint *outResult) const; GLuint getCondition() const { return mCondition; } private: DISALLOW_COPY_AND_ASSIGN(FenceSync); - rx::FenceImpl *mFence; - LONGLONG mCounterFrequency; + rx::FenceSyncImpl *mFence; GLenum mCondition; }; diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index 5b21433f90..3d57262e3c 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -16,13 +16,18 @@ #include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/RenderbufferImpl.h" +#include "libGLESv2/renderer/Workarounds.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" #include "common/utilities.h" namespace rx { -RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +// TODO: Move these functions, and the D3D-specific header inclusions above, +// to FramebufferD3D. +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT) { if (attachment->isTexture()) { @@ -31,14 +36,16 @@ RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); const gl::ImageIndex *index = attachment->getTextureImageIndex(); ASSERT(index); - return textureD3D->getRenderTarget(*index); + return textureD3D->getRenderTarget(*index, outRT); + } + else + { + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + *outRT = renderbufferD3D->getRenderTarget(); + return gl::Error(GL_NO_ERROR); } - - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - - // TODO: cast to RenderbufferD3D - return renderbuffer->getStorage()->getRenderTarget(); } // Note: RenderTarget serials should ideally be in the RenderTargets themselves. @@ -56,9 +63,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); ASSERT(renderbuffer); - - // TODO: cast to RenderbufferD3D - return renderbuffer->getStorage()->getSerial(); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + return renderbufferD3D->getRenderTargetSerial(); } } @@ -66,9 +72,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) namespace gl { -Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id) - : mRenderer(renderer), - mId(id), +Framebuffer::Framebuffer(GLuint id) + : mId(id), mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), mDepthbuffer(NULL), mStencilbuffer(NULL) @@ -91,124 +96,6 @@ Framebuffer::~Framebuffer() SafeDelete(mStencilbuffer); } -FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const -{ - if (handle == 0) - { - return NULL; - } - - gl::Context *context = gl::getContext(); - - switch (type) - { - case GL_NONE: - return NULL; - - case GL_RENDERBUFFER: - return new RenderbufferAttachment(binding, context->getRenderbuffer(handle)); - - case GL_TEXTURE_2D: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_2D) - { - return new TextureAttachment(binding, texture, ImageIndex::Make2D(level)); - } - else - { - return NULL; - } - } - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) - { - return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level)); - } - else - { - return NULL; - } - } - - case GL_TEXTURE_3D: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_3D) - { - return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer)); - } - else - { - return NULL; - } - } - - case GL_TEXTURE_2D_ARRAY: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) - { - return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer)); - } - else - { - return NULL; - } - } - - default: - UNREACHABLE(); - return NULL; - } -} - -void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer) -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - SafeDelete(mColorbuffers[colorAttachment]); - GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0; - mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer); -} - -void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) -{ - SafeDelete(mDepthbuffer); - mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer); -} - -void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) -{ - SafeDelete(mStencilbuffer); - mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer); -} - -void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) -{ - FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); - - SafeDelete(mDepthbuffer); - SafeDelete(mStencilbuffer); - - // ensure this is a legitimate depth+stencil format - if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0) - { - mDepthbuffer = attachment; - - // Make a new attachment object to ensure we do not double-delete - // See angle issue 686 - mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); - } -} - void Framebuffer::detachTexture(GLuint textureId) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) @@ -382,14 +269,13 @@ bool Framebuffer::usingExtendedDrawBuffers() const return false; } -GLenum Framebuffer::completeness() const +GLenum Framebuffer::completeness(const gl::Data &data) const { int width = 0; int height = 0; unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; - GLuint clientVersion = mRenderer->getCurrentClientVersion(); for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { @@ -403,8 +289,7 @@ GLenum Framebuffer::completeness() const } GLenum internalformat = colorbuffer->getInternalFormat(); - // TODO(geofflang): use context's texture caps - const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorbuffer->isTexture()) { @@ -443,7 +328,7 @@ GLenum Framebuffer::completeness() const // in GLES 2.0, all color attachments attachments must have the same number of bitplanes // in GLES 3.0, there is no such restriction - if (clientVersion < 3) + if (data.clientVersion < 3) { if (formatInfo.pixelBytes != colorbufferSize) { @@ -483,14 +368,12 @@ GLenum Framebuffer::completeness() const } GLenum internalformat = mDepthbuffer->getInternalFormat(); - // TODO(geofflang): use context's texture caps - const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mDepthbuffer->isTexture()) { // depth texture attachments require OES/ANGLE_depth_texture - // TODO(geofflang): use context's extensions - if (!mRenderer->getRendererExtensions().depthTextures) + if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -538,15 +421,13 @@ GLenum Framebuffer::completeness() const } GLenum internalformat = mStencilbuffer->getInternalFormat(); - // TODO(geofflang): use context's texture caps - const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mStencilbuffer->isTexture()) { // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - // TODO(geofflang): use context's extensions - if (!mRenderer->getRendererExtensions().depthTextures) + if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -602,42 +483,44 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } -void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) +Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) { GLuint maxDimension = caps.maxRenderbufferSize; - invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension); + return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension); } -void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, - GLint x, GLint y, GLsizei width, GLsizei height) +Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) { - ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE); for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex) { GLenum attachmentTarget = attachments[attachIndex]; - gl::FramebufferAttachment *attachment = - (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() : - getAttachment(attachmentTarget); + FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() + : getAttachment(attachmentTarget); if (attachment) { - rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); - if (renderTarget) + rx::RenderTarget *renderTarget = NULL; + Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - renderTarget->invalidate(x, y, width, height); + return error; } + + renderTarget->invalidate(x, y, width, height); } } + + return Error(GL_NO_ERROR); } -DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) - : Framebuffer(renderer, 0) +DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil) + : Framebuffer(0) { - Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer); + Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0); mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer); - Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil); + Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0); // Make a new attachment objects to ensure we do not double-delete // See angle issue 686 @@ -648,9 +531,9 @@ DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colo mReadBufferState = GL_BACK; } -int Framebuffer::getSamples() const +int Framebuffer::getSamples(const gl::Data &data) const { - if (completeness() == GL_FRAMEBUFFER_COMPLETE) + if (completeness(data) == GL_FRAMEBUFFER_COMPLETE) { // for a complete framebuffer, all attachments must have the same sample count // in this case return the first nonzero sample size @@ -675,7 +558,7 @@ bool Framebuffer::hasValidDepthStencil() const mDepthbuffer->id() == mStencilbuffer->id()); } -ColorbufferInfo Framebuffer::getColorbuffersForRender() const +ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const { ColorbufferInfo colorbuffersForRender; @@ -689,18 +572,78 @@ ColorbufferInfo Framebuffer::getColorbuffersForRender() const ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); colorbuffersForRender.push_back(colorbuffer); } -#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED) - else + else if (!workarounds.mrtPerfWorkaround) { colorbuffersForRender.push_back(NULL); } -#endif } return colorbuffersForRender; } -GLenum DefaultFramebuffer::completeness() const +void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex) +{ + setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex)); +} + +void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer) +{ + setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer)); +} + +void Framebuffer::setNULLAttachment(GLenum attachment) +{ + setAttachment(attachment, NULL); +} + +void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj) +{ + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS)) + { + size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0; + SafeDelete(mColorbuffers[colorAttachment]); + mColorbuffers[colorAttachment] = attachmentObj; + } + else if (attachment == GL_DEPTH_ATTACHMENT) + { + SafeDelete(mDepthbuffer); + mDepthbuffer = attachmentObj; + } + else if (attachment == GL_STENCIL_ATTACHMENT) + { + SafeDelete(mStencilbuffer); + mStencilbuffer = attachmentObj; + } + else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) + { + SafeDelete(mDepthbuffer); + SafeDelete(mStencilbuffer); + + // ensure this is a legitimate depth+stencil format + if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0) + { + mDepthbuffer = attachmentObj; + + // Make a new attachment object to ensure we do not double-delete + // See angle issue 686 + if (attachmentObj->isTexture()) + { + mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(), + *attachmentObj->getTextureImageIndex()); + } + else + { + mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer()); + } + } + } + else + { + UNREACHABLE(); + } +} + +GLenum DefaultFramebuffer::completeness(const gl::Data &) const { // The default framebuffer *must* always be complete, though it may not be // subject to the same rules as application FBOs. ie, it could have 0x0 size. diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index cc12d22953..d0fe8935ea 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -10,41 +10,44 @@ #ifndef LIBGLESV2_FRAMEBUFFER_H_ #define LIBGLESV2_FRAMEBUFFER_H_ -#include <vector> +#include "libGLESv2/Error.h" #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "constants.h" +#include "Constants.h" + +#include <vector> namespace rx { -class Renderer; +class RenderbufferImpl; +struct Workarounds; } namespace gl { class FramebufferAttachment; -class Colorbuffer; -class Depthbuffer; -class Stencilbuffer; -class DepthStencilbuffer; +class Texture; +class Renderbuffer; +struct ImageIndex; struct Caps; +struct Extensions; +class TextureCapsMap; +struct Data; typedef std::vector<FramebufferAttachment *> ColorbufferInfo; class Framebuffer { public: - Framebuffer(rx::Renderer *renderer, GLuint id); - + Framebuffer(GLuint id); virtual ~Framebuffer(); GLuint id() const { return mId; } - void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer); - void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer); - void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer); - void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer); + void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex); + void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer); + void setNULLAttachment(GLenum attachment); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); @@ -66,24 +69,21 @@ class Framebuffer bool isEnabledColorAttachment(unsigned int colorAttachment) const; bool hasEnabledColorAttachment() const; bool hasStencil() const; - int getSamples() const; + int getSamples(const gl::Data &data) const; bool usingExtendedDrawBuffers() const; - virtual GLenum completeness() const; + virtual GLenum completeness(const gl::Data &data) const; bool hasValidDepthStencil() const; - void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); - void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, - GLint x, GLint y, GLsizei width, GLsizei height); + Error invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); + Error invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); // Use this method to retrieve the color buffer map when doing rendering. // It will apply a workaround for poor shader performance on some systems // by compacting the list to skip NULL values. - ColorbufferInfo getColorbuffersForRender() const; + ColorbufferInfo getColorbuffersForRender(const rx::Workarounds &workarounds) const; protected: - rx::Renderer *mRenderer; - GLuint mId; FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; @@ -96,15 +96,15 @@ class Framebuffer private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); - FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const; + void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); }; class DefaultFramebuffer : public Framebuffer { public: - DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); + DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil); - virtual GLenum completeness() const; + GLenum completeness(const gl::Data &data) const override; virtual FramebufferAttachment *getAttachment(GLenum attachment) const; private: @@ -118,7 +118,7 @@ namespace rx class RenderTarget; // TODO: place this in FramebufferD3D.h -RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT); unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment); } diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp index 540ede1cd2..894884a6d8 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp @@ -187,7 +187,7 @@ GLenum RenderbufferAttachment::getActualFormat() const GLsizei RenderbufferAttachment::getSamples() const { - return mRenderbuffer->getStorage()->getSamples(); + return mRenderbuffer->getSamples(); } GLuint RenderbufferAttachment::id() const diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h index c18ef7364d..8d2dafa7ee 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h @@ -16,13 +16,6 @@ #include "angle_gl.h" -namespace rx -{ -class Renderer; -class RenderTarget; -class TextureStorage; -} - namespace gl { class Renderbuffer; diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp index 3522b997e8..b45cd9c169 100644 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp @@ -48,10 +48,101 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex); } +ImageIndex ImageIndex::MakeInvalid() +{ + return ImageIndex(GL_NONE, -1, -1); +} + ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) : type(typeIn), mipIndex(mipIndexIn), layerIndex(layerIndexIn) {} +ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip) +{ + return ImageIndexIterator(GL_TEXTURE_2D, rx::Range<GLint>(minMip, maxMip), + rx::Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL); +} + +ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip) +{ + return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(0, 6), NULL); +} + +ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip, + GLint minLayer, GLint maxLayer) +{ + return ImageIndexIterator(GL_TEXTURE_3D, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(minLayer, maxLayer), NULL); +} + +ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip, + const GLsizei *layerCounts) +{ + return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range<GLint>(minMip, maxMip), + rx::Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts); +} + +ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange, + const rx::Range<GLint> &layerRange, const GLsizei *layerCounts) + : mType(type), + mMipRange(mipRange), + mLayerRange(layerRange), + mLayerCounts(layerCounts), + mCurrentMip(mipRange.start), + mCurrentLayer(layerRange.start) +{} + +GLint ImageIndexIterator::maxLayer() const +{ + return (mLayerCounts ? static_cast<GLint>(mLayerCounts[mCurrentMip]) : mLayerRange.end); +} + +ImageIndex ImageIndexIterator::next() +{ + ASSERT(hasNext()); + + ImageIndex value = current(); + + // Iterate layers in the inner loop for now. We can add switchable + // layer or mip iteration if we need it. + + if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL) + { + if (mCurrentLayer < maxLayer()-1) + { + mCurrentLayer++; + } + else if (mCurrentMip < mMipRange.end-1) + { + mCurrentMip++; + mCurrentLayer = mLayerRange.start; + } + } + else if (mCurrentMip < mMipRange.end-1) + { + mCurrentMip++; + mCurrentLayer = mLayerRange.start; + } + + return value; +} + +ImageIndex ImageIndexIterator::current() const +{ + ImageIndex value(mType, mCurrentMip, mCurrentLayer); + + if (mType == GL_TEXTURE_CUBE_MAP) + { + value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer); + } + + return value; +} + +bool ImageIndexIterator::hasNext() const +{ + return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer()); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h index 9f2df88061..8bb14fd555 100644 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h @@ -10,6 +10,7 @@ #define LIBGLESV2_IMAGE_INDEX_H_ #include "angle_gl.h" +#include "common/mathutil.h" namespace gl { @@ -20,6 +21,7 @@ struct ImageIndex GLint mipIndex; GLint layerIndex; + ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); ImageIndex(const ImageIndex &other); ImageIndex &operator=(const ImageIndex &other); @@ -29,11 +31,36 @@ struct ImageIndex static ImageIndex MakeCube(GLenum target, GLint mipIndex); static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex); static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL); + static ImageIndex MakeInvalid(); static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1); +}; + +class ImageIndexIterator +{ + public: + static ImageIndexIterator Make2D(GLint minMip, GLint maxMip); + static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip); + static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); + static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); + + ImageIndex next(); + ImageIndex current() const; + bool hasNext() const; private: - ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); + + ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange, + const rx::Range<GLint> &layerRange, const GLsizei *layerCounts); + + GLint maxLayer() const; + + GLenum mType; + rx::Range<GLint> mMipRange; + rx::Range<GLint> mLayerRange; + const GLsizei *mLayerCounts; + GLint mCurrentMip; + GLint mCurrentLayer; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp index 9bfda09a64..3faa8c56f6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp @@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name) // Links the HLSL code of the vertex and pixel shader by matching up their varyings, // compiling them into binaries, determining the attribute mappings, and collecting // a list of uniforms -bool Program::link(const Caps &caps) +Error Program::link(const Data &data) { unlink(false); @@ -252,10 +252,15 @@ bool Program::link(const Caps &caps) resetUniformBlockBindings(); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); + LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, + mTransformFeedbackVaryings, mTransformFeedbackBufferMode); + if (result.error.isError()) + { + return result.error; + } - return mLinked; + mLinked = result.linkSuccess; + return gl::Error(GL_NO_ERROR); } int AttributeBindings::getAttributeBinding(const std::string &name) const @@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const return mProgramBinary.get(); } -bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) +Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) { unlink(false); mInfoLog.reset(); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); - - if (!mLinked) + LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); + if (result.error.isError()) { mProgramBinary.set(NULL); + return result.error; } - return mLinked; + mLinked = result.linkSuccess; + return Error(GL_NO_ERROR); } void Program::release() diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h index 6528dd1191..b92349eeef 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ b/src/3rdparty/angle/src/libGLESv2/Program.h @@ -29,6 +29,7 @@ class Renderer; namespace gl { struct Caps; +struct Data; class ResourceManager; class Shader; @@ -77,9 +78,9 @@ class Program void bindAttributeLocation(GLuint index, const char *name); - bool link(const Caps &caps); + Error link(const Data &data); bool isLinked(); - bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); + Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); ProgramBinary *getProgramBinary() const; int getInfoLogLength() const; diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 3f6d9e0ef9..6d64b38b56 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -23,13 +23,11 @@ #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/ProgramImpl.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" #include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/Context.h" #include "libGLESv2/Buffer.h" #include "common/blocklayout.h" +#include "common/features.h" namespace gl { @@ -37,36 +35,6 @@ namespace gl namespace { -GLenum GetTextureType(GLenum samplerType) -{ - switch (samplerType) - { - case GL_SAMPLER_2D: - case GL_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_SAMPLER_2D_SHADOW: - return GL_TEXTURE_2D; - case GL_SAMPLER_3D: - case GL_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_3D: - return GL_TEXTURE_3D; - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return GL_TEXTURE_CUBE_MAP; - case GL_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - return GL_TEXTURE_CUBE_MAP; - case GL_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_ARRAY_SHADOW: - return GL_TEXTURE_2D_ARRAY; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; -} - unsigned int ParseAndStripArrayIndex(std::string* name) { unsigned int subscript = GL_INVALID_INDEX; @@ -83,52 +51,6 @@ unsigned int ParseAndStripArrayIndex(std::string* name) return subscript; } -void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) -{ - size_t layoutIndex = 0; - for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) - { - ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS); - - const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; - - if (shaderAttr.type != GL_NONE) - { - GLenum transposedType = TransposeMatrixType(shaderAttr.type); - - for (size_t rowIndex = 0; static_cast<int>(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++) - { - VertexFormat *defaultFormat = &inputLayout[layoutIndex]; - - defaultFormat->mType = VariableComponentType(transposedType); - defaultFormat->mNormalized = false; - defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool - defaultFormat->mComponents = VariableColumnCount(transposedType); - } - } - } -} - -std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<rx::PixelShaderOutputVariable> &shaderOutputVars) -{ - std::vector<GLenum> defaultPixelOutput(1); - - ASSERT(!shaderOutputVars.empty()); - defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; - - return defaultPixelOutput; -} - -bool IsRowMajorLayout(const sh::InterfaceBlockField &var) -{ - return var.isRowMajorLayout; -} - -bool IsRowMajorLayout(const sh::ShaderVariable &var) -{ - return false; -} - } VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) @@ -136,47 +58,6 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element { } -ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[], - const GLenum signature[], - rx::ShaderExecutable *shaderExecutable) - : mShaderExecutable(shaderExecutable) -{ - for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - mInputs[attributeIndex] = inputLayout[attributeIndex]; - mSignature[attributeIndex] = signature[attributeIndex]; - } -} - -ProgramBinary::VertexExecutable::~VertexExecutable() -{ - SafeDelete(mShaderExecutable); -} - -bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const -{ - for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (mSignature[attributeIndex] != signature[attributeIndex]) - { - return false; - } - } - - return true; -} - -ProgramBinary::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable) - : mOutputSignature(outputSignature), - mShaderExecutable(shaderExecutable) -{ -} - -ProgramBinary::PixelExecutable::~PixelExecutable() -{ - SafeDelete(mShaderExecutable); -} - LinkedVarying::LinkedVarying() { } @@ -187,17 +68,17 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, { } +LinkResult::LinkResult(bool linkSuccess, const Error &error) + : linkSuccess(linkSuccess), + error(error) +{ +} + unsigned int ProgramBinary::mCurrentSerial = 1; ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) : RefCountObject(0), mProgram(impl), - mGeometryExecutable(NULL), - mUsedVertexSamplerRange(0), - mUsedPixelSamplerRange(0), - mUsesPointSize(false), - mShaderVersion(100), - mDirtySamplerMapping(true), mValidated(false), mSerial(issueSerial()) { @@ -220,103 +101,11 @@ unsigned int ProgramBinary::getSerial() const return mSerial; } -int ProgramBinary::getShaderVersion() const -{ - return mShaderVersion; -} - unsigned int ProgramBinary::issueSerial() { return mCurrentSerial++; } -rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo) -{ - std::vector<GLenum> outputs; - - const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(); - - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - - if (colorbuffer) - { - outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); - } - else - { - outputs.push_back(GL_NONE); - } - } - - return getPixelExecutableForOutputLayout(outputs); -} - -rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature) -{ - for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) - { - if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) - { - return mPixelExecutables[executableIndex]->shaderExecutable(); - } - } - - InfoLog tempInfoLog; - rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature, - mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!pixelExecutable) - { - std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); - ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); - } - else - { - mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); - } - - return pixelExecutable; -} - -rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) -{ - GLenum signature[MAX_VERTEX_ATTRIBS]; - mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); - - for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) - { - if (mVertexExecutables[executableIndex]->matchesSignature(signature)) - { - return mVertexExecutables[executableIndex]->shaderExecutable(); - } - } - - InfoLog tempInfoLog; - rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes, - mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!vertexExecutable) - { - std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); - ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); - } - else - { - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); - } - - return vertexExecutable; -} - -rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const -{ - return mGeometryExecutable; -} - GLuint ProgramBinary::getAttributeLocation(const char *name) { if (name) @@ -343,157 +132,42 @@ int ProgramBinary::getSemanticIndex(int attributeIndex) // Returns one more than the highest sampler index used. GLint ProgramBinary::getUsedSamplerRange(SamplerType type) { - switch (type) - { - case SAMPLER_PIXEL: - return mUsedPixelSamplerRange; - case SAMPLER_VERTEX: - return mUsedVertexSamplerRange; - default: - UNREACHABLE(); - return 0; - } + return mProgram->getUsedSamplerRange(type); } bool ProgramBinary::usesPointSize() const { - return mUsesPointSize; -} - -bool ProgramBinary::usesPointSpriteEmulation() const -{ - return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4; -} - -bool ProgramBinary::usesGeometryShader() const -{ - return usesPointSpriteEmulation(); + return mProgram->usesPointSize(); } GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) { - GLint logicalTextureUnit = -1; - - switch (type) - { - case SAMPLER_PIXEL: - ASSERT(samplerIndex < caps.maxTextureImageUnits); - if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) - { - logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; - } - break; - case SAMPLER_VERTEX: - ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); - if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) - { - logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; - } - break; - default: UNREACHABLE(); - } - - if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast<GLint>(caps.maxCombinedTextureImageUnits)) - { - return logicalTextureUnit; - } - - return -1; + return mProgram->getSamplerMapping(type, samplerIndex, caps); } -// Returns the texture type for a given Direct3D 9 sampler type and -// index (0-15 for the pixel shader and 0-3 for the vertex shader). GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) { - switch (type) - { - case SAMPLER_PIXEL: - ASSERT(samplerIndex < mSamplersPS.size()); - ASSERT(mSamplersPS[samplerIndex].active); - return mSamplersPS[samplerIndex].textureType; - case SAMPLER_VERTEX: - ASSERT(samplerIndex < mSamplersVS.size()); - ASSERT(mSamplersVS[samplerIndex].active); - return mSamplersVS[samplerIndex].textureType; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; + return mProgram->getSamplerTextureType(type, samplerIndex); } GLint ProgramBinary::getUniformLocation(std::string name) { - unsigned int subscript = ParseAndStripArrayIndex(&name); - - unsigned int numUniforms = mUniformIndex.size(); - for (unsigned int location = 0; location < numUniforms; location++) - { - if (mUniformIndex[location].name == name) - { - const int index = mUniformIndex[location].index; - const bool isArray = mUniforms[index]->isArray(); - - if ((isArray && mUniformIndex[location].element == subscript) || - (subscript == GL_INVALID_INDEX)) - { - return location; - } - } - } - - return -1; + return mProgram->getUniformLocation(name); } GLuint ProgramBinary::getUniformIndex(std::string name) { - unsigned int subscript = ParseAndStripArrayIndex(&name); - - // The app is not allowed to specify array indices other than 0 for arrays of basic types - if (subscript != 0 && subscript != GL_INVALID_INDEX) - { - return GL_INVALID_INDEX; - } - - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) - { - if (mUniforms[index]->name == name) - { - if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX) - { - return index; - } - } - } - - return GL_INVALID_INDEX; + return mProgram->getUniformIndex(name); } GLuint ProgramBinary::getUniformBlockIndex(std::string name) { - unsigned int subscript = ParseAndStripArrayIndex(&name); - - unsigned int numUniformBlocks = mUniformBlocks.size(); - for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) - { - const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex]; - if (uniformBlock.name == name) - { - const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); - if (subscript == uniformBlock.elementIndex || arrayElementZero) - { - return blockIndex; - } - } - } - - return GL_INVALID_INDEX; + return mProgram->getUniformBlockIndex(name); } UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex) { - ASSERT(blockIndex < mUniformBlocks.size()); - return mUniformBlocks[blockIndex]; + return mProgram->getUniformBlockByIndex(blockIndex); } GLint ProgramBinary::getFragDataLocation(const char *name) const @@ -517,524 +191,129 @@ GLint ProgramBinary::getFragDataLocation(const char *name) const size_t ProgramBinary::getTransformFeedbackVaryingCount() const { - return mTransformFeedbackLinkedVaryings.size(); + return mProgram->getTransformFeedbackLinkedVaryings().size(); } const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const { - return mTransformFeedbackLinkedVaryings[idx]; + return mProgram->getTransformFeedbackLinkedVaryings()[idx]; } GLenum ProgramBinary::getTransformFeedbackBufferMode() const { - return mTransformFeedbackBufferMode; -} - -template <typename T> -static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) -{ - ASSERT(dest != NULL); - ASSERT(dirtyFlag != NULL); - - *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); - *dest = source; -} - -template <typename T> -void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) -{ - const int components = VariableComponentCount(targetUniformType); - const GLenum targetBoolType = VariableBoolVectorType(targetUniformType); - - LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == targetUniformType) - { - T *target = reinterpret_cast<T*>(targetUniform->data) + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - T *dest = target + (i * 4); - const T *source = v + (i * components); - - for (int c = 0; c < components; c++) - { - SetIfDirty(dest + c, source[c], &targetUniform->dirty); - } - for (int c = components; c < 4; c++) - { - SetIfDirty(dest + c, T(0), &targetUniform->dirty); - } - } - } - else if (targetUniform->type == targetBoolType) - { - GLint *boolParams = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - GLint *dest = boolParams + (i * 4); - const T *source = v + (i * components); - - for (int c = 0; c < components; c++) - { - SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); - } - for (int c = components; c < 4; c++) - { - SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); - } - } - } - else if (IsSampler(targetUniform->type)) - { - ASSERT(targetUniformType == GL_INT); - - GLint *target = reinterpret_cast<GLint*>(targetUniform->data) + mUniformIndex[location].element * 4; - - bool wasDirty = targetUniform->dirty; - - for (int i = 0; i < count; i++) - { - GLint *dest = target + (i * 4); - const GLint *source = reinterpret_cast<const GLint*>(v) + (i * components); - - SetIfDirty(dest + 0, source[0], &targetUniform->dirty); - SetIfDirty(dest + 1, 0, &targetUniform->dirty); - SetIfDirty(dest + 2, 0, &targetUniform->dirty); - SetIfDirty(dest + 3, 0, &targetUniform->dirty); - } - - if (!wasDirty && targetUniform->dirty) - { - mDirtySamplerMapping = true; - } - } - else UNREACHABLE(); -} - -void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) -{ - setUniform(location, count, v, GL_FLOAT); + return mProgram->getTransformFeedbackBufferMode(); } -void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC2); -} - -void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC3); -} - -void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC4); -} - -template<typename T> -bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetHeight, srcWidth); - int copyHeight = std::min(targetWidth, srcHeight); - - for (int x = 0; x < copyWidth; x++) - { - for (int y = 0; y < copyHeight; y++) - { - SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyWidth; y++) - { - for (int x = copyHeight; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyWidth; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - - return dirty; -} - -template<typename T> -bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetWidth, srcWidth); - int copyHeight = std::min(targetHeight, srcHeight); - - for (int y = 0; y < copyHeight; y++) - { - for (int x = 0; x < copyWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyHeight; y++) - { - for (int x = copyWidth; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyHeight; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty); - } - } - - return dirty; +void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform1fv(location, count, v); } -template <int cols, int rows> -void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) -{ - LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - const unsigned int targetMatrixStride = (4 * rows); - GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); - - for (int i = 0; i < count; i++) - { - // Internally store matrices as transposed versions to accomodate HLSL matrix indexing - if (transpose == GL_FALSE) - { - targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty; - } - else - { - targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty; - } - target += targetMatrixStride; - value += cols * rows; - } +void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform2fv(location, count, v); } -void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); +void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform3fv(location, count, v); } -void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); +void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform4fv(location, count, v); } -void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); +void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform1iv(location, count, v); } -void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); +void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform2iv(location, count, v); } -void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); +void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform3iv(location, count, v); } -void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); +void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform4iv(location, count, v); } -void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); +void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform1uiv(location, count, v); } -void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); +void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform2uiv(location, count, v); } -void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); +void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform3uiv(location, count, v); } -void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT); +void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform4uiv(location, count, v); } -void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC2); +void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix2fv(location, count, transpose, v); } -void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC3); +void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix3fv(location, count, transpose, v); } -void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC4); +void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix4fv(location, count, transpose, v); } -void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT); +void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix2x3fv(location, count, transpose, v); } -void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); +void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix2x4fv(location, count, transpose, v); } -void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); +void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix3x2fv(location, count, transpose, v); } -void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); +void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix3x4fv(location, count, transpose, v); } -template <typename T> -void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType) -{ - LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - - if (IsMatrixType(targetUniform->type)) - { - const int rows = VariableRowCount(targetUniform->type); - const int cols = VariableColumnCount(targetUniform->type); - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); - } - else if (uniformType == VariableComponentType(targetUniform->type)) - { - unsigned int size = VariableComponentCount(targetUniform->type); - memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), - size * sizeof(T)); - } - else - { - unsigned int size = VariableComponentCount(targetUniform->type); - switch (VariableComponentType(targetUniform->type)) - { - case GL_BOOL: - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1); - } - } - break; - - case GL_FLOAT: - { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast<T>(floatParams[i]); - } - } - break; - - case GL_INT: - { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast<T>(intParams[i]); - } - } - break; - - case GL_UNSIGNED_INT: - { - GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast<T>(uintParams[i]); - } - } - break; - - default: UNREACHABLE(); - } - } +void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix4x2fv(location, count, transpose, v); } -void ProgramBinary::getUniformfv(GLint location, GLfloat *params) -{ - getUniformv(location, params, GL_FLOAT); +void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix4x3fv(location, count, transpose, v); } -void ProgramBinary::getUniformiv(GLint location, GLint *params) -{ - getUniformv(location, params, GL_INT); +void ProgramBinary::getUniformfv(GLint location, GLfloat *v) { + mProgram->getUniformfv(location, v); } -void ProgramBinary::getUniformuiv(GLint location, GLuint *params) -{ - getUniformv(location, params, GL_UNSIGNED_INT); +void ProgramBinary::getUniformiv(GLint location, GLint *v) { + mProgram->getUniformiv(location, v); } -void ProgramBinary::dirtyAllUniforms() -{ - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) - { - mUniforms[index]->dirty = true; - } +void ProgramBinary::getUniformuiv(GLint location, GLuint *v) { + mProgram->getUniformuiv(location, v); } void ProgramBinary::updateSamplerMapping() { - if (!mDirtySamplerMapping) - { - return; - } - - mDirtySamplerMapping = false; - - // Retrieve sampler uniform values - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - LinkedUniform *targetUniform = mUniforms[uniformIndex]; - - if (targetUniform->dirty) - { - if (IsSampler(targetUniform->type)) - { - int count = targetUniform->elementCount(); - GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data); - - if (targetUniform->isReferencedByFragmentShader()) - { - unsigned int firstIndex = targetUniform->psRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersPS.size()) - { - ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - - if (targetUniform->isReferencedByVertexShader()) - { - unsigned int firstIndex = targetUniform->vsRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersVS.size()) - { - ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - } - } - } + return mProgram->updateSamplerMapping(); } // Applies all the uniforms set for this program object to the renderer Error ProgramBinary::applyUniforms() { - updateSamplerMapping(); - - Error error = mProgram->getRenderer()->applyUniforms(*this); - if (error.isError()) - { - return error; - } - - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - mUniforms[uniformIndex]->dirty = false; - } - - return gl::Error(GL_NO_ERROR); + return mProgram->applyUniforms(); } Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps) { - const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; - const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; - - const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers(); - const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers(); - - ASSERT(boundBuffers.size() == mUniformBlocks.size()); - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) - { - UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex); - gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; - - ASSERT(uniformBlock && uniformBuffer); - - if (uniformBuffer->getSize() < uniformBlock->dataSize) - { - // undefined behaviour - return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); - } - - // Unnecessary to apply an unreferenced standard or shared UBO - if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) - { - continue; - } - - if (uniformBlock->isReferencedByVertexShader()) - { - unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; - ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxVertexUniformBlocks); - vertexUniformBuffers[registerIndex] = uniformBuffer; - } - - if (uniformBlock->isReferencedByFragmentShader()) - { - unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; - ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxFragmentUniformBlocks); - fragmentUniformBuffers[registerIndex] = uniformBuffer; - } - } - - return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); + return mProgram->applyUniformBuffers(boundBuffers, caps); } bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) @@ -1082,10 +361,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade return true; } -bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) +LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) { -#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD - return false; +#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED + return LinkResult(false, Error(GL_NO_ERROR)); #else ASSERT(binaryFormat == mProgram->getBinaryFormat()); @@ -1097,7 +376,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina if (format != mProgram->getBinaryFormat()) { infoLog.append("Invalid program binary format."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } int majorVersion = stream.readInt<int>(); @@ -1105,7 +384,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) { infoLog.append("Invalid program binary version."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; @@ -1113,250 +392,38 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { infoLog.append("Invalid program binary version."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } int compileFlags = stream.readInt<int>(); if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) { infoLog.append("Mismatched compilation flags."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { stream.readInt(&mLinkedAttribute[i].type); stream.readString(&mLinkedAttribute[i].name); - stream.readInt(&mShaderAttributes[i].type); - stream.readString(&mShaderAttributes[i].name); + stream.readInt(&mProgram->getShaderAttributes()[i].type); + stream.readString(&mProgram->getShaderAttributes()[i].name); stream.readInt(&mSemanticIndex[i]); } initAttributesByLayout(); - const unsigned int psSamplerCount = stream.readInt<unsigned int>(); - for (unsigned int i = 0; i < psSamplerCount; ++i) - { - Sampler sampler; - stream.readBool(&sampler.active); - stream.readInt(&sampler.logicalTextureUnit); - stream.readInt(&sampler.textureType); - mSamplersPS.push_back(sampler); - } - const unsigned int vsSamplerCount = stream.readInt<unsigned int>(); - for (unsigned int i = 0; i < vsSamplerCount; ++i) - { - Sampler sampler; - stream.readBool(&sampler.active); - stream.readInt(&sampler.logicalTextureUnit); - stream.readInt(&sampler.textureType); - mSamplersVS.push_back(sampler); - } - - stream.readInt(&mUsedVertexSamplerRange); - stream.readInt(&mUsedPixelSamplerRange); - stream.readBool(&mUsesPointSize); - stream.readInt(&mShaderVersion); - - const unsigned int uniformCount = stream.readInt<unsigned int>(); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; - } - - mUniforms.resize(uniformCount); - for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) - { - GLenum type = stream.readInt<GLenum>(); - GLenum precision = stream.readInt<GLenum>(); - std::string name = stream.readString(); - unsigned int arraySize = stream.readInt<unsigned int>(); - int blockIndex = stream.readInt<int>(); - - int offset = stream.readInt<int>(); - int arrayStride = stream.readInt<int>(); - int matrixStride = stream.readInt<int>(); - bool isRowMajorMatrix = stream.readBool(); - - const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); - - LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); - - stream.readInt(&uniform->psRegisterIndex); - stream.readInt(&uniform->vsRegisterIndex); - stream.readInt(&uniform->registerCount); - stream.readInt(&uniform->registerElement); - - mUniforms[uniformIndex] = uniform; - } - - unsigned int uniformBlockCount = stream.readInt<unsigned int>(); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; - } - - mUniformBlocks.resize(uniformBlockCount); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) - { - std::string name = stream.readString(); - unsigned int elementIndex = stream.readInt<unsigned int>(); - unsigned int dataSize = stream.readInt<unsigned int>(); - - UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize); - - stream.readInt(&uniformBlock->psRegisterIndex); - stream.readInt(&uniformBlock->vsRegisterIndex); - - unsigned int numMembers = stream.readInt<unsigned int>(); - uniformBlock->memberUniformIndexes.resize(numMembers); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) - { - stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); - } - - mUniformBlocks[uniformBlockIndex] = uniformBlock; - } - - const unsigned int uniformIndexCount = stream.readInt<unsigned int>(); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; - } - - mUniformIndex.resize(uniformIndexCount); - for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) - { - stream.readString(&mUniformIndex[uniformIndexIndex].name); - stream.readInt(&mUniformIndex[uniformIndexIndex].element); - stream.readInt(&mUniformIndex[uniformIndexIndex].index); - } - - stream.readInt(&mTransformFeedbackBufferMode); - const unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>(); - mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); - for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) - { - LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; - - stream.readString(&varying.name); - stream.readInt(&varying.type); - stream.readInt(&varying.size); - stream.readString(&varying.semanticName); - stream.readInt(&varying.semanticIndex); - stream.readInt(&varying.semanticIndexCount); - } - - const unsigned int vertexShaderCount = stream.readInt<unsigned int>(); - for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) - { - VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; - - for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++) - { - VertexFormat *vertexInput = &inputLayout[inputIndex]; - stream.readInt(&vertexInput->mType); - stream.readInt(&vertexInput->mNormalized); - stream.readInt(&vertexInput->mComponents); - stream.readBool(&vertexInput->mPureInteger); - } - - unsigned int vertexShaderSize = stream.readInt<unsigned int>(); - const unsigned char *vertexShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction), - vertexShaderSize, rx::SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - if (!shaderExecutable) - { - infoLog.append("Could not create vertex shader."); - return false; - } - - // generated converted input layout - GLenum signature[MAX_VERTEX_ATTRIBS]; - mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); - - // add new binary - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); - - stream.skip(vertexShaderSize); - } - - const size_t pixelShaderCount = stream.readInt<unsigned int>(); - for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) + LinkResult result = mProgram->load(infoLog, &stream); + if (result.error.isError() || !result.linkSuccess) { - const size_t outputCount = stream.readInt<unsigned int>(); - std::vector<GLenum> outputs(outputCount); - for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) - { - stream.readInt(&outputs[outputIndex]); - } - - const size_t pixelShaderSize = stream.readInt<unsigned int>(); - const unsigned char *pixelShaderFunction = reinterpret_cast<const unsigned char*>(binary) + stream.offset(); - rx::Renderer *renderer = mProgram->getRenderer(); - rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize, - rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!shaderExecutable) - { - infoLog.append("Could not create pixel shader."); - return false; - } - - // add new binary - mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); - - stream.skip(pixelShaderSize); + return result; } - unsigned int geometryShaderSize = stream.readInt<unsigned int>(); - - if (geometryShaderSize > 0) - { - const char *geometryShaderFunction = (const char*) binary + stream.offset(); - rx::Renderer *renderer = mProgram->getRenderer(); - mGeometryExecutable = renderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction), - geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!mGeometryExecutable) - { - infoLog.append("Could not create geometry shader."); - return false; - } - stream.skip(geometryShaderSize); - } - - if (!mProgram->load(infoLog, &stream)) - { - return false; - } - - const char *ptr = (const char*) binary + stream.offset(); - - const GUID *binaryIdentifier = (const GUID *) ptr; - ptr += sizeof(GUID); - - GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); - if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) - { - infoLog.append("Invalid program binary."); - return false; - } - - mProgram->initializeUniformStorage(mUniforms); - - return true; -#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD + return LinkResult(true, Error(GL_NO_ERROR)); +#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED } -bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) +Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) { if (binaryFormat) { @@ -1375,168 +442,27 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL { stream.writeInt(mLinkedAttribute[i].type); stream.writeString(mLinkedAttribute[i].name); - stream.writeInt(mShaderAttributes[i].type); - stream.writeString(mShaderAttributes[i].name); + stream.writeInt(mProgram->getShaderAttributes()[i].type); + stream.writeString(mProgram->getShaderAttributes()[i].name); stream.writeInt(mSemanticIndex[i]); } - stream.writeInt(mSamplersPS.size()); - for (unsigned int i = 0; i < mSamplersPS.size(); ++i) - { - stream.writeInt(mSamplersPS[i].active); - stream.writeInt(mSamplersPS[i].logicalTextureUnit); - stream.writeInt(mSamplersPS[i].textureType); - } - - stream.writeInt(mSamplersVS.size()); - for (unsigned int i = 0; i < mSamplersVS.size(); ++i) - { - stream.writeInt(mSamplersVS[i].active); - stream.writeInt(mSamplersVS[i].logicalTextureUnit); - stream.writeInt(mSamplersVS[i].textureType); - } - - stream.writeInt(mUsedVertexSamplerRange); - stream.writeInt(mUsedPixelSamplerRange); - stream.writeInt(mUsesPointSize); - stream.writeInt(mShaderVersion); - - stream.writeInt(mUniforms.size()); - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - stream.writeInt(uniform.type); - stream.writeInt(uniform.precision); - stream.writeString(uniform.name); - stream.writeInt(uniform.arraySize); - stream.writeInt(uniform.blockIndex); - - stream.writeInt(uniform.blockInfo.offset); - stream.writeInt(uniform.blockInfo.arrayStride); - stream.writeInt(uniform.blockInfo.matrixStride); - stream.writeInt(uniform.blockInfo.isRowMajorMatrix); - - stream.writeInt(uniform.psRegisterIndex); - stream.writeInt(uniform.vsRegisterIndex); - stream.writeInt(uniform.registerCount); - stream.writeInt(uniform.registerElement); - } - - stream.writeInt(mUniformBlocks.size()); - for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) - { - const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; - - stream.writeString(uniformBlock.name); - stream.writeInt(uniformBlock.elementIndex); - stream.writeInt(uniformBlock.dataSize); - - stream.writeInt(uniformBlock.memberUniformIndexes.size()); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) - { - stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); - } - - stream.writeInt(uniformBlock.psRegisterIndex); - stream.writeInt(uniformBlock.vsRegisterIndex); - } - - stream.writeInt(mUniformIndex.size()); - for (size_t i = 0; i < mUniformIndex.size(); ++i) - { - stream.writeString(mUniformIndex[i].name); - stream.writeInt(mUniformIndex[i].element); - stream.writeInt(mUniformIndex[i].index); - } - - stream.writeInt(mTransformFeedbackBufferMode); - stream.writeInt(mTransformFeedbackLinkedVaryings.size()); - for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) - { - const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; - - stream.writeString(varying.name); - stream.writeInt(varying.type); - stream.writeInt(varying.size); - stream.writeString(varying.semanticName); - stream.writeInt(varying.semanticIndex); - stream.writeInt(varying.semanticIndexCount); - } - - stream.writeInt(mVertexExecutables.size()); - for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) - { - VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; - - for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) - { - const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; - stream.writeInt(vertexInput.mType); - stream.writeInt(vertexInput.mNormalized); - stream.writeInt(vertexInput.mComponents); - stream.writeInt(vertexInput.mPureInteger); - } - - size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); - stream.writeInt(vertexShaderSize); - - const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); - stream.writeBytes(vertexBlob, vertexShaderSize); - } - - stream.writeInt(mPixelExecutables.size()); - for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) - { - PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; - - const std::vector<GLenum> outputs = pixelExecutable->outputSignature(); - stream.writeInt(outputs.size()); - for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) - { - stream.writeInt(outputs[outputIndex]); - } - - size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); - stream.writeInt(pixelShaderSize); - - const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); - stream.writeBytes(pixelBlob, pixelShaderSize); - } - - size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; - stream.writeInt(geometryShaderSize); - - if (mGeometryExecutable != NULL && geometryShaderSize > 0) - { - const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); - stream.writeBytes(geometryBlob, geometryShaderSize); - } - - if (!mProgram->save(&stream)) - { - if (length) - { - *length = 0; - } - - return false; - } - - GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); + mProgram->save(&stream); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); - GLsizei totalLength = streamLength + sizeof(GUID); - if (totalLength > bufSize) + if (streamLength > bufSize) { if (length) { *length = 0; } - return false; + // TODO: This should be moved to the validation layer but computing the size of the binary before saving + // it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate + // sizes and then copy it. + return Error(GL_INVALID_OPERATION); } if (binary) @@ -1546,129 +472,197 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL memcpy(ptr, streamData, streamLength); ptr += streamLength; - memcpy(ptr, &identifier, sizeof(GUID)); - ptr += sizeof(GUID); - - ASSERT(ptr - totalLength == binary); + ASSERT(ptr - streamLength == binary); } if (length) { - *length = totalLength; + *length = streamLength; } - return true; + return Error(GL_NO_ERROR); } GLint ProgramBinary::getLength() { GLint length; - if (save(NULL, NULL, INT_MAX, &length)) - { - return length; - } - else + Error error = save(NULL, NULL, INT_MAX, &length); + if (error.isError()) { return 0; } + + return length; } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, - const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) +LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, + Shader *fragmentShader, Shader *vertexShader, + const std::vector<std::string> &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode) { if (!fragmentShader || !fragmentShader->isCompiled()) { - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); if (!vertexShader || !vertexShader->isCompiled()) { - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); reset(); - mSamplersPS.resize(caps.maxTextureImageUnits); - mSamplersVS.resize(caps.maxVertexTextureImageUnits); + int registers; + std::vector<LinkedVarying> linkedVaryings; + LinkResult result = mProgram->link(data, infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode, + ®isters, &linkedVaryings, &mOutputVariables); + if (result.error.isError() || !result.linkSuccess) + { + return result; + } - mTransformFeedbackBufferMode = transformFeedbackBufferMode; + if (!linkAttributes(infoLog, attributeBindings, vertexShader)) + { + return LinkResult(false, Error(GL_NO_ERROR)); + } - rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps)) + { + return LinkResult(false, Error(GL_NO_ERROR)); + } - mShaderVersion = vertexShaderD3D->getShaderVersion(); + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps)) + { + return LinkResult(false, Error(GL_NO_ERROR)); + } - int registers; - std::vector<LinkedVarying> linkedVaryings; - if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, ®isters, &linkedVaryings, &mOutputVariables)) + if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, + transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) { - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } - mUsesPointSize = vertexShaderD3D->usesPointSize(); + // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, + // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. + result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers); + if (result.error.isError() || !result.linkSuccess) + { + infoLog.append("Failed to create D3D shaders."); + reset(); + return result; + } - bool success = true; + return LinkResult(true, Error(GL_NO_ERROR)); +} - if (!linkAttributes(infoLog, attributeBindings, vertexShader)) +bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps) +{ + const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); + const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); + + // Check that interface blocks defined in the vertex and fragment shaders are identical + typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap; + UniformBlockMap linkedUniformBlocks; + + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - success = false; + const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; + linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; } - if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - success = false; + const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; + UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); + if (entry != linkedUniformBlocks.end()) + { + const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; + if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) + { + return false; + } + } } - // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); + const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + { + if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + { + return false; + } + } } - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - success = false; + const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + { + if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } + } } - if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps)) + return true; +} + +bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock) +{ + const char* blockName = vertexInterfaceBlock.name.c_str(); + + // validate blocks for the same member types + if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) { - success = false; + infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); + return false; } - if (success) + if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) { - VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; - GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); - rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout); + infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; + } - std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey()); - rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); + if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) + { + infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; + } - if (usesGeometryShader()) + const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) + { + const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; + const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; + + if (vertexMember.name != fragmentMember.name) { - std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); - mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(), - rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - rx::ANGLE_D3D_WORKAROUND_NONE); + infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", + blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); + return false; } - if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) { - infoLog.append("Failed to create D3D shaders."); - success = false; - reset(); + return false; } } - return success; + return true; } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices @@ -1688,7 +682,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - mShaderAttributes[attributeIndex] = attribute; + mProgram->getShaderAttributes()[attributeIndex] = attribute; if (location != -1) // Set by glBindAttribLocation or by location layout qualifier { @@ -1708,7 +702,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at // In GLSL 3.00, attribute aliasing produces a link error // In GLSL 1.00, attribute aliasing is allowed - if (mShaderVersion >= 300) + if (mProgram->getShaderVersion() >= 300) { if (!linkedAttribute.name.empty()) { @@ -1856,346 +850,6 @@ bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) -{ - const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); - const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); - - const std::vector<sh::Uniform> &vertexUniforms = vertexShader.getUniforms(); - const std::vector<sh::Uniform> &fragmentUniforms = fragmentShader.getUniforms(); - - // Check that uniforms defined in the vertex and fragment shaders are identical - typedef std::map<std::string, const sh::Uniform*> UniformMap; - UniformMap linkedUniforms; - - for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) - { - const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; - linkedUniforms[vertexUniform.name] = &vertexUniform; - } - - for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) - { - const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; - UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); - if (entry != linkedUniforms.end()) - { - const sh::Uniform &vertexUniform = *entry->second; - const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - } - } - - for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - - if (uniform.staticUse) - { - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); - } - } - - for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; - - if (uniform.staticUse) - { - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); - } - } - - if (!indexUniforms(infoLog, caps)) - { - return false; - } - - mProgram->initializeUniformStorage(mUniforms); - - return true; -} - -void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) -{ - ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader); - sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); - encoder.skipRegisters(uniformRegister); - - defineUniform(shader, uniform, uniform.name, &encoder); -} - -void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, - const std::string &fullName, sh::HLSLBlockEncoder *encoder) -{ - if (uniform.isStruct()) - { - for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) - { - const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); - - encoder->enterAggregateType(); - - for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) - { - const sh::ShaderVariable &field = uniform.fields[fieldIndex]; - const std::string &fieldFullName = (fullName + elementString + "." + field.name); - - defineUniform(shader, field, fieldFullName, encoder); - } - - encoder->exitAggregateType(); - } - } - else // Not a struct - { - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->enterAggregateType(); - } - - LinkedUniform *linkedUniform = getUniformByName(fullName); - - if (!linkedUniform) - { - linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, - -1, sh::BlockMemberInfo::getDefaultBlockInfo()); - ASSERT(linkedUniform); - linkedUniform->registerElement = encoder->getCurrentElement(); - mUniforms.push_back(linkedUniform); - } - - ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); - - if (shader == GL_FRAGMENT_SHADER) - { - linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); - } - else if (shader == GL_VERTEX_SHADER) - { - linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); - } - else UNREACHABLE(); - - // Advance the uniform offset, to track registers allocation for structs - encoder->encodeType(uniform.type, uniform.arraySize, false); - - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->exitAggregateType(); - } - } -} - -bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps) -{ - ASSERT(IsSampler(uniform.type)); - ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); - - if (uniform.vsRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange)) - { - infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mSamplersVS.size()); - return false; - } - - unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; - if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) - { - infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - caps.maxVertexUniformVectors); - return false; - } - } - - if (uniform.psRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange)) - { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - mSamplersPS.size()); - return false; - } - - unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; - if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) - { - infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - caps.maxFragmentUniformVectors); - return false; - } - } - - return true; -} - -bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps) -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (IsSampler(uniform.type)) - { - if (!indexSamplerUniform(uniform, infoLog, caps)) - { - return false; - } - } - - for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) - { - mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); - } - } - - return true; -} - -bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, - GLenum samplerType, - unsigned int samplerCount, - std::vector<Sampler> &outSamplers, - GLuint *outUsedRange) -{ - unsigned int samplerIndex = startSamplerIndex; - - do - { - if (samplerIndex < outSamplers.size()) - { - Sampler& sampler = outSamplers[samplerIndex]; - sampler.active = true; - sampler.textureType = GetTextureType(samplerType); - sampler.logicalTextureUnit = 0; - *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); - } - else - { - return false; - } - - samplerIndex++; - } while (samplerIndex < startSamplerIndex + samplerCount); - - return true; -} - -bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock) -{ - const char* blockName = vertexInterfaceBlock.name.c_str(); - - // validate blocks for the same member types - if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) - { - infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); - return false; - } - - if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) - { - infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; - } - - if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) - { - infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; - } - - const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) - { - const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; - const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; - - if (vertexMember.name != fragmentMember.name) - { - infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", - blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); - return false; - } - - std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) - { - return false; - } - } - - return true; -} - -bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) -{ - const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); - const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); - - // Check that interface blocks defined in the vertex and fragment shaders are identical - typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap; - UniformBlockMap linkedUniformBlocks; - - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; - linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; - } - - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; - UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); - if (entry != linkedUniformBlocks.end()) - { - const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; - if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) - { - return false; - } - } - } - - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; - - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) - { - if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) - { - return false; - } - } - } - - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; - - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) - { - if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) - { - return false; - } - } - } - - return true; -} - bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, const std::vector<std::string> &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, @@ -2253,142 +907,6 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons return true; } -template <typename VarT> -void ProgramBinary::defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes, - bool inRowMajorLayout) -{ - for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) - { - const VarT &field = fields[uniformIndex]; - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - - if (field.isStruct()) - { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); - - for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) - { - encoder->enterAggregateType(); - - const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); - - encoder->exitAggregateType(); - } - } - else - { - bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout); - - sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); - - LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, - blockIndex, memberInfo); - - // add to uniform list, but not index, since uniform block uniforms have no location - blockUniformIndexes->push_back(mUniforms.size()); - mUniforms.push_back(newUniform); - } - } -} - -bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps) -{ - const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation()); - - // create uniform block entries if they do not exist - if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) - { - std::vector<unsigned int> blockUniformIndexes; - const unsigned int blockIndex = mUniformBlocks.size(); - - // define member uniforms - sh::BlockLayoutEncoder *encoder = NULL; - - if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) - { - encoder = new sh::Std140BlockEncoder; - } - else - { - encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); - } - ASSERT(encoder); - - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); - - size_t dataSize = encoder->getBlockSize(); - - // create all the uniform blocks - if (interfaceBlock.arraySize > 0) - { - for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) - { - UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - else - { - UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - - if (interfaceBlock.staticUse) - { - // Assign registers to the uniform blocks - const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); - const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); - ASSERT(blockIndex != GL_INVALID_INDEX); - ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); - - unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) - { - UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); - - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement, caps)) - { - return false; - } - } - } - - return true; -} - -bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps) -{ - if (shader == GL_VERTEX_SHADER) - { - uniformBlock->vsRegisterIndex = registerIndex; - if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) - { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); - return false; - } - } - else if (shader == GL_FRAGMENT_SHADER) - { - uniformBlock->psRegisterIndex = registerIndex; - if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) - { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); - return false; - } - } - else UNREACHABLE(); - - return true; -} - bool ProgramBinary::isValidated() const { return mValidated; @@ -2464,13 +982,13 @@ GLint ProgramBinary::getActiveAttributeMaxLength() const void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const { - ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount() + ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() if (bufsize > 0) { - std::string string = mUniforms[index]->name; + std::string string = mProgram->getUniforms()[index]->name; - if (mUniforms[index]->isArray()) + if (mProgram->getUniforms()[index]->isArray()) { string += "[0]"; } @@ -2484,27 +1002,27 @@ void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *len } } - *size = mUniforms[index]->elementCount(); + *size = mProgram->getUniforms()[index]->elementCount(); - *type = mUniforms[index]->type; + *type = mProgram->getUniforms()[index]->type; } GLint ProgramBinary::getActiveUniformCount() const { - return mUniforms.size(); + return mProgram->getUniforms().size(); } GLint ProgramBinary::getActiveUniformMaxLength() const { int maxLength = 0; - unsigned int numUniforms = mUniforms.size(); + unsigned int numUniforms = mProgram->getUniforms().size(); for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) { - if (!mUniforms[uniformIndex]->name.empty()) + if (!mProgram->getUniforms()[uniformIndex]->name.empty()) { - int length = (int)(mUniforms[uniformIndex]->name.length() + 1); - if (mUniforms[uniformIndex]->isArray()) + int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); + if (mProgram->getUniforms()[uniformIndex]->isArray()) { length += 3; // Counting in "[0]". } @@ -2517,7 +1035,7 @@ GLint ProgramBinary::getActiveUniformMaxLength() const GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const { - const gl::LinkedUniform& uniform = *mUniforms[index]; + const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; switch (pname) { @@ -2540,34 +1058,25 @@ GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const bool ProgramBinary::isValidUniformLocation(GLint location) const { - ASSERT(rx::IsIntegerCastSafe<GLint>(mUniformIndex.size())); - return (location >= 0 && location < static_cast<GLint>(mUniformIndex.size())); + ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size())); + return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size())); } LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const { - ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size()); - return mUniforms[mUniformIndex[location].index]; + return mProgram->getUniformByLocation(location); } LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const { - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - if (mUniforms[uniformIndex]->name == name) - { - return mUniforms[uniformIndex]; - } - } - - return NULL; + return mProgram->getUniformByName(name); } void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const { - ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; if (bufSize > 0) { @@ -2590,9 +1099,9 @@ void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const { - ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; switch (pname) { @@ -2625,17 +1134,17 @@ void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pna GLuint ProgramBinary::getActiveUniformBlockCount() const { - return mUniformBlocks.size(); + return mProgram->getUniformBlocks().size(); } GLuint ProgramBinary::getActiveUniformBlockMaxLength() const { unsigned int maxLength = 0; - unsigned int numUniformBlocks = mUniformBlocks.size(); + unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) { - const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; if (!uniformBlock.name.empty()) { const unsigned int length = uniformBlock.name.length() + 1; @@ -2665,88 +1174,7 @@ void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) { - // if any two active samplers in a program are of different types, but refer to the same - // texture image unit, and this is the current program, then ValidateProgram will fail, and - // DrawArrays and DrawElements will issue the INVALID_OPERATION error. - updateSamplerMapping(); - - std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); - - for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) - { - if (mSamplersPS[i].active) - { - unsigned int unit = mSamplersPS[i].logicalTextureUnit; - - if (unit >= textureUnitTypes.size()) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); - } - - return false; - } - - if (textureUnitTypes[unit] != GL_NONE) - { - if (mSamplersPS[i].textureType != textureUnitTypes[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; - } - } - else - { - textureUnitTypes[unit] = mSamplersPS[i].textureType; - } - } - } - - for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) - { - if (mSamplersVS[i].active) - { - unsigned int unit = mSamplersVS[i].logicalTextureUnit; - - if (unit >= textureUnitTypes.size()) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); - } - - return false; - } - - if (textureUnitTypes[unit] != GL_NONE) - { - if (mSamplersVS[i].textureType != textureUnitTypes[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; - } - } - else - { - textureUnitTypes[unit] = mSamplersVS[i].textureType; - } - } - } - - return true; -} - -ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) -{ + return mProgram->validateSamplers(infoLog, caps); } struct AttributeSorter @@ -2795,26 +1223,6 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA void ProgramBinary::reset() { - SafeDeleteContainer(mVertexExecutables); - SafeDeleteContainer(mPixelExecutables); - - SafeDelete(mGeometryExecutable); - - mTransformFeedbackBufferMode = GL_NONE; - mTransformFeedbackLinkedVaryings.clear(); - - mSamplersPS.clear(); - mSamplersVS.clear(); - - mUsedVertexSamplerRange = 0; - mUsedPixelSamplerRange = 0; - mUsesPointSize = false; - mShaderVersion = 0; - mDirtySamplerMapping = true; - - SafeDeleteContainer(mUniforms); - SafeDeleteContainer(mUniformBlocks); - mUniformIndex.clear(); mOutputVariables.clear(); mProgram->reset(); diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index ad470d417b..3142d66c6d 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h @@ -24,11 +24,6 @@ #include <string> #include <vector> -// TODO(jmadill): place this in workarounds library -#define ANGLE_WORKAROUND_ENABLED 1 -#define ANGLE_WORKAROUND_DISABLED 2 -#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED - namespace sh { class HLSLBlockEncoder; @@ -44,7 +39,6 @@ class HLSLBlockEncoder; namespace rx { class ShaderExecutable; -class Renderer; struct TranslatedAttribute; class UniformStorage; class ProgramImpl; @@ -58,6 +52,7 @@ class InfoLog; class AttributeBindings; class Buffer; class Framebuffer; +struct Data; // Struct used for correlating uniforms/elements of uniform arrays to handles struct VariableLocation @@ -91,6 +86,14 @@ struct LinkedVarying unsigned int semanticIndexCount; }; +struct LinkResult +{ + bool linkSuccess; + Error error; + + LinkResult(bool linkSuccess, const Error &error); +}; + // This is the result of linking a program. It is the state that would be passed to ProgramBinary. class ProgramBinary : public RefCountObject { @@ -101,11 +104,6 @@ class ProgramBinary : public RefCountObject rx::ProgramImpl *getImplementation() { return mProgram; } const rx::ProgramImpl *getImplementation() const { return mProgram; } - rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); - rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout); - rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); - rx::ShaderExecutable *getGeometryExecutable() const; - GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); @@ -113,8 +111,6 @@ class ProgramBinary : public RefCountObject GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; - bool usesPointSpriteEmulation() const; - bool usesGeometryShader() const; GLint getUniformLocation(std::string name); GLuint getUniformIndex(std::string name); @@ -145,18 +141,17 @@ class ProgramBinary : public RefCountObject void getUniformiv(GLint location, GLint *params); void getUniformuiv(GLint location, GLuint *params); - void dirtyAllUniforms(); - Error applyUniforms(); Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps); - bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); - bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); + LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); + Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); GLint getLength(); - bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, - const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); - void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); + LinkResult link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, + Shader *fragmentShader, Shader *vertexShader, + const std::vector<std::string> &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; GLint getActiveAttributeCount() const; @@ -188,30 +183,23 @@ class ProgramBinary : public RefCountObject void updateSamplerMapping(); unsigned int getSerial() const; - int getShaderVersion() const; void initAttributesByLayout(); void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; - const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; } - static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); + static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - struct Sampler - { - Sampler(); - - bool active; - GLint logicalTextureUnit; - GLenum textureType; - }; - void reset(); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); + bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); + bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock); static bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, @@ -219,102 +207,21 @@ class ProgramBinary : public RefCountObject const sh::ShaderVariable &fragmentVariable, bool validatePrecision); - static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); - static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); - bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); - void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); - bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps); - bool indexUniforms(InfoLog &infoLog, const Caps &caps); - static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - std::vector<Sampler> &outSamplers, GLuint *outUsedRange); - bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); - bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, const std::vector<std::string> &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings, const Caps &caps) const; - template <typename VarT> - void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes, - bool inRowMajorLayout); - bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); void defineOutputVariables(Shader *fragmentShader); - template <typename T> - void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); - - template <int cols, int rows> - void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); - - template <typename T> - void getUniformv(GLint location, T *params, GLenum uniformType); - - class VertexExecutable - { - public: - VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], - const GLenum signature[MAX_VERTEX_ATTRIBS], - rx::ShaderExecutable *shaderExecutable); - ~VertexExecutable(); - - bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const; - - const VertexFormat *inputs() const { return mInputs; } - const GLenum *signature() const { return mSignature; } - rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } - - private: - VertexFormat mInputs[MAX_VERTEX_ATTRIBS]; - GLenum mSignature[MAX_VERTEX_ATTRIBS]; - rx::ShaderExecutable *mShaderExecutable; - }; - - class PixelExecutable - { - public: - PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable); - ~PixelExecutable(); - - bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; } - - const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } - rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } - - private: - std::vector<GLenum> mOutputSignature; - rx::ShaderExecutable *mShaderExecutable; - }; - rx::ProgramImpl *mProgram; - std::vector<VertexExecutable *> mVertexExecutables; - std::vector<PixelExecutable *> mPixelExecutables; - - rx::ShaderExecutable *mGeometryExecutable; - sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; - sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; - GLenum mTransformFeedbackBufferMode; - std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings; - - std::vector<Sampler> mSamplersPS; - std::vector<Sampler> mSamplersVS; - GLuint mUsedVertexSamplerRange; - GLuint mUsedPixelSamplerRange; - bool mUsesPointSize; - int mShaderVersion; - bool mDirtySamplerMapping; - - std::vector<LinkedUniform*> mUniforms; - std::vector<UniformBlock*> mUniformBlocks; - std::vector<VariableLocation> mUniformIndex; std::map<int, VariableLocation> mOutputVariables; bool mValidated; diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index 9406fce58d..911a389dfa 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -4,77 +4,86 @@ // found in the LICENSE file. // -// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes -// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. +// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class, +// GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Texture.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/RenderbufferImpl.h" #include "common/utilities.h" namespace gl { -unsigned int RenderbufferStorage::mCurrentSerial = 1; - -Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage) +Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id) : RefCountObject(id), - mStorage(newStorage) + mRenderbuffer(impl) { - ASSERT(mStorage); + ASSERT(mRenderbuffer); + + mWidth = mRenderbuffer->getWidth(); + mHeight = mRenderbuffer->getHeight(); + mInternalFormat = mRenderbuffer->getInternalFormat(); + mActualFormat = mRenderbuffer->getActualFormat(); + mSamples = mRenderbuffer->getSamples(); } Renderbuffer::~Renderbuffer() { - SafeDelete(mStorage); + SafeDelete(mRenderbuffer); } -void Renderbuffer::setStorage(RenderbufferStorage *newStorage) +Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { - ASSERT(newStorage); + Error error = mRenderbuffer->setStorage(width, height, internalformat, samples); + if (error.isError()) + { + return error; + } - SafeDelete(mStorage); - mStorage = newStorage; + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + mSamples = samples; + mActualFormat = mRenderbuffer->getActualFormat(); + + return Error(GL_NO_ERROR); } -RenderbufferStorage *Renderbuffer::getStorage() +rx::RenderbufferImpl *Renderbuffer::getImplementation() { - ASSERT(mStorage); - return mStorage; + ASSERT(mRenderbuffer); + return mRenderbuffer; } GLsizei Renderbuffer::getWidth() const { - ASSERT(mStorage); - return mStorage->getWidth(); + return mWidth; } GLsizei Renderbuffer::getHeight() const { - ASSERT(mStorage); - return mStorage->getHeight(); + return mHeight; } GLenum Renderbuffer::getInternalFormat() const { - ASSERT(mStorage); - return mStorage->getInternalFormat(); + return mInternalFormat; } GLenum Renderbuffer::getActualFormat() const { - ASSERT(mStorage); - return mStorage->getActualFormat(); + return mActualFormat; } GLsizei Renderbuffer::getSamples() const { - ASSERT(mStorage); - return mStorage->getSamples(); + return mSamples; } GLuint Renderbuffer::getRedSize() const @@ -107,176 +116,4 @@ GLuint Renderbuffer::getStencilSize() const return GetInternalFormatInfo(getActualFormat()).stencilBits; } -RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1)) -{ - mWidth = 0; - mHeight = 0; - mInternalFormat = GL_RGBA4; - mActualFormat = GL_RGBA8_OES; - mSamples = 0; -} - -RenderbufferStorage::~RenderbufferStorage() -{ -} - -rx::RenderTarget *RenderbufferStorage::getRenderTarget() -{ - return NULL; -} - -GLsizei RenderbufferStorage::getWidth() const -{ - return mWidth; -} - -GLsizei RenderbufferStorage::getHeight() const -{ - return mHeight; -} - -GLenum RenderbufferStorage::getInternalFormat() const -{ - return mInternalFormat; -} - -GLenum RenderbufferStorage::getActualFormat() const -{ - return mActualFormat; -} - -GLsizei RenderbufferStorage::getSamples() const -{ - return mSamples; -} - -unsigned int RenderbufferStorage::getSerial() const -{ - return mSerial; -} - -unsigned int RenderbufferStorage::issueSerials(unsigned int count) -{ - unsigned int firstSerial = mCurrentSerial; - mCurrentSerial += count; - return firstSerial; -} - -bool RenderbufferStorage::isTexture() const -{ - return false; -} - -unsigned int RenderbufferStorage::getTextureSerial() const -{ - return -1; -} - -Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) -{ - mRenderTarget = renderer->createRenderTarget(swapChain, false); - - if (mRenderTarget) - { - mWidth = mRenderTarget->getWidth(); - mHeight = mRenderTarget->getHeight(); - mInternalFormat = mRenderTarget->getInternalFormat(); - mActualFormat = mRenderTarget->getActualFormat(); - mSamples = mRenderTarget->getSamples(); - } -} - -Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) -{ - mRenderTarget = renderer->createRenderTarget(width, height, format, samples); - - if (mRenderTarget) - { - mWidth = width; - mHeight = height; - mInternalFormat = format; - mActualFormat = mRenderTarget->getActualFormat(); - mSamples = mRenderTarget->getSamples(); - } -} - -Colorbuffer::~Colorbuffer() -{ - if (mRenderTarget) - { - delete mRenderTarget; - } -} - -rx::RenderTarget *Colorbuffer::getRenderTarget() -{ - return mRenderTarget; -} - -DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) -{ - mDepthStencil = renderer->createRenderTarget(swapChain, true); - if (mDepthStencil) - { - mWidth = mDepthStencil->getWidth(); - mHeight = mDepthStencil->getHeight(); - mInternalFormat = mDepthStencil->getInternalFormat(); - mSamples = mDepthStencil->getSamples(); - mActualFormat = mDepthStencil->getActualFormat(); - } -} - -DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) -{ - - mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples); - - mWidth = mDepthStencil->getWidth(); - mHeight = mDepthStencil->getHeight(); - mInternalFormat = GL_DEPTH24_STENCIL8_OES; - mActualFormat = mDepthStencil->getActualFormat(); - mSamples = mDepthStencil->getSamples(); -} - -DepthStencilbuffer::~DepthStencilbuffer() -{ - if (mDepthStencil) - { - delete mDepthStencil; - } -} - -rx::RenderTarget *DepthStencilbuffer::getRenderTarget() -{ - return mDepthStencil; -} - -Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) -{ - if (mDepthStencil) - { - mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Depthbuffer::~Depthbuffer() -{ -} - -Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) -{ - if (mDepthStencil) - { - mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Stencilbuffer::~Stencilbuffer() -{ -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index 71bcb0e1f8..e9f12af3ce 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -4,30 +4,27 @@ // found in the LICENSE file. // -// Renderbuffer.h: Defines the wrapper class gl::Renderbuffer, as well as the -// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer, -// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. +// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer. +// Implements GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. #ifndef LIBGLESV2_RENDERBUFFER_H_ #define LIBGLESV2_RENDERBUFFER_H_ #include "angle_gl.h" +#include "libGLESv2/Error.h" + #include "common/angleutils.h" #include "common/RefCountObject.h" namespace rx { -class Renderer; -class SwapChain; -class RenderTarget; -class TextureStorage; +class RenderbufferImpl; } namespace gl { -class RenderbufferStorage; class FramebufferAttachment; // A GL renderbuffer object is usually used as a depth or stencil buffer attachment @@ -38,11 +35,12 @@ class FramebufferAttachment; class Renderbuffer : public RefCountObject { public: - Renderbuffer(GLuint id, RenderbufferStorage *newStorage); + Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); virtual ~Renderbuffer(); - void setStorage(RenderbufferStorage *newStorage); - RenderbufferStorage *getStorage(); + Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); + + rx::RenderbufferImpl *getImplementation(); GLsizei getWidth() const; GLsizei getHeight() const; @@ -57,102 +55,15 @@ class Renderbuffer : public RefCountObject GLuint getStencilSize() const; private: - RenderbufferStorage *mStorage; -}; - -// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage -// is called. The specific concrete type depends on whether the internal format is -// colour depth, stencil or packed depth/stencil. -class RenderbufferStorage -{ - public: - RenderbufferStorage(); + DISALLOW_COPY_AND_ASSIGN(Renderbuffer); - virtual ~RenderbufferStorage() = 0; + rx::RenderbufferImpl *mRenderbuffer; - virtual rx::RenderTarget *getRenderTarget(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual bool isTexture() const; - virtual unsigned int getTextureSerial() const; - - static unsigned int issueSerials(unsigned int count); - - protected: GLsizei mWidth; GLsizei mHeight; GLenum mInternalFormat; GLenum mActualFormat; GLsizei mSamples; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage); - - const unsigned int mSerial; - - static unsigned int mCurrentSerial; -}; - -class Colorbuffer : public RenderbufferStorage -{ - public: - Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); - Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); - - virtual ~Colorbuffer(); - - virtual rx::RenderTarget *getRenderTarget(); - - private: - DISALLOW_COPY_AND_ASSIGN(Colorbuffer); - - rx::RenderTarget *mRenderTarget; -}; - -class DepthStencilbuffer : public RenderbufferStorage -{ - public: - DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); - DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); - - ~DepthStencilbuffer(); - - virtual rx::RenderTarget *getRenderTarget(); - - protected: - rx::RenderTarget *mDepthStencil; - - private: - DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer); -}; - -class Depthbuffer : public DepthStencilbuffer -{ - public: - Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); - - virtual ~Depthbuffer(); - - private: - DISALLOW_COPY_AND_ASSIGN(Depthbuffer); -}; - -class Stencilbuffer : public DepthStencilbuffer -{ - public: - Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); - - virtual ~Stencilbuffer(); - - private: - DISALLOW_COPY_AND_ASSIGN(Stencilbuffer); }; } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp index 9121de1750..38d53cad81 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp @@ -21,9 +21,9 @@ namespace gl { ResourceManager::ResourceManager(rx::Renderer *renderer) + : mRenderer(renderer), + mRefCount(1) { - mRefCount = 1; - mRenderer = renderer; } ResourceManager::~ResourceManager() @@ -88,13 +88,13 @@ GLuint ResourceManager::createBuffer() } // Returns an unused shader/program name -GLuint ResourceManager::createShader(GLenum type) +GLuint ResourceManager::createShader(const gl::Data &data, GLenum type) { GLuint handle = mProgramShaderHandleAllocator.allocate(); if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle); + mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle); } else UNREACHABLE(); @@ -146,7 +146,7 @@ GLuint ResourceManager::createFenceSync() { GLuint handle = mFenceSyncHandleAllocator.allocate(); - FenceSync *fenceSync = new FenceSync(mRenderer, handle); + FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle); fenceSync->addRef(); mFenceSyncMap[handle] = fenceSync; @@ -295,9 +295,9 @@ Texture *ResourceManager::getTexture(unsigned int handle) } } -Program *ResourceManager::getProgram(unsigned int handle) +Program *ResourceManager::getProgram(unsigned int handle) const { - ProgramMap::iterator program = mProgramMap.find(handle); + ProgramMap::const_iterator program = mProgramMap.find(handle); if (program == mProgramMap.end()) { @@ -403,7 +403,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) { if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) { - Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); + Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer); mRenderbufferMap[renderbuffer] = renderbufferObject; renderbufferObject->addRef(); } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h index 7d53bd4854..acad29b51d 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h @@ -32,6 +32,7 @@ class Texture; class Renderbuffer; class Sampler; class FenceSync; +struct Data; class ResourceManager { @@ -43,7 +44,7 @@ class ResourceManager void release(); GLuint createBuffer(); - GLuint createShader(GLenum type); + GLuint createShader(const gl::Data &data, GLenum type); GLuint createProgram(); GLuint createTexture(); GLuint createRenderbuffer(); @@ -60,7 +61,7 @@ class ResourceManager Buffer *getBuffer(GLuint handle); Shader *getShader(GLuint handle); - Program *getProgram(GLuint handle); + Program *getProgram(GLuint handle) const; Texture *getTexture(GLuint handle); Renderbuffer *getRenderbuffer(GLuint handle); Sampler *getSampler(GLuint handle); @@ -78,8 +79,8 @@ class ResourceManager private: DISALLOW_COPY_AND_ASSIGN(ResourceManager); - std::size_t mRefCount; rx::Renderer *mRenderer; + std::size_t mRefCount; typedef std::unordered_map<GLuint, Buffer*> BufferMap; BufferMap mBufferMap; diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index 4cf5251ff9..1cc17a0501 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -118,9 +118,15 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); } -void Shader::compile() +void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const { - mCompiled = mShader->compile(mSource); + std::string debugInfo(mShader->getDebugInfo()); + getSourceImpl(debugInfo, bufSize, length, buffer); +} + +void Shader::compile(const gl::Data &data) +{ + mCompiled = mShader->compile(data, mSource); } void Shader::addRef() diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index 7ba3bd165c..904217dab8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -31,6 +31,7 @@ class ShaderImpl; namespace gl { class ResourceManager; +struct Data; struct PackedVarying : public sh::Varying { @@ -73,8 +74,9 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; + void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const; - void compile(); + void compile(const gl::Data &data); bool isCompiled() const { return mCompiled; } void addRef(); diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp index 3c03b90e56..b5b62f5848 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.cpp +++ b/src/3rdparty/angle/src/libGLESv2/State.cpp @@ -10,18 +10,20 @@ #include "libGLESv2/Context.h" #include "libGLESv2/Caps.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/Query.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/Query.h" +#include "libGLESv2/VertexArray.h" #include "libGLESv2/formatutils.h" +#include "libGLESv2/renderer/RenderTarget.h" namespace gl { State::State() { + mMaxDrawBuffers = 0; + mMaxCombinedTextureImageUnits = 0; } State::~State() @@ -31,7 +33,8 @@ State::~State() void State::initialize(const Caps& caps, GLuint clientVersion) { - mContext = NULL; + mMaxDrawBuffers = caps.maxDrawBuffers; + mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; setClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -111,11 +114,15 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mActiveSampler = 0; const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) + mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); + for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex) { mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); } + mUniformBuffers.resize(caps.maxCombinedUniformBlocks); + mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes); + mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); if (clientVersion >= 3) @@ -153,12 +160,6 @@ void State::reset() mSamplers[samplerIdx].set(NULL); } - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) - { - mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } - mArrayBuffer.set(NULL); mRenderbuffer.set(NULL); @@ -170,15 +171,15 @@ void State::reset() } mGenericUniformBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + mGenericTransformFeedbackBuffer.set(NULL); + for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) { - mUniformBuffers[i].set(NULL); + bufItr->set(NULL); } - mGenericTransformFeedbackBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr) { - mTransformFeedbackBuffers[i].set(NULL); + bufItr->set(NULL); } mCopyReadBuffer.set(NULL); @@ -485,7 +486,7 @@ void State::setSampleCoverageParams(GLclampf value, bool invert) mSampleCoverageInvert = invert; } -void State::getSampleCoverageParams(GLclampf *value, bool *invert) +void State::getSampleCoverageParams(GLclampf *value, bool *invert) const { ASSERT(value != NULL && invert != NULL); @@ -612,14 +613,7 @@ void State::setSamplerTexture(GLenum type, Texture *texture) Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const { - const BindingPointer<Texture>& binding = mSamplerTextures.at(type)[sampler]; - - if (binding.id() == 0) // Special case: 0 refers to default textures held by Context - { - return NULL; - } - - return binding.get(); + return mSamplerTextures.at(type)[sampler].get(); } GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const @@ -627,7 +621,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const return mSamplerTextures.at(type)[sampler].id(); } -void State::detachTexture(GLuint texture) +void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) { // Textures have a detach method on State rather than a simple // removeBinding, because the zero/null texture objects are managed @@ -640,13 +634,15 @@ void State::detachTexture(GLuint texture) for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) { + GLenum textureType = bindingVec->first; TextureBindingVector &textureVector = bindingVec->second; for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) { BindingPointer<Texture> &binding = textureVector[textureIdx]; if (binding.id() == texture) { - binding.set(NULL); + // Zero textures are the "default" textures instead of NULL + binding.set(zeroTextures.at(textureType).get()); } } } @@ -667,6 +663,19 @@ void State::detachTexture(GLuint texture) } } +void State::initializeZeroTextures(const TextureMap &zeroTextures) +{ + for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++) + { + TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first]; + + for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) + { + samplerTextureArray[textureUnit].set(i->second.get()); + } + } +} + void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) { mSamplers[textureUnit].set(sampler); @@ -947,14 +956,14 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt GLuint State::getIndexedUniformBufferId(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); return mUniformBuffers[index].id(); } Buffer *State::getIndexedUniformBuffer(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); return mUniformBuffers[index].get(); } @@ -971,25 +980,30 @@ void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffe GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size()); return mTransformFeedbackBuffers[index].id(); } Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size()); return mTransformFeedbackBuffers[index].get(); } GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size()); return mTransformFeedbackBuffers[index].getOffset(); } +size_t State::getTransformFeedbackBufferIndexRange() const +{ + return mTransformFeedbackBuffers.size(); +} + void State::setCopyReadBufferBinding(Buffer *buffer) { mCopyReadBuffer.set(buffer); @@ -1033,19 +1047,19 @@ void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) void State::setVertexAttribf(GLuint index, const GLfloat values[4]) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setFloatValues(values); } void State::setVertexAttribu(GLuint index, const GLuint values[4]) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setUnsignedIntValues(values); } void State::setVertexAttribi(GLuint index, const GLint values[4]) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setIntValues(values); } @@ -1062,15 +1076,10 @@ const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const { - ASSERT(attribNum < MAX_VERTEX_ATTRIBS); + ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size()); return mVertexAttribCurrentValues[attribNum]; } -const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const -{ - return mVertexAttribCurrentValues; -} - const void *State::getVertexAttribPointer(unsigned int attribNum) const { return getVertexArray()->getVertexAttribute(attribNum).pointer; @@ -1180,12 +1189,12 @@ void State::getFloatv(GLenum pname, GLfloat *params) } } -void State::getIntegerv(GLenum pname, GLint *params) +void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) { if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) { unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); - ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers); + ASSERT(colorAttachment < mMaxDrawBuffers); Framebuffer *framebuffer = mDrawFramebuffer; *params = framebuffer->getDrawBufferState(colorAttachment); return; @@ -1238,12 +1247,12 @@ void State::getIntegerv(GLenum pname, GLint *params) case GL_SAMPLES: { gl::Framebuffer *framebuffer = mDrawFramebuffer; - if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE) { switch (pname) { case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples() != 0) + if (framebuffer->getSamples(data) != 0) { *params = 1; } @@ -1253,7 +1262,7 @@ void State::getIntegerv(GLenum pname, GLint *params) } break; case GL_SAMPLES: - *params = framebuffer->getSamples(); + *params = framebuffer->getSamples(data); break; } } @@ -1332,19 +1341,19 @@ void State::getIntegerv(GLenum pname, GLint *params) } break; case GL_TEXTURE_BINDING_2D: - ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_CUBE_MAP: - ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_3D: - ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_2D_ARRAY: - ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id(); break; case GL_UNIFORM_BUFFER_BINDING: @@ -1376,13 +1385,13 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size()) { *data = mTransformFeedbackBuffers[index].id(); } break; case GL_UNIFORM_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + if (static_cast<size_t>(index) < mUniformBuffers.size()) { *data = mUniformBuffers[index].id(); } @@ -1399,25 +1408,25 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size()) { *data = mTransformFeedbackBuffers[index].getOffset(); } break; case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size()) { *data = mTransformFeedbackBuffers[index].getSize(); } break; case GL_UNIFORM_BUFFER_START: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + if (static_cast<size_t>(index) < mUniformBuffers.size()) { *data = mUniformBuffers[index].getOffset(); } break; case GL_UNIFORM_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + if (static_cast<size_t>(index) < mUniformBuffers.size()) { *data = mUniformBuffers[index].getSize(); } @@ -1433,9 +1442,9 @@ bool State::hasMappedBuffer(GLenum target) const { if (target == GL_ARRAY_BUFFER) { - for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) + for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++) { - const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex); + const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast<unsigned int>(attribIndex)); gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) { diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libGLESv2/State.h index 5f0433136c..c3e6106bd8 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.h +++ b/src/3rdparty/angle/src/libGLESv2/State.h @@ -25,6 +25,9 @@ class Query; class VertexArray; class Context; struct Caps; +struct Data; + +typedef std::map< GLenum, BindingPointer<Texture> > TextureMap; class State { @@ -35,8 +38,6 @@ class State void initialize(const Caps& caps, GLuint clientVersion); void reset(); - void setContext(Context *context) { mContext = context; } - // State chunk getters const RasterizerState &getRasterizerState() const; const BlendState &getBlendState() const; @@ -100,7 +101,7 @@ class State bool isSampleCoverageEnabled() const; void setSampleCoverage(bool enabled); void setSampleCoverageParams(GLclampf value, bool invert); - void getSampleCoverageParams(GLclampf *value, bool *invert); + void getSampleCoverageParams(GLclampf *value, bool *invert) const; // Scissor test state toggle & query bool isScissorTestEnabled() const; @@ -133,7 +134,8 @@ class State void setSamplerTexture(GLenum type, Texture *texture); Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const; - void detachTexture(GLuint texture); + void detachTexture(const TextureMap &zeroTextures, GLuint texture); + void initializeZeroTextures(const TextureMap &zeroTextures); // Sampler object binding manipulation void setSamplerBinding(GLuint textureUnit, Sampler *sampler); @@ -199,6 +201,7 @@ class State GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; + size_t getTransformFeedbackBufferIndexRange() const; // GL_COPY_[READ/WRITE]_BUFFER void setCopyReadBufferBinding(Buffer *buffer); @@ -220,7 +223,6 @@ class State bool normalized, bool pureInteger, GLsizei stride, const void *pointer); const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; - const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const; const void *getVertexAttribPointer(unsigned int attribNum) const; // Pixel pack state manipulation @@ -238,7 +240,7 @@ class State // State query functions void getBooleanv(GLenum pname, GLboolean *params); void getFloatv(GLenum pname, GLfloat *params); - void getIntegerv(GLenum pname, GLint *params); + void getIntegerv(const gl::Data &data, GLenum pname, GLint *params); bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); @@ -247,7 +249,9 @@ class State private: DISALLOW_COPY_AND_ASSIGN(State); - Context *mContext; + // Cached values from Context's caps + GLuint mMaxDrawBuffers; + GLuint mMaxCombinedTextureImageUnits; ColorF mColorClearValue; GLclampf mDepthClearValue; @@ -283,7 +287,8 @@ class State GLuint mCurrentProgramId; BindingPointer<ProgramBinary> mCurrentProgramBinary; - VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib + typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector; + VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib VertexArray *mVertexArray; // Texture and sampler bindings @@ -300,11 +305,12 @@ class State ActiveQueryMap mActiveQueries; BindingPointer<Buffer> mGenericUniformBuffer; - OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + typedef std::vector< OffsetBindingPointer<Buffer> > BufferVector; + BufferVector mUniformBuffers; BindingPointer<TransformFeedback> mTransformFeedback; BindingPointer<Buffer> mGenericTransformFeedbackBuffer; - OffsetBindingPointer<Buffer> mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + BufferVector mTransformFeedbackBuffers; BindingPointer<Buffer> mCopyReadBuffer; BindingPointer<Buffer> mCopyWriteBuffer; diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 3ec492de07..cd4fc4e32a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -47,11 +47,14 @@ bool IsPointSampled(const gl::SamplerState &samplerState) return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST)); } +unsigned int Texture::mCurrentTextureSerial = 1; + Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) : RefCountObject(id), mTexture(impl), + mTextureSerial(issueTextureSerial()), mUsage(GL_NONE), - mImmutable(false), + mImmutableLevelCount(0), mTarget(target) { } @@ -72,16 +75,6 @@ void Texture::setUsage(GLenum usage) getImplementation()->setUsage(usage); } -void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler) -{ - *sampler = mSamplerState; - - // Offset the effective base level by the texture storage's top level - rx::TextureStorage *texture = getNativeTexture(); - int topLevel = texture ? texture->getTopLevel() : 0; - sampler->baseLevel = topLevel + mSamplerState.baseLevel; -} - GLenum Texture::getUsage() const { return mUsage; @@ -138,35 +131,35 @@ GLenum Texture::getActualFormat(const ImageIndex &index) const return image->getActualFormat(); } -rx::TextureStorage *Texture::getNativeTexture() +Error Texture::generateMipmaps() { - return getImplementation()->getNativeTexture(); + return getImplementation()->generateMipmaps(); } -void Texture::generateMipmaps() +Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - getImplementation()->generateMipmaps(); + return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); } -void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +unsigned int Texture::getTextureSerial() const { - getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); + return mTextureSerial; } -unsigned int Texture::getTextureSerial() +unsigned int Texture::issueTextureSerial() { - rx::TextureStorage *texture = getNativeTexture(); - return texture ? texture->getTextureSerial() : 0; + return mCurrentTextureSerial++; } bool Texture::isImmutable() const { - return mImmutable; + return (mImmutableLevelCount > 0); } int Texture::immutableLevelCount() { - return (mImmutable ? getNativeTexture()->getLevelCount() : 0); + return mImmutableLevelCount; } int Texture::mipLevels() const @@ -226,11 +219,11 @@ GLenum Texture2D::getActualFormat(GLint level) const return GL_NONE; } -void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { releaseTexImage(); - mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void Texture2D::bindTexImage(egl::Surface *surface) @@ -254,35 +247,44 @@ void Texture2D::releaseTexImage() } } -void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, + const PixelUnpackState &unpack, const void *pixels) { releaseTexImage(); - mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels); + return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels); } -void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); + return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } -void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); + return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); } -void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, + Framebuffer *source) { releaseTexImage(); - mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); + return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); } -void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); + if (error.isError()) + { + return error; + } + + mImmutableLevelCount = levels; - mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); + return Error(GL_NO_ERROR); } // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. @@ -359,11 +361,11 @@ bool Texture2D::isDepth(GLint level) const return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void Texture2D::generateMipmaps() +Error Texture2D::generateMipmaps() { releaseTexImage(); - mTexture->generateMipmaps(); + return mTexture->generateMipmaps(); } // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -467,49 +469,27 @@ GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const return GL_NONE; } -void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels); } -void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels); + return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } -void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); -} - -void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) -{ - mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); + return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -549,16 +529,23 @@ bool TextureCubeMap::isDepth(GLenum target, GLint level) const return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0; } -void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, + GLsizei width, GLsizei height, Framebuffer *source) { - mTexture->copyImage(target, level, format, x, y, width, height, source); + return mTexture->copyImage(target, level, format, x, y, width, height, source); } -void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) +Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); + if (error.isError()) + { + return error; + } + + mImmutableLevelCount = levels; - mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); + return Error(GL_NO_ERROR); } // Tests for texture sampling completeness @@ -734,31 +721,40 @@ bool Texture3D::isDepth(GLint level) const return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); } -void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels); + return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels); } -void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); + return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } -void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); + return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); } -void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); + if (error.isError()) + { + return error; + } - mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); + mImmutableLevelCount = levels; + + return Error(GL_NO_ERROR); } bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const @@ -892,31 +888,40 @@ bool Texture2DArray::isDepth(GLint level) const return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); } -void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels); + return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels); } -void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); + return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } -void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); + return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); } -void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); + if (error.isError()) + { + return error; + } + + mImmutableLevelCount = levels; - mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); + return Error(GL_NO_ERROR); } bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h index ca5686fde3..66d4df8015 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ b/src/3rdparty/angle/src/libGLESv2/Texture.h @@ -14,7 +14,7 @@ #include "common/debug.h" #include "common/RefCountObject.h" #include "libGLESv2/angletypes.h" -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "libGLESv2/renderer/TextureImpl.h" #include "libGLESv2/Caps.h" @@ -52,7 +52,6 @@ class Texture : public RefCountObject const SamplerState &getSamplerState() const { return mSamplerState; } SamplerState &getSamplerState() { return mSamplerState; } - void getSamplerStateWithNativeOffset(SamplerState *sampler); void setUsage(GLenum usage); GLenum getUsage() const; @@ -69,15 +68,16 @@ class Texture : public RefCountObject virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0; - rx::TextureStorage *getNativeTexture(); + virtual Error generateMipmaps(); - virtual void generateMipmaps(); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - unsigned int getTextureSerial(); + // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer. + // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id. + unsigned int getTextureSerial() const; bool isImmutable() const; - int immutableLevelCount(); + GLsizei immutableLevelCount(); rx::TextureImpl *getImplementation() { return mTexture; } const rx::TextureImpl *getImplementation() const { return mTexture; } @@ -86,17 +86,20 @@ class Texture : public RefCountObject protected: int mipLevels() const; + const rx::Image *getBaseLevelImage() const; + static unsigned int issueTextureSerial(); rx::TextureImpl *mTexture; SamplerState mSamplerState; GLenum mUsage; - bool mImmutable; + GLsizei mImmutableLevelCount; GLenum mTarget; - const rx::Image *getBaseLevelImage() const; + const unsigned int mTextureSerial; + static unsigned int mCurrentTextureSerial; private: DISALLOW_COPY_AND_ASSIGN(Texture); @@ -116,18 +119,18 @@ class Texture2D : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual void generateMipmaps(); + virtual Error generateMipmaps(); private: DISALLOW_COPY_AND_ASSIGN(Texture2D); @@ -152,19 +155,12 @@ class TextureCubeMap : public Texture bool isCompressed(GLenum target, GLint level) const; bool isDepth(GLenum target, GLint level) const; - void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - - void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - - void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - void storage(GLsizei levels, GLenum internalformat, GLsizei size); + Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + Error storage(GLsizei levels, GLenum internalformat, GLsizei size); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; @@ -195,11 +191,11 @@ class Texture3D : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; @@ -225,11 +221,11 @@ class Texture2DArray : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h index 993ba042cf..a724c0be1c 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h +++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.h @@ -14,14 +14,13 @@ #define LIBGLESV2_VERTEXARRAY_H_ #include "common/RefCountObject.h" -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "libGLESv2/VertexAttribute.h" #include <vector> namespace rx { -class Renderer; class VertexArrayImpl; } @@ -44,7 +43,7 @@ class VertexArray void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); } + const VertexAttribute* getVertexAttributes() const { return &mVertexAttributes[0]; } Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } void setElementArrayBuffer(Buffer *buffer); GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp index bb6425df64..5a0cfc5ad9 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp @@ -9,6 +9,10 @@ #include "libGLESv2/angletypes.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/State.h" +#include "libGLESv2/VertexArray.h" + +#include <float.h> namespace gl { @@ -148,16 +152,16 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp void VertexFormat::GetInputLayout(VertexFormat *inputLayout, ProgramBinary *programBinary, - const VertexAttribute *attributes, - const gl::VertexAttribCurrentValueData *currentValues) + const State &state) { + const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes(); for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { int semanticIndex = programBinary->getSemanticIndex(attributeIndex); if (semanticIndex != -1) { - inputLayout[semanticIndex] = VertexFormat(attributes[attributeIndex], currentValues[attributeIndex].Type); + inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type); } } } @@ -192,4 +196,15 @@ bool VertexFormat::operator<(const VertexFormat& other) const return mPureInteger < other.mPureInteger; } +bool Box::operator==(const Box &other) const +{ + return (x == other.x && y == other.y && z == other.z && + width == other.width && height == other.height && depth == other.depth); +} + +bool Box::operator!=(const Box &other) const +{ + return !(*this == other); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h index 642a6ec266..78fe6b0e26 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h @@ -9,13 +9,13 @@ #ifndef LIBGLESV2_ANGLETYPES_H_ #define LIBGLESV2_ANGLETYPES_H_ -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "common/RefCountObject.h" -#include <float.h> namespace gl { class Buffer; +class State; class ProgramBinary; struct VertexAttribute; struct VertexAttribCurrentValueData; @@ -66,6 +66,8 @@ struct Box Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { } Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { } + bool operator==(const Box &other) const; + bool operator!=(const Box &other) const; }; struct Extents @@ -230,8 +232,7 @@ struct VertexFormat static void GetInputLayout(VertexFormat *inputLayout, ProgramBinary *programBinary, - const VertexAttribute *attributes, - const gl::VertexAttribCurrentValueData *currentValues); + const State& currentValues); bool operator==(const VertexFormat &other) const; bool operator!=(const VertexFormat &other) const; @@ -251,13 +252,6 @@ enum VertexConversionType VERTEX_CONVERT_BOTH = 3 }; -enum D3DWorkaroundType -{ - ANGLE_D3D_WORKAROUND_NONE, - ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION, - ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION -}; - } #endif // LIBGLESV2_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 07f5d47473..587950a139 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -34,13 +34,12 @@ #include "libGLESv2/validationES3.h" #include "libGLESv2/queryconversions.h" - extern "C" { // OpenGL ES 2.0 functions -void __stdcall glActiveTexture(GLenum texture) +void GL_APIENTRY glActiveTexture(GLenum texture) { EVENT("(GLenum texture = 0x%X)", texture); @@ -57,7 +56,7 @@ void __stdcall glActiveTexture(GLenum texture) } } -void __stdcall glAttachShader(GLuint program, GLuint shader) +void GL_APIENTRY glAttachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); @@ -103,7 +102,7 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) } } -void __stdcall glBeginQueryEXT(GLenum target, GLuint id) +void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); @@ -124,7 +123,7 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) } } -void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) +void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) { EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); @@ -163,7 +162,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* } } -void __stdcall glBindBuffer(GLenum target, GLuint buffer) +void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) { EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); @@ -210,7 +209,7 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) } } -void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) +void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) { EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); @@ -235,7 +234,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) } } -void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) +void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer) { EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); @@ -252,7 +251,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) } } -void __stdcall glBindTexture(GLenum target, GLuint texture) +void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) { EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); @@ -291,7 +290,7 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) } } -void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); @@ -304,12 +303,12 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } } -void __stdcall glBlendEquation(GLenum mode) +void GL_APIENTRY glBlendEquation(GLenum mode) { glBlendEquationSeparate(mode, mode); } -void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); @@ -348,12 +347,12 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) } } -void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor) +void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); } -void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", srcRGB, dstRGB, srcAlpha, dstAlpha); @@ -488,7 +487,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha } } -void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", target, size, data, usage); @@ -550,7 +549,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, } } -void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", target, offset, size, data); @@ -611,7 +610,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, } } -GLenum __stdcall glCheckFramebufferStatus(GLenum target) +GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target) { EVENT("(GLenum target = 0x%X)", target); @@ -626,13 +625,14 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); ASSERT(framebuffer); - return framebuffer->completeness(); + + return framebuffer->completeness(context->getData()); } return 0; } -void __stdcall glClear(GLbitfield mask) +void GL_APIENTRY glClear(GLbitfield mask) { EVENT("(GLbitfield mask = 0x%X)", mask); @@ -640,8 +640,9 @@ void __stdcall glClear(GLbitfield mask) if (context) { gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (framebufferObject->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return; @@ -662,7 +663,7 @@ void __stdcall glClear(GLbitfield mask) } } -void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); @@ -674,7 +675,7 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } } -void __stdcall glClearDepthf(GLclampf depth) +void GL_APIENTRY glClearDepthf(GLclampf depth) { EVENT("(GLclampf depth = %f)", depth); @@ -685,7 +686,7 @@ void __stdcall glClearDepthf(GLclampf depth) } } -void __stdcall glClearStencil(GLint s) +void GL_APIENTRY glClearStencil(GLint s) { EVENT("(GLint s = %d)", s); @@ -696,7 +697,7 @@ void __stdcall glClearStencil(GLint s) } } -void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", red, green, blue, alpha); @@ -708,7 +709,7 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo } } -void __stdcall glCompileShader(GLuint shader) +void GL_APIENTRY glCompileShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); @@ -731,11 +732,11 @@ void __stdcall glCompileShader(GLuint shader) } } - shaderObject->compile(); + shaderObject->compile(context->getData()); } } -void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, +void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " @@ -771,7 +772,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->setCompressedImage(level, internalformat, width, height, imageSize, data); + gl::Error error = texture->setCompressedImage(level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -783,7 +789,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); + gl::Error error = texture->setCompressedImage(target, level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -794,7 +805,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna } } -void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, +void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " @@ -831,7 +842,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); + gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -843,7 +859,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); + gl::Error error = texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -854,7 +875,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs } } -void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", @@ -884,7 +905,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + gl::Error error = texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + if (error.isError()) + { + |