diff options
author | Andrew Knight <andrew.knight@intopalo.com> | 2015-04-08 17:04:36 +0300 |
---|---|---|
committer | Andrew Knight <qt@panimo.net> | 2015-04-09 10:31:12 +0000 |
commit | a218a252c4200cfe7048de81a46f7e48349084d5 (patch) | |
tree | c1a82865d97e610cd0abb3a1360408363b38205b /src/3rdparty | |
parent | 331ddacfca90c91c5b44484bf3c78e2aa5b85947 (diff) | |
download | qtbase-a218a252c4200cfe7048de81a46f7e48349084d5.tar.gz |
Upgrade ANGLE to 2.1~99f075dade7c
This aligns with Chromium branch 2356.
This version brings more complete OpenGL ES 3 support as well as various
bug fixes and performance improvements.
The following changes were made to earlier patches:
-0000-General-fixes-for-ANGLE-2.1
Removed. All changes are now handled elsewhere.
+0001-ANGLE-Improve-Windows-Phone-support
Consolidated remaining parts from 0009/0010.
+0002-ANGLE-Fix-compilation-with-MinGW
Remaining issues from patch 0016.
+0003-ANGLE-Fix-compilation-with-MSVC2010
Remaining issues from patch 0015.
+0004-ANGLE-Dynamically-load-D3D-compiler-from-list
Renamed from patch 0008.
+0005-ANGLE-Add-support-for-querying-platform-device
Renamed from patch 0013.
-0004-Make-it-possible-to-link-ANGLE-statically-for-single
Removed. Fixed by adding defines to project files.
-0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t
Renamed to patch 0005.
-0009-ANGLE-Support-WinRT
Removed. Mostly fixed upstream; remaining parts in patch 0001.
-0010-ANGLE-Enable-D3D11-for-feature-level-9-cards
Removed. Mostly fixed upstream; remaining parts in patch 0001.
-0012-ANGLE-fix-semantic-index-lookup
Removed. Fixed upstream.
-0013-ANGLE-Add-support-for-querying-platform-device
Renamed to patch 0005.
-0014-Let-ANGLE-use-multithreaded-devices-if-necessary
Removed. No longer needed.
-0015-ANGLE-Fix-angle-d3d11-on-MSVC2010
Moved remaining parts to patch 0003.
-0016-ANGLE-Fix-compilation-with-MinGW-D3D11
Moved remaining parts to patch 0002.
-0017-ANGLE-Fix-compilation-with-D3D9
Removed. Fixed upstream.
-0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11
Removed. Fixed upstream.
-0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt
Removed. Fixed upstream.
-0020-ANGLE-Do-not-use-std-strlen
Removed. Fixed upstream.
-0020-ANGLE-Fix-compilation-with-MSVC2013-Update4
Removed. Fixed upstream.
[ChangeLog][Third-party libraries] ANGLE was updated to Chromium branch
2356 (2.1~99f075dade7c).
Change-Id: I32ccbfe95e10986bd94be7191dfd53445ea09158
Task-number: QTBUG-44815
Task-number: QTBUG-37660
Task-number: QTBUG-44694
Task-number: QTBUG-42443
Reviewed-by: Andrew Knight <qt@panimo.net>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Diffstat (limited to 'src/3rdparty')
485 files changed, 38109 insertions, 27559 deletions
diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore index cbb7e6a5af..17958a0fb5 100644 --- a/src/3rdparty/angle/.gitignore +++ b/src/3rdparty/angle/.gitignore @@ -6,19 +6,28 @@ build extensions samples tests -third_party src/ipch +util .svn # Files from ANGLE we don't want/need DEPS +*.chromium +*.isolate +*.md +*.gn *.gyp *.gypi *.sh *.bat *.patch *.py +*.rc +*_unittest.cpp codereview.settings +src/commit.h +src/libANGLE/renderer/gl +src/third_party/khronos/GL # Generated by flex/bison src/compiler/preprocessor/Tokenizer.cpp @@ -28,5 +37,5 @@ src/compiler/translator/glslang_tab.cpp src/compiler/translator/glslang_tab.h # Generated by FXC -src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/*.h -src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/*.h +src/libANGLE/renderer/d3d/d3d9/shaders/compiled/*.h +src/libANGLE/renderer/d3d/d3d11/shaders/compiled/*.h diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index be114bcf68..836bed8e8a 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -16,17 +16,22 @@ Autodesk, Inc. BlackBerry Limited Cable Television Laboratories, Inc. Cloud Party, Inc. +Imagination Technologies Ltd. Intel Corporation Mozilla Corporation Turbulenz Klarälvdalens Datakonsult AB +Microsoft Corporation Microsoft Open Technologies, Inc. NVIDIA Corporation +Opera Software ASA +The Qt Company Ltd. Jacek Caban Mark Callow Ginn Chen Tibor den Ouden +Régis Fénéon James Hauxwell Sam Hocevar Pierre Leveille @@ -35,3 +40,4 @@ Boying Lu Aitor Moreno Yuri O'Donnell Josh Soref +Maks Naumov diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index 6b27416e38..5252141973 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -1,4 +1,4 @@ -# This is the official list of people who can contribute +# This is the official list of people who can contribute # (and who have contributed) code to the ANGLE project # repository. # The AUTHORS file lists the copyright holders; this file @@ -40,6 +40,7 @@ Google Inc. thestig@chromium.org Justin Schuh Scott Graham + Corentin Wallez Adobe Systems Inc. Alexandru Chiculita @@ -55,6 +56,9 @@ Cloud Party, Inc. The Qt Company Ltd. Andrew Knight +Imagination Technologies Ltd. + Gregoire Payen de La Garanderie + Intel Corporation Jin Yang Andy Chen @@ -80,10 +84,21 @@ Mark Banner (standard8mbp) David Kilzer Jacek Caban Tibor den Ouden +Régis Fénéon + +Microsoft Corporation + Cooper Partin + Austin Kinross + Minmin Gong Microsoft Open Technologies, Inc. -Cooper Partin -Austin Kinross + Cooper Partin + Austin Kinross NVIDIA Corporation Olli Etuaho + Arun Patole + Qingqing Deng + +Opera Software ASA + Daniel Bratell diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h index 12590a0e20..5a27291213 100644 --- a/src/3rdparty/angle/include/EGL/egl.h +++ b/src/3rdparty/angle/include/EGL/egl.h @@ -33,12 +33,12 @@ extern "C" { ** used to make the header, and the header can be found at ** http://www.opengl.org/registry/ ** -** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ +** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $ */ #include <EGL/eglplatform.h> -/* Generated on date 20140610 */ +/* Generated on date 20150102 */ /* Generated C header for: * API: egl @@ -240,6 +240,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); typedef void *EGLSync; typedef intptr_t EGLAttrib; typedef khronos_utime_nanoseconds_t EGLTime; +typedef void *EGLImage; #define EGL_CONTEXT_MAJOR_VERSION 0x3098 #define EGL_CONTEXT_MINOR_VERSION 0x30FB #define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD @@ -281,10 +282,14 @@ typedef khronos_utime_nanoseconds_t EGLTime; #define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 #define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 #define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +#define EGL_IMAGE_PRESERVED 0x30D2 +#define EGL_NO_IMAGE ((EGLImage)0) EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image); EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h index 0cc5eec293..a44afecb3f 100644 --- a/src/3rdparty/angle/include/EGL/eglext.h +++ b/src/3rdparty/angle/include/EGL/eglext.h @@ -440,24 +440,28 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #ifndef EGL_ANGLE_platform_angle #define EGL_ANGLE_platform_angle 1 -#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#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 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206 #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 0x3206 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C +#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F #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 0x3209 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E #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 2eb3674a0b..519df3e750 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h @@ -73,15 +73,14 @@ #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 */ +#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */ +typedef HWND EGLNativeWindowType; +#else /* 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 */ @@ -110,6 +109,14 @@ typedef Display *EGLNativeDisplayType; typedef Pixmap EGLNativePixmapType; typedef Window EGLNativeWindowType; +#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) ) + +// TODO(jmadill): native implementation for OSX + +typedef void *EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + #else #error "Platform not recognized" #endif diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index 647fed6a02..126205af2c 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef _COMPILER_INTERFACE_INCLUDED_ -#define _COMPILER_INTERFACE_INCLUDED_ +#ifndef GLSLANG_SHADERLANG_H_ +#define GLSLANG_SHADERLANG_H_ #if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC) #if defined(_WIN32) || defined(_WIN64) @@ -48,7 +48,7 @@ typedef unsigned int GLenum; // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 132 +#define ANGLE_SH_VERSION 134 typedef enum { SH_GLES2_SPEC = 0x8B40, @@ -81,11 +81,16 @@ typedef enum { } ShShaderSpec; typedef enum { - SH_ESSL_OUTPUT = 0x8B45, - SH_GLSL_OUTPUT = 0x8B46, - SH_HLSL_OUTPUT = 0x8B47, - SH_HLSL9_OUTPUT = 0x8B47, - SH_HLSL11_OUTPUT = 0x8B48 + SH_ESSL_OUTPUT = 0x8B45, + // SH_GLSL_OUTPUT is deprecated. This is to not break the build. + SH_GLSL_OUTPUT = 0x8B46, + SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46, + SH_GLSL_CORE_OUTPUT = 0x8B47, + + // HLSL output only supported in some configurations. + SH_HLSL_OUTPUT = 0x8B48, + SH_HLSL9_OUTPUT = 0x8B48, + SH_HLSL11_OUTPUT = 0x8B49 } ShShaderOutput; // Compile options. @@ -223,6 +228,10 @@ typedef struct int EXT_draw_buffers; int EXT_frag_depth; int EXT_shader_texture_lod; + int WEBGL_debug_shader_precision; + int EXT_shader_framebuffer_fetch; + int NV_shader_framebuffer_fetch; + int ARM_shader_framebuffer_fetch; // 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 @@ -290,7 +299,8 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha // spec: Specifies the language spec the compiler must conform to - // SH_GLES2_SPEC or SH_WEBGL_SPEC. // output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT, -// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. +// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only +// supported in some configurations. // resources: Specifies the built-in resources. COMPILER_EXPORT ShHandle ShConstructCompiler( sh::GLenum type, @@ -408,4 +418,4 @@ COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, const std::string &uniformName, unsigned int *indexOut); -#endif // _COMPILER_INTERFACE_INCLUDED_ +#endif // GLSLANG_SHADERLANG_H_ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h index da21c3e76e..4128c343f8 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h @@ -7,8 +7,8 @@ // Types to represent GL variables (varyings, uniforms, etc) // -#ifndef _COMPILER_INTERFACE_VARIABLES_ -#define _COMPILER_INTERFACE_VARIABLES_ +#ifndef GLSLANG_SHADERVARS_H_ +#define GLSLANG_SHADERVARS_H_ #include <string> #include <vector> @@ -28,6 +28,9 @@ enum InterpolationType INTERPOLATION_FLAT }; +// Validate link & SSO consistency of interpolation qualifiers +COMPILER_EXPORT bool InterpolationTypesMatch(InterpolationType a, InterpolationType b); + // Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec enum BlockLayoutType { @@ -182,4 +185,4 @@ struct COMPILER_EXPORT InterfaceBlock } -#endif // _COMPILER_INTERFACE_VARIABLES_ +#endif // GLSLANG_SHADERVARS_H_ diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h index 1ac2d3f324..c9e6f17d34 100644..100755 --- a/src/3rdparty/angle/include/KHR/khrplatform.h +++ b/src/3rdparty/angle/include/KHR/khrplatform.h @@ -97,7 +97,7 @@ *------------------------------------------------------------------------- * This precedes the return type of the function in the function prototype. */ -#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) # define KHRONOS_APICALL __declspec(dllimport) #elif defined (__SYMBIAN32__) # define KHRONOS_APICALL IMPORT_C diff --git a/src/3rdparty/angle/include/angle_gl.h b/src/3rdparty/angle/include/angle_gl.h index d093f75ee2..e7ecdbd2f0 100644 --- a/src/3rdparty/angle/include/angle_gl.h +++ b/src/3rdparty/angle/include/angle_gl.h @@ -7,8 +7,8 @@ // Includes all necessary GL headers and definitions for ANGLE. // -#ifndef ANGLE_GL_H_ -#define ANGLE_GL_H_ +#ifndef ANGLEGL_H_ +#define ANGLEGL_H_ #include "GLES2/gl2.h" #include "GLES2/gl2ext.h" @@ -20,4 +20,4 @@ #define GL_SAMPLER_2D_RECT_ARB 0x8B63 #endif -#endif // ANGLE_GL_H_ +#endif // ANGLEGL_H_ diff --git a/src/3rdparty/angle/include/export.h b/src/3rdparty/angle/include/export.h new file mode 100644 index 0000000000..cdf6245d6d --- /dev/null +++ b/src/3rdparty/angle/include/export.h @@ -0,0 +1,28 @@ +// +// 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. +// + +// export.h : Defines ANGLE_EXPORT, a macro for exporting functions from the DLL + +#ifndef LIBGLESV2_EXPORT_H_ +#define LIBGLESV2_EXPORT_H_ + +#if defined(_WIN32) +# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) +# define ANGLE_EXPORT __declspec(dllexport) +# else +# define ANGLE_EXPORT __declspec(dllimport) +# endif +#elif defined(__GNUC__) +# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) +# define ANGLE_EXPORT __attribute__((visibility ("default"))) +# else +# define ANGLE_EXPORT +# endif +#else +# define ANGLE_EXPORT +#endif + +#endif // LIBGLESV2_EXPORT_H_ diff --git a/src/3rdparty/angle/include/platform/Platform.h b/src/3rdparty/angle/include/platform/Platform.h new file mode 100644 index 0000000000..d915d5c0fd --- /dev/null +++ b/src/3rdparty/angle/include/platform/Platform.h @@ -0,0 +1,112 @@ +// +// Copyright (c) 2015 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. + +// Platform.h: The public interface ANGLE exposes to the API layer, for +// doing platform-specific tasks like gathering data, or for tracing. + +#ifndef ANGLE_PLATFORM_H +#define ANGLE_PLATFORM_H + +#include <stdint.h> + +#include "../export.h" + +namespace angle +{ + +class Platform +{ + public: + + // Tracing -------- + + typedef uint64_t TraceEventHandle; + + // Add a trace event to the platform tracing system. Depending on the actual + // enabled state, this event may be recorded or dropped. + // - phase specifies the type of event: + // - BEGIN ('B'): Marks the beginning of a scoped event. + // - END ('E'): Marks the end of a scoped event. + // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't + // need a matching END event. Instead, at the end of the scope, + // updateTraceEventDuration() must be called with the TraceEventHandle + // returned from addTraceEvent(). + // - INSTANT ('I'): Standalone, instantaneous event. + // - START ('S'): Marks the beginning of an asynchronous event (the end + // event can occur in a different scope or thread). The id parameter is + // used to match START/FINISH pairs. + // - FINISH ('F'): Marks the end of an asynchronous event. + // - COUNTER ('C'): Used to trace integer quantities that change over + // time. The argument values are expected to be of type int. + // - METADATA ('M'): Reserved for internal use. + // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag. + // - name is the name of the event. Also used to match BEGIN/END and + // START/FINISH pairs. + // - id optionally allows events of the same name to be distinguished from + // each other. For example, to trace the consutruction and destruction of + // objects, specify the pointer as the id parameter. + // - numArgs specifies the number of elements in argNames, argTypes, and + // argValues. + // - argNames is the array of argument names. Use long-lived literal strings + // or specify the COPY flag. + // - argTypes is the array of argument types: + // - BOOL (1): bool + // - UINT (2): unsigned long long + // - INT (3): long long + // - DOUBLE (4): double + // - POINTER (5): void* + // - STRING (6): char* (long-lived null-terminated char* string) + // - COPY_STRING (7): char* (temporary null-terminated char* string) + // - CONVERTABLE (8): WebConvertableToTraceFormat + // - argValues is the array of argument values. Each value is the unsigned + // long long member of a union of all supported types. + // - flags can be 0 or one or more of the following, ORed together: + // - COPY (0x1): treat all strings (name, argNames and argValues of type + // string) as temporary so that they will be copied by addTraceEvent. + // - HAS_ID (0x2): use the id argument to uniquely identify the event for + // matching with other events of the same name. + // - MANGLE_ID (0x4): specify this flag if the id parameter is the value + // of a pointer. + virtual TraceEventHandle addTraceEvent(char phase, + const unsigned char *categoryEnabledFlag, + const char *name, + unsigned long long id, + double timestamp, + int numArgs, + const char **argNames, + const unsigned char *argTypes, + const unsigned long long *argValues, + unsigned char flags) + { + return 0; + } + + // Set the duration field of a COMPLETE trace event. + virtual void updateTraceEventDuration(const unsigned char* categoryEnabledFlag, const char* name, TraceEventHandle) { } + + // Callbacks for reporting histogram data. + // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do. + virtual void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount) { } + // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value. + virtual void histogramEnumeration(const char* name, int sample, int boundaryValue) { } + // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets. + virtual void histogramSparse(const char* name, int sample) { } + + protected: + virtual ~Platform() { } +}; + +} + +typedef void(*ANGLEPlatformInitializeFunc)(angle::Platform*); +ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform*); + +typedef void (*ANGLEPlatformShutdownFunc)(); +ANGLE_EXPORT void ANGLEPlatformShutdown(); + +typedef angle::Platform *(*ANGLEPlatformCurrentFunc)(); +ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent(); + +#endif // ANGLE_PLATFORM_H diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h deleted file mode 100644 index 08fc893c25..0000000000 --- a/src/3rdparty/angle/src/commit.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// 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. -// -// commit.h: -// This is a default commit hash header, when git is not available. -// - -#define ANGLE_COMMIT_HASH "30d6c255d238" -#define ANGLE_COMMIT_HASH_SIZE 12 -#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/common/MemoryBuffer.cpp index 2b5b09a324..e7a3fb4a2b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp +++ b/src/3rdparty/angle/src/common/MemoryBuffer.cpp @@ -4,12 +4,13 @@ // found in the LICENSE file. // -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "common/debug.h" +#include "common/MemoryBuffer.h" #include <algorithm> #include <cstdlib> +#include "common/debug.h" + namespace rx { @@ -32,26 +33,31 @@ bool MemoryBuffer::resize(size_t size) free(mData); mData = NULL; mSize = 0; + return true; + } + + if (size == mSize) + { + return true; } - else + + // Only reallocate if the size has changed. + uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size)); + if (newMemory == NULL) + { + return false; + } + + if (mData) { - uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size)); - if (newMemory == NULL) - { - return false; - } - - if (mData) - { - // Copy the intersection of the old data and the new data - std::copy(mData, mData + std::min(mSize, size), newMemory); - free(mData); - } - - mData = newMemory; - mSize = size; + // Copy the intersection of the old data and the new data + std::copy(mData, mData + std::min(mSize, size), newMemory); + free(mData); } + mData = newMemory; + mSize = size; + return true; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/src/3rdparty/angle/src/common/MemoryBuffer.h index c65f79fe10..ec621cbca7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h +++ b/src/3rdparty/angle/src/common/MemoryBuffer.h @@ -4,16 +4,18 @@ // found in the LICENSE file. // -#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ -#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ +#ifndef COMMON_MEMORYBUFFER_H_ +#define COMMON_MEMORYBUFFER_H_ + +#include "common/angleutils.h" #include <cstddef> -#include <cstdint> +#include <stdint.h> namespace rx { -class MemoryBuffer +class MemoryBuffer : angle::NonCopyable { public: MemoryBuffer(); @@ -33,4 +35,4 @@ class MemoryBuffer } -#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H +#endif // COMMON_MEMORYBUFFER_H_ diff --git a/src/3rdparty/angle/src/common/Optional.h b/src/3rdparty/angle/src/common/Optional.h new file mode 100644 index 0000000000..9665b7ddf6 --- /dev/null +++ b/src/3rdparty/angle/src/common/Optional.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2015 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. +// +// Optional.h: +// Represents a type that may be invalid, similar to std::optional. +// + +#ifndef COMMON_OPTIONAL_H_ +#define COMMON_OPTIONAL_H_ + +template <class T> +struct Optional +{ + Optional() + : mValid(false), + mValue(T()) + {} + + explicit Optional(const T &valueIn) + : mValid(true), + mValue(valueIn) + {} + + Optional(const Optional &other) + : mValid(other.mValid), + mValue(other.mValue) + {} + + Optional &operator=(const Optional &other) + { + this->mValid = other.mValid; + this->mValue = other.mValue; + return *this; + } + + static Optional None() + { + return Optional(); + } + + bool valid() const { return mValid; } + const T &value() const { return mValue; } + + bool operator==(const Optional &other) const + { + return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue))); + } + + bool operator!=(const Optional &other) const + { + return !(*this == other); + } + + private: + bool mValid; + T mValue; +}; + +#endif // COMMON_OPTIONAL_H_ diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h deleted file mode 100644 index 6eeaee1928..0000000000 --- a/src/3rdparty/angle/src/common/RefCountObject.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright (c) 2002-2010 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. -// - -// RefCountObject.h: Defines the gl::RefCountObject base class that provides -// lifecycle support for GL objects using the traditional BindObject scheme, but -// that need to be reference counted for correct cross-context deletion. -// (Concretely, textures, buffers and renderbuffers.) - -#ifndef COMMON_REFCOUNTOBJECT_H_ -#define COMMON_REFCOUNTOBJECT_H_ - -#include "common/debug.h" - -#include "angle_gl.h" - -#include <cstddef> - -class RefCountObject -{ - public: - explicit RefCountObject(GLuint id); - virtual ~RefCountObject(); - - virtual void addRef() const; - virtual void release() const; - - GLuint id() const { return mId; } - - private: - GLuint mId; - - mutable std::size_t mRefCount; -}; - -class RefCountObjectBindingPointer -{ - protected: - RefCountObjectBindingPointer() : mObject(NULL) { } - ~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up. - - void set(RefCountObject *newObject); - RefCountObject *get() const { return mObject; } - - public: - GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; } - bool operator!() const { return (get() == NULL); } - - private: - RefCountObject *mObject; -}; - -template <class ObjectType> -class BindingPointer : public RefCountObjectBindingPointer -{ - public: - void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); } - ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); } - ObjectType *operator->() const { return get(); } -}; - -template <class ObjectType> -class OffsetBindingPointer : public RefCountObjectBindingPointer -{ - public: - OffsetBindingPointer() : mOffset(0), mSize(0) { } - - void set(ObjectType *newObject) - { - RefCountObjectBindingPointer::set(newObject); - mOffset = 0; - mSize = 0; - } - - void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size) - { - RefCountObjectBindingPointer::set(newObject); - mOffset = offset; - mSize = size; - } - - GLintptr getOffset() const { return mOffset; } - GLsizeiptr getSize() const { return mSize; } - - ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); } - ObjectType *operator->() const { return get(); } - - private: - GLintptr mOffset; - GLsizeiptr mSize; -}; - -#endif // COMMON_REFCOUNTOBJECT_H_ diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp index c1367c460a..af5eb6c447 100644 --- a/src/3rdparty/angle/src/common/angleutils.cpp +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -5,7 +5,8 @@ // #include "common/angleutils.h" -#include "debug.h" +#include "common/debug.h" + #include <stdio.h> #include <vector> diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index b343ece5bc..4cf84a3182 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -11,19 +11,31 @@ #include "common/platform.h" -#include <stddef.h> -#include <limits.h> +#include <climits> +#include <cstdarg> +#include <cstddef> #include <string> #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 -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) +// A helper class to disallow copy and assignment operators +namespace angle +{ + +class NonCopyable +{ +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) + public: + NonCopyable() = default; + ~NonCopyable() = default; + protected: + NonCopyable(const NonCopyable&) = delete; + void operator=(const NonCopyable&) = delete; +#endif +}; + +} template <typename T, size_t N> inline size_t ArraySize(T(&)[N]) @@ -150,13 +162,12 @@ std::string FormatString(const char *fmt, ...); #define snprintf _snprintf #endif -#define VENDOR_ID_AMD 0x1002 -#define VENDOR_ID_INTEL 0x8086 -#define VENDOR_ID_NVIDIA 0x10DE - #define GL_BGRA4_ANGLEX 0x6ABC #define GL_BGR5_A1_ANGLEX 0x6ABD #define GL_INT_64_ANGLEX 0x6ABE #define GL_STRUCT_ANGLEX 0x6ABF +// Hidden enum for the NULL D3D device type. +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0 + #endif // COMMON_ANGLEUTILS_H_ diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index 5f55ff1e39..2fc0a2984a 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -17,172 +17,9 @@ namespace gl { -#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; -}; -#if defined(ANGLE_ENABLE_D3D9) -class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper +namespace { - 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 - - // Otherwise, we have to return true here. - return true; - } - - protected: - - void initializeDevice() - { - if (!mInitialized) - { -#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 - enum DebugTraceOutputType { DebugTraceOutputTypeNone, @@ -190,29 +27,44 @@ enum DebugTraceOutputType 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); +DebugAnnotator *g_debugAnnotator = nullptr; - if (perfActive()) +void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType, + const char *format, va_list vararg) +{ + if (DebugAnnotationsActive()) { + static std::vector<char> buffer(512); size_t len = FormatStringIntoVector(format, vararg, buffer); std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len); + ASSERT(g_debugAnnotator != nullptr); switch (outputType) { - case DebugTraceOutputTypeNone: - break; - case DebugTraceOutputTypeBeginEvent: - g_DebugAnnotationWrapper->beginEvent(formattedWideMessage); - break; - case DebugTraceOutputTypeSetMarker: - g_DebugAnnotationWrapper->setMarker(formattedWideMessage); - break; + case DebugTraceOutputTypeNone: + break; + case DebugTraceOutputTypeBeginEvent: + g_debugAnnotator->beginEvent(formattedWideMessage); + break; + case DebugTraceOutputTypeSetMarker: + g_debugAnnotator->setMarker(formattedWideMessage); + break; } } -#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS + + std::string formattedMessage; + UNUSED_TRACE_VARIABLE(formattedMessage); + +#if !defined(NDEBUG) && defined(_MSC_VER) + if (messageType == MESSAGE_ERR) + { + if (formattedMessage.empty()) + { + formattedMessage = FormatString(format, vararg); + } + OutputDebugStringA(formattedMessage.c_str()); + } +#endif #if defined(ANGLE_ENABLE_DEBUG_TRACE) #if defined(NDEBUG) @@ -221,7 +73,10 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const return; } #endif // NDEBUG - std::string formattedMessage = FormatString(format, vararg); + if (formattedMessage.empty()) + { + formattedMessage = FormatString(format, vararg); + } static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) @@ -237,53 +92,57 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const #endif // ANGLE_ENABLE_DEBUG_TRACE } -void trace(bool traceInDebugOnly, const char *format, ...) +} // namespace + +bool DebugAnnotationsActive() { - va_list vararg; - va_start(vararg, format); #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg); + return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus(); #else - output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg); + return false; #endif - va_end(vararg); } -bool perfActive() +void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator) { -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - static bool active = g_DebugAnnotationWrapper->getStatus(); - return active; -#else - return false; -#endif + UninitializeDebugAnnotations(); + g_debugAnnotator = debugAnnotator; +} + +void UninitializeDebugAnnotations() +{ + // Pointer is not managed. + g_debugAnnotator = nullptr; +} + +void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...) +{ + va_list vararg; + va_start(vararg, format); + output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg); + va_end(vararg); } ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { #if !defined(ANGLE_ENABLE_DEBUG_TRACE) - if (!perfActive()) + if (!DebugAnnotationsActive()) { return; } #endif // !ANGLE_ENABLE_DEBUG_TRACE va_list vararg; va_start(vararg, format); -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - output(true, DebugTraceOutputTypeBeginEvent, format, vararg); -#else - output(true, DebugTraceOutputTypeNone, format, vararg); -#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS + output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg); va_end(vararg); } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - if (perfActive()) + if (DebugAnnotationsActive()) { - g_DebugAnnotationWrapper->endEvent(); + g_debugAnnotator->endEvent(); } -#endif } + } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index c177f51314..c4f118ebae 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -9,8 +9,9 @@ #ifndef COMMON_DEBUG_H_ #define COMMON_DEBUG_H_ -#include <stdio.h> #include <assert.h> +#include <stdio.h> +#include <string> #include "common/angleutils.h" @@ -20,50 +21,71 @@ namespace gl { - // Outputs text to the debugging log, or the debugging window - void trace(bool traceInDebugOnly, const char *format, ...); - // Returns whether D3DPERF is active. - bool perfActive(); +enum MessageType +{ + MESSAGE_TRACE, + MESSAGE_FIXME, + MESSAGE_ERR, + MESSAGE_EVENT, +}; - // Pairs a D3D begin event with an end event. - class ScopedPerfEventHelper - { - public: - ScopedPerfEventHelper(const char* format, ...); - ~ScopedPerfEventHelper(); +// Outputs text to the debugging log, or the debugging window +void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...); - private: - DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper); - }; +// Pairs a D3D begin event with an end event. +class ScopedPerfEventHelper : angle::NonCopyable +{ + public: + ScopedPerfEventHelper(const char* format, ...); + ~ScopedPerfEventHelper(); +}; + +// Wraps the D3D9/D3D11 debug annotation functions. +class DebugAnnotator : angle::NonCopyable +{ + public: + DebugAnnotator() { }; + virtual ~DebugAnnotator() { }; + virtual void beginEvent(const std::wstring &eventName) = 0; + virtual void endEvent() = 0; + virtual void setMarker(const std::wstring &markerName) = 0; + virtual bool getStatus() = 0; +}; + +void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator); +void UninitializeDebugAnnotations(); +bool DebugAnnotationsActive(); - 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_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ANGLE_TRACE_ENABLED +#endif + +// A macro to output a trace of a function call and its arguments to the debugging log +#if defined(ANGLE_TRACE_ENABLED) +#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "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_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#if defined(ANGLE_TRACE_ENABLED) +#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "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_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#if defined(ANGLE_TRACE_ENABLED) +#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "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_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) +#if defined(ANGLE_TRACE_ENABLED) #if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); #else @@ -73,6 +95,10 @@ namespace gl #define EVENT(message, ...) (void(0)) #endif +#if defined(ANGLE_TRACE_ENABLED) +#undef ANGLE_TRACE_ENABLED +#endif + // A macro asserting a condition and outputting failures to the debug log #if !defined(NDEBUG) #define ASSERT(expression) do { \ @@ -130,14 +156,4 @@ namespace gl #define HAS_DYNAMIC_TYPE(type, obj) true #endif -// A macro functioning as a compile-time assert to validate constant conditions -#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 -#define META_ASSERT_CONCAT2(a, b) META_ASSERT_CONCAT(a, b) -#define META_ASSERT_MSG(condition, msg) typedef int META_ASSERT_CONCAT2(COMPILE_TIME_ASSERT_, __LINE__)[static_cast<bool>(condition)?1:-1] -#endif -#define META_ASSERT(condition) META_ASSERT_MSG(condition, "compile time assertion failed.") - #endif // COMMON_DEBUG_H_ diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp new file mode 100644 index 0000000000..eb0c98c9e5 --- /dev/null +++ b/src/3rdparty/angle/src/common/event_tracer.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2012 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 "common/event_tracer.h" + +namespace gl +{ + +GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag; +AddTraceEventFunc g_addTraceEvent; + +} // namespace gl + +namespace gl +{ + +const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name) +{ + if (g_getCategoryEnabledFlag) + { + return g_getCategoryEnabledFlag(name); + } + static unsigned char disabled = 0; + return &disabled; +} + +void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, + int numArgs, const char** argNames, const unsigned char* argTypes, + const unsigned long long* argValues, unsigned char flags) +{ + if (g_addTraceEvent) + { + g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags); + } +} + +} // namespace gl diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h new file mode 100644 index 0000000000..dbe4c1bef9 --- /dev/null +++ b/src/3rdparty/angle/src/common/event_tracer.h @@ -0,0 +1,34 @@ +// Copyright (c) 2012 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 COMMON_EVENT_TRACER_H_ +#define COMMON_EVENT_TRACER_H_ + +#include "common/platform.h" + +extern "C" { + +typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); +typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name, + unsigned long long id, int numArgs, const char** argNames, + const unsigned char* argTypes, const unsigned long long* argValues, + unsigned char flags); + +} + +namespace gl +{ + +extern GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag; +extern AddTraceEventFunc g_addTraceEvent; + +const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name); + +void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, + int numArgs, const char** argNames, const unsigned char* argTypes, + const unsigned long long* argValues, unsigned char flags); + +} + +#endif // COMMON_EVENT_TRACER_H_ diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index a1717892fd..1015bd2312 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -6,8 +6,8 @@ // mathutil.h: Math and bit manipulation functions. -#ifndef LIBGLESV2_MATHUTIL_H_ -#define LIBGLESV2_MATHUTIL_H_ +#ifndef COMMON_MATHUTIL_H_ +#define COMMON_MATHUTIL_H_ #include "common/debug.h" #include "common/platform.h" @@ -15,6 +15,7 @@ #include <limits> #include <algorithm> #include <string.h> +#include <stdlib.h> namespace gl { @@ -118,6 +119,9 @@ inline bool supportsSSE2() return supports; } +#if defined(__GNUC__) + supports = __builtin_cpu_supports("sse2"); +#else int info[4]; __cpuid(info, 0); @@ -127,6 +131,7 @@ inline bool supportsSSE2() supports = (info[3] >> 26) & 1; } +#endif checked = true; @@ -353,7 +358,7 @@ inline float float11ToFloat32(unsigned short fp11) } else // The value is zero { - exponent = -112; + exponent = static_cast<unsigned short>(-112); } return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17)); @@ -392,7 +397,7 @@ inline float float10ToFloat32(unsigned short fp11) } else // The value is zero { - exponent = -112; + exponent = static_cast<unsigned short>(-112); } return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18)); @@ -402,7 +407,7 @@ inline float float10ToFloat32(unsigned short fp11) template <typename T> inline float normalizedToFloat(T input) { - META_ASSERT(std::numeric_limits<T>::is_integer); + static_assert(std::numeric_limits<T>::is_integer, "T must be an integer."); const float inverseMax = 1.0f / std::numeric_limits<T>::max(); return input * inverseMax; @@ -411,8 +416,8 @@ inline float normalizedToFloat(T input) template <unsigned int inputBitCount, typename T> inline float normalizedToFloat(T input) { - META_ASSERT(std::numeric_limits<T>::is_integer); - META_ASSERT(inputBitCount < (sizeof(T) * 8)); + static_assert(std::numeric_limits<T>::is_integer, "T must be an integer."); + static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount."); const float inverseMax = 1.0f / ((1 << inputBitCount) - 1); return input * inverseMax; @@ -427,14 +432,15 @@ inline T floatToNormalized(float input) template <unsigned int outputBitCount, typename T> inline T floatToNormalized(float input) { - META_ASSERT(outputBitCount < (sizeof(T) * 8)); + static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount."); return ((1 << outputBitCount) - 1) * input + 0.5f; } template <unsigned int inputBitCount, unsigned int inputBitStart, typename T> inline T getShiftedData(T input) { - META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8)); + static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8), + "T must have at least as many bits as inputBitCount + inputBitStart."); const T mask = (1 << inputBitCount) - 1; return (input >> inputBitStart) & mask; } @@ -442,7 +448,8 @@ inline T getShiftedData(T input) template <unsigned int inputBitCount, unsigned int inputBitStart, typename T> inline T shiftData(T input) { - META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8)); + static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8), + "T must have at least as many bits as inputBitCount + inputBitStart."); const T mask = (1 << inputBitCount) - 1; return (input & mask) << inputBitStart; } @@ -503,6 +510,7 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b) namespace rx { +// Represents intervals of the type [a, b) template <typename T> struct Range { @@ -513,6 +521,18 @@ struct Range T end; T length() const { return end - start; } + + bool intersects(Range<T> other) + { + if (start <= other.start) + { + return other.start < end; + } + else + { + return start < other.end; + } + } }; typedef Range<int> RangeI; @@ -533,14 +553,14 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor) template <class T> inline bool IsUnsignedAdditionSafe(T lhs, T rhs) { - META_ASSERT(!std::numeric_limits<T>::is_signed); + static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned."); return (rhs <= std::numeric_limits<T>::max() - lhs); } template <class T> inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs) { - META_ASSERT(!std::numeric_limits<T>::is_signed); + static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned."); return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits<T>::max() / lhs)); } @@ -550,6 +570,21 @@ inline bool IsIntegerCastSafe(BigIntT bigValue) return (static_cast<BigIntT>(static_cast<SmallIntT>(bigValue)) == bigValue); } +#if defined(_MSC_VER) + +#define ANGLE_ROTL(x,y) _rotl(x,y) + +#else + +inline uint32_t RotL(uint32_t x, int8_t r) +{ + return (x << r) | (x >> (32 - r)); +} + +#define ANGLE_ROTL(x,y) RotL(x,y) + +#endif // namespace rx + } -#endif // LIBGLESV2_MATHUTIL_H_ +#endif // COMMON_MATHUTIL_H_ diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index 5bf97f9184..3a2aa91bed 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -14,12 +14,12 @@ #elif defined(__APPLE__) # define ANGLE_PLATFORM_APPLE 1 # define ANGLE_PLATFORM_POSIX 1 -#elif defined(__linux__) -# define ANGLE_PLATFORM_LINUX 1 -# define ANGLE_PLATFORM_POSIX 1 #elif defined(ANDROID) # define ANGLE_PLATFORM_ANDROID 1 # define ANGLE_PLATFORM_POSIX 1 +#elif defined(__linux__) || defined(EMSCRIPTEN) +# define ANGLE_PLATFORM_LINUX 1 +# define ANGLE_PLATFORM_POSIX 1 #elif defined(__FreeBSD__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) || \ @@ -34,9 +34,6 @@ #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,24 +47,32 @@ # include <windows.h> # include <intrin.h> +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP) +# define ANGLE_ENABLE_WINDOWS_STORE 1 +# endif + # if defined(ANGLE_ENABLE_D3D9) # include <d3d9.h> -# include <dxgi.h> -# if !defined(COMPILER_IMPLEMENTATION) +# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION) # include <d3dcompiler.h> # endif # endif # if defined(ANGLE_ENABLE_D3D11) # include <d3d10_1.h> -# include <d3d10.h> # include <d3d11.h> # include <dxgi.h> -# if defined(_MSC_VER) && (_MSC_VER >= 1700) +# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__) +# define ANGLE_MINGW32_COMPAT +# endif +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# define ANGLE_ENABLE_D3D11_1 +# endif +# if defined(ANGLE_ENABLE_D3D11_1) # include <d3d11_1.h> # include <dxgi1_2.h> # endif -# if !defined(COMPILER_IMPLEMENTATION) +# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION) # include <d3dcompiler.h> # endif # endif @@ -75,88 +80,24 @@ # if defined(ANGLE_ENABLE_WINDOWS_STORE) # include <dxgi1_3.h> # if defined(_DEBUG) -# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) +# 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 -} D3D11_MAP_FLAG; -typedef struct D3D11_QUERY_DATA_SO_STATISTICS -{ - UINT64 NumPrimitivesWritten; - UINT64 PrimitivesStorageNeeded; -} D3D11_QUERY_DATA_SO_STATISTICS; -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__ +# if defined(_MSC_VER) && (_MSC_VER <= 1600) +# define final +# define override +# endif # undef near # undef far #endif +#if !defined(_M_ARM) && !defined(ANGLE_PLATFORM_ANDROID) +# define ANGLE_USE_SSE +#endif + #endif // COMMON_PLATFORM_H_ diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h index 8a06e92d1a..ca9e07ab70 100644 --- a/src/3rdparty/angle/src/common/tls.h +++ b/src/3rdparty/angle/src/common/tls.h @@ -15,7 +15,9 @@ // TLS does not exist for Windows Store and needs to be emulated # ifdef ANGLE_ENABLE_WINDOWS_STORE -# define TLS_OUT_OF_INDEXES -1 +# ifndef TLS_OUT_OF_INDEXES +# define TLS_OUT_OF_INDEXES static_cast<DWORD>(0xFFFFFFFF) +# endif # ifndef CREATE_SUSPENDED # define CREATE_SUSPENDED 0x00000004 # endif diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp index 0eae42cac2..501e9c2564 100644 --- a/src/3rdparty/angle/src/common/utilities.cpp +++ b/src/3rdparty/angle/src/common/utilities.cpp @@ -254,7 +254,7 @@ int VariableColumnCount(GLenum type) return 0; } -bool IsSampler(GLenum type) +bool IsSamplerType(GLenum type) { switch (type) { @@ -343,9 +343,27 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig return -1; } -bool IsCubemapTextureTarget(GLenum target) +static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value."); + +bool IsCubeMapTextureTarget(GLenum target) +{ + return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget); +} + +size_t CubeMapTextureTargetToLayerIndex(GLenum target) { - return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + ASSERT(IsCubeMapTextureTarget(target)); + return target - static_cast<size_t>(FirstCubeMapTextureTarget); +} + +GLenum LayerIndexToCubeMapTextureTarget(size_t index) +{ + ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget)); + return FirstCubeMapTextureTarget + static_cast<GLenum>(index); } bool IsTriangleMode(GLenum drawMode) @@ -486,10 +504,15 @@ void writeFile(const char* path, const void* content, size_t size) } #endif // !ANGLE_ENABLE_WINDOWS_STORE -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101 +#if defined (ANGLE_PLATFORM_WINDOWS) -void Sleep(unsigned long dwMilliseconds) +// Causes the thread to relinquish the remainder of its time slice to any +// other thread that is ready to run.If there are no other threads ready +// to run, the function returns immediately, and the thread continues execution. +void ScheduleYield() { +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + // This implementation of Sleep exists because it is not available prior to Update 4. static HANDLE singletonEvent = nullptr; HANDLE sleepEvent = singletonEvent; if (!sleepEvent) @@ -510,7 +533,10 @@ void Sleep(unsigned long dwMilliseconds) } // Emulate sleep by waiting with timeout on an event that is never signalled. - WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); + WaitForSingleObjectEx(sleepEvent, 0, false); +#else + Sleep(0); +#endif } -#endif // ANGLE_ENABLE_WINDOWS_STORE +#endif diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h index 7583d3e160..9f7f5e03c0 100644 --- a/src/3rdparty/angle/src/common/utilities.h +++ b/src/3rdparty/angle/src/common/utilities.h @@ -6,8 +6,8 @@ // utilities.h: Conversion functions and other utility routines. -#ifndef LIBGLESV2_UTILITIES_H -#define LIBGLESV2_UTILITIES_H +#ifndef COMMON_UTILITIES_H_ +#define COMMON_UTILITIES_H_ #include "angle_gl.h" #include <string> @@ -24,7 +24,7 @@ size_t VariableExternalSize(GLenum type); GLenum VariableBoolVectorType(GLenum type); int VariableRowCount(GLenum type); int VariableColumnCount(GLenum type); -bool IsSampler(GLenum type); +bool IsSamplerType(GLenum type); bool IsMatrixType(GLenum type); GLenum TransposeMatrixType(GLenum type); int VariableRegisterCount(GLenum type); @@ -34,7 +34,11 @@ int VariableSortOrder(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); -bool IsCubemapTextureTarget(GLenum target); +static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; +static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; +bool IsCubeMapTextureTarget(GLenum target); +size_t CubeMapTextureTargetToLayerIndex(GLenum target); +GLenum LayerIndexToCubeMapTextureTarget(size_t index); bool IsTriangleMode(GLenum drawMode); @@ -51,8 +55,8 @@ std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); #endif -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101 -void Sleep(_In_ unsigned long dwMilliseconds); +#if defined (ANGLE_PLATFORM_WINDOWS) +void ScheduleYield(); #endif -#endif // LIBGLESV2_UTILITIES_H +#endif // COMMON_UTILITIES_H_ diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index f01e0242cb..758c78d44a 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -1,4 +1,13 @@ -#include "../commit.h" +// +// 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 COMMON_VERSION_H_ +#define COMMON_VERSION_H_ + +#include "id/commit.h" #define ANGLE_MAJOR_VERSION 2 #define ANGLE_MINOR_VERSION 1 @@ -10,3 +19,5 @@ ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \ ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \ ANGLE_COMMIT_HASH + +#endif // COMMON_VERSION_H_ diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h deleted file mode 100644 index 1c5512417d..0000000000 --- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h index a7587ed657..5922d03857 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ -#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ +#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_ +#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_ #include <string> @@ -84,4 +84,5 @@ class Diagnostics }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ + +#endif // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h index eec0d5e5f0..cf67895764 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ +#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_ #include <string> @@ -41,4 +41,5 @@ class DirectiveHandler }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ + +#endif // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h index 335091781c..e1acdbb8d0 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_ #include "Lexer.h" #include "Macro.h" @@ -78,5 +78,5 @@ class DirectiveParser : public Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#endif // COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h index f040cb01fa..4b80ba7261 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ -#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ +#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ +#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ #include "pp_utils.h" @@ -31,4 +31,5 @@ class ExpressionParser }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ + +#endif // COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y index 662a31b650..8caf36bfc8 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser. #pragma GCC diagnostic ignored "-Wuninitialized" #endif #elif defined(_MSC_VER) -#pragma warning(disable: 4065 4701) +#pragma warning(disable: 4065 4701 4702) #endif #include "ExpressionParser.h" @@ -69,7 +69,7 @@ struct Context %} %pure-parser -%name-prefix="pp" +%name-prefix "pp" %parse-param {Context *context} %lex-param {Context *context} diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h index 2ac4f0c170..e951cb4d5f 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Input.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h @@ -58,5 +58,5 @@ class Input }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_INPUT_H_ +#endif // COMPILER_PREPROCESSOR_INPUT_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h index d42d3db7e0..990dc5e21d 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h @@ -21,5 +21,5 @@ class Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_LEXER_H_ +#endif // COMPILER_PREPROCESSOR_LEXER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h index b77e7bc15c..7662a9c5a2 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h @@ -46,4 +46,5 @@ struct Macro typedef std::map<std::string, Macro> MacroSet; } // namespace pp + #endif // COMPILER_PREPROCESSOR_MACRO_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h index d4fd091786..5a0c7751a8 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ -#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_ +#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_ #include <cassert> #include <memory> @@ -85,5 +85,5 @@ class MacroExpander : public Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#endif // COMPILER_PREPROCESSOR_MACROEXPANDER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h index 0a55f1c9c1..fe25daa123 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h @@ -50,5 +50,5 @@ class Preprocessor }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ +#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h index d4c1a5e178..af8a8d5d19 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ -#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ +#ifndef COMPILER_PREPROCESSOR_SOURCELOCATION_H_ +#define COMPILER_PREPROCESSOR_SOURCELOCATION_H_ namespace pp { @@ -43,4 +43,5 @@ inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs) } } // namespace pp -#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ + +#endif // COMPILER_PREPROCESSOR_SOURCELOCATION_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h index 8832e279c7..347c47e307 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Token.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h @@ -116,4 +116,5 @@ inline bool operator!=(const Token &lhs, const Token &rhs) extern std::ostream &operator<<(std::ostream &out, const Token &token); } // namepsace pp + #endif // COMPILER_PREPROCESSOR_TOKEN_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h index 07ad93da05..78eb86dd3b 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h @@ -55,5 +55,5 @@ class Tokenizer : public Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ +#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l index 2a77b905a4..89cb5c8596 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -267,7 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") namespace pp { -Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(0) +Tokenizer::Tokenizer(Diagnostics *diagnostics) + : mHandle(0), + mMaxTokenSize(256) { mContext.diagnostics = diagnostics; } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h index 8a24540696..58c51b0961 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h @@ -6,8 +6,8 @@ // numeric_lex.h: Functions to extract numeric values from string. -#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ -#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ +#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_ +#define COMPILER_PREPROCESSOR_NUMERICLEX_H_ #include <sstream> @@ -58,4 +58,5 @@ bool numeric_lex_float(const std::string &str, FloatType *value) } } // namespace pp. -#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ + +#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h index 324b0669f4..ee1428b2d3 100644 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#ifndef _BASICTYPES_INCLUDED_ -#define _BASICTYPES_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_BASETYPES_H_ +#define COMPILER_TRANSLATOR_BASETYPES_H_ -#include <assert.h> +#include "compiler/translator/compilerdebug.h" // // Precision qualifiers @@ -42,7 +42,15 @@ enum TBasicType EbtInt, EbtUInt, EbtBool, - EbtGVec4, // non type: represents vec4, ivec4 and uvec4 + EbtGVec4, // non type: represents vec4, ivec4, and uvec4 + EbtGenType, // non type: represents float, vec2, vec3, and vec4 + EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4 + EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4 + EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4 + EbtVec, // non type: represents vec2, vec3, and vec4 + EbtIVec, // non type: represents ivec2, ivec3, and ivec4 + EbtUVec, // non type: represents uvec2, uvec3, and uvec4 + EbtBVec, // non type: represents bvec2, bvec3, and bvec4 EbtGuardSamplerBegin, // non type: see implementation of IsSampler() EbtSampler2D, EbtSampler3D, @@ -62,10 +70,10 @@ enum TBasicType EbtSamplerCubeShadow, EbtSampler2DArrayShadow, EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtGSampler2D, // non type: represents sampler2D, isampler2D and usampler2D - EbtGSampler3D, // non type: represents sampler3D, isampler3D and usampler3D - EbtGSamplerCube, // non type: represents samplerCube, isamplerCube and usamplerCube - EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray and usampler2DArray + EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D + EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D + EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube + EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray EbtStruct, EbtInterfaceBlock, EbtAddress, // should be deprecated?? @@ -258,6 +266,11 @@ inline bool IsShadowSampler(TBasicType type) return false; } +inline bool IsInteger(TBasicType type) +{ + return type == EbtInt || type == EbtUInt; +} + inline bool SupportsPrecision(TBasicType type) { return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type); @@ -293,6 +306,9 @@ enum TQualifier EvqInOut, EvqConstReadOnly, + // built-ins read by vertex shader + EvqInstanceID, + // built-ins written by vertex shader EvqPosition, EvqPointSize, @@ -307,6 +323,10 @@ enum TQualifier EvqFragData, EvqFragDepth, + // built-ins written by the shader_framebuffer_fetch extension(s) + EvqLastFragColor, + EvqLastFragData, + // GLSL ES 3.0 vertex output and fragment input EvqSmooth, // Incomplete qualifier, smooth is the default EvqFlat, // Incomplete qualifier @@ -383,6 +403,7 @@ inline const char* getQualifierString(TQualifier q) case EvqIn: return "in"; break; case EvqOut: return "out"; break; case EvqInOut: return "inout"; break; + case EvqInstanceID: return "InstanceID"; break; case EvqPosition: return "Position"; break; case EvqPointSize: return "PointSize"; break; case EvqFragCoord: return "FragCoord"; break; @@ -396,7 +417,9 @@ inline const char* getQualifierString(TQualifier q) case EvqSmoothIn: return "smooth in"; break; case EvqCentroidIn: return "centroid in"; break; case EvqFlatIn: return "flat in"; break; - default: return "unknown qualifier"; + case EvqLastFragColor: return "LastFragColor"; break; + case EvqLastFragData: return "LastFragData"; break; + default: UNREACHABLE(); return "unknown qualifier"; } } @@ -407,7 +430,7 @@ inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq) case EmpUnspecified: return "mp_unspecified"; case EmpRowMajor: return "row_major"; case EmpColumnMajor: return "column_major"; - default: return "unknown matrix packing"; + default: UNREACHABLE(); return "unknown matrix packing"; } } @@ -419,7 +442,7 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq) case EbsShared: return "shared"; case EbsPacked: return "packed"; case EbsStd140: return "std140"; - default: return "unknown block storage"; + default: UNREACHABLE(); return "unknown block storage"; } } @@ -433,8 +456,8 @@ inline const char* getInterpolationString(TQualifier q) case EvqSmoothIn: return "smooth"; break; case EvqCentroidIn: return "centroid"; break; case EvqFlatIn: return "flat"; break; - default: return "unknown interpolation"; + default: UNREACHABLE(); return "unknown interpolation"; } } -#endif // _BASICTYPES_INCLUDED_ +#endif // COMPILER_TRANSLATOR_BASETYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp index 0e8239cc1e..51461207c5 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -8,193 +8,9 @@ #include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/SymbolTable.h" -namespace { - -// we use macros here instead of function definitions to work around more GLSL -// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are -// problematic because if the argument has side-effects they will be repeatedly -// evaluated. This is unlikely to show up in real shaders, but is something to -// consider. -const char* kFunctionEmulationVertexSource[] = { - "#error no emulation for cos(float)", - "#error no emulation for cos(vec2)", - "#error no emulation for cos(vec3)", - "#error no emulation for cos(vec4)", - - "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", - "#error no emulation for distance(vec2, vec2)", - "#error no emulation for distance(vec3, vec3)", - "#error no emulation for distance(vec4, vec4)", - - "#define webgl_dot_emu(x, y) ((x) * (y))", - "#error no emulation for dot(vec2, vec2)", - "#error no emulation for dot(vec3, vec3)", - "#error no emulation for dot(vec4, vec4)", - - "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", - "#error no emulation for length(vec2)", - "#error no emulation for length(vec3)", - "#error no emulation for length(vec4)", - - "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", - "#error no emulation for normalize(vec2)", - "#error no emulation for normalize(vec3)", - "#error no emulation for normalize(vec4)", - - "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", - "#error no emulation for reflect(vec2, vec2)", - "#error no emulation for reflect(vec3, vec3)", - "#error no emulation for reflect(vec4, vec4)" -}; - -const char* kFunctionEmulationFragmentSource[] = { - "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }", - "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }", - "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }", - "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }", - - "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", - "#error no emulation for distance(vec2, vec2)", - "#error no emulation for distance(vec3, vec3)", - "#error no emulation for distance(vec4, vec4)", - - "#define webgl_dot_emu(x, y) ((x) * (y))", - "#error no emulation for dot(vec2, vec2)", - "#error no emulation for dot(vec3, vec3)", - "#error no emulation for dot(vec4, vec4)", - - "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", - "#error no emulation for length(vec2)", - "#error no emulation for length(vec3)", - "#error no emulation for length(vec4)", - - "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", - "#error no emulation for normalize(vec2)", - "#error no emulation for normalize(vec3)", - "#error no emulation for normalize(vec4)", - - "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", - "#error no emulation for reflect(vec2, vec2)", - "#error no emulation for reflect(vec3, vec3)", - "#error no emulation for reflect(vec4, vec4)" -}; - -const bool kFunctionEmulationVertexMask[] = { -#if defined(__APPLE__) - // Work around ATI driver bugs in Mac. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - true, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - true, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - true, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - true, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - true, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#else - // Work around D3D driver bug in Win. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - false, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - false, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - false, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - false, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - false, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#endif - false // TFunctionUnknown -}; - -const bool kFunctionEmulationFragmentMask[] = { -#if defined(__APPLE__) - // Work around ATI driver bugs in Mac. - true, // TFunctionCos1 - true, // TFunctionCos2 - true, // TFunctionCos3 - true, // TFunctionCos4 - true, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - true, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - true, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - true, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - true, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#else - // Work around D3D driver bug in Win. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - false, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - false, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - false, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - false, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - false, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#endif - false // TFunctionUnknown -}; - -class BuiltInFunctionEmulationMarker : public TIntermTraverser { -public: +class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser +{ + public: BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator) : mEmulator(emulator) { @@ -238,148 +54,119 @@ public: case EOpFaceForward: case EOpReflect: case EOpRefract: + case EOpOuterProduct: case EOpMul: break; default: return true; }; const TIntermSequence& sequence = *(node->getSequence()); - // Right now we only handle built-in functions with two parameters. - if (sequence.size() != 2) - return true; - TIntermTyped* param1 = sequence[0]->getAsTyped(); - TIntermTyped* param2 = sequence[1]->getAsTyped(); - if (!param1 || !param2) + bool needToEmulate = false; + // Right now we only handle built-in functions with two or three parameters. + if (sequence.size() == 2) + { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + if (!param1 || !param2) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType()); + } + else if (sequence.size() == 3) + { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + TIntermTyped* param3 = sequence[2]->getAsTyped(); + if (!param1 || !param2 || !param3) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType(), param3->getType()); + } + else + { return true; - bool needToEmulate = mEmulator.SetFunctionCalled( - node->getOp(), param1->getType(), param2->getType()); + } + if (needToEmulate) node->setUseEmulatedFunction(); } return true; } -private: + private: BuiltInFunctionEmulator& mEmulator; }; -} // anonymous namepsace +BuiltInFunctionEmulator::BuiltInFunctionEmulator() +{} -BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType) +void BuiltInFunctionEmulator::addEmulatedFunction( + TOperator op, const TType& param, + const char* emulatedFunctionDefinition) { - if (shaderType == GL_FRAGMENT_SHADER) { - mFunctionMask = kFunctionEmulationFragmentMask; - mFunctionSource = kFunctionEmulationFragmentSource; - } else { - mFunctionMask = kFunctionEmulationVertexMask; - mFunctionSource = kFunctionEmulationVertexSource; - } + mEmulatedFunctions[FunctionId(op, param)] = + std::string(emulatedFunctionDefinition); } -bool BuiltInFunctionEmulator::SetFunctionCalled( - TOperator op, const TType& param) +void BuiltInFunctionEmulator::addEmulatedFunction( + TOperator op, const TType& param1, const TType& param2, + const char* emulatedFunctionDefinition) { - TBuiltInFunction function = IdentifyFunction(op, param); - return SetFunctionCalled(function); + mEmulatedFunctions[FunctionId(op, param1, param2)] = + std::string(emulatedFunctionDefinition); } -bool BuiltInFunctionEmulator::SetFunctionCalled( - TOperator op, const TType& param1, const TType& param2) +void BuiltInFunctionEmulator::addEmulatedFunction( + TOperator op, const TType& param1, const TType& param2, const TType& param3, + const char* emulatedFunctionDefinition) { - TBuiltInFunction function = IdentifyFunction(op, param1, param2); - return SetFunctionCalled(function); + mEmulatedFunctions[FunctionId(op, param1, param2, param3)] = + std::string(emulatedFunctionDefinition); } -bool BuiltInFunctionEmulator::SetFunctionCalled( - BuiltInFunctionEmulator::TBuiltInFunction function) { - if (function == TFunctionUnknown || mFunctionMask[function] == false) - return false; - for (size_t i = 0; i < mFunctions.size(); ++i) { - if (mFunctions[i] == function) - return true; - } - mFunctions.push_back(function); - return true; +bool BuiltInFunctionEmulator::IsOutputEmpty() const +{ + return (mFunctions.size() == 0); } -void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition( - TInfoSinkBase& out, bool withPrecision) const +void BuiltInFunctionEmulator::OutputEmulatedFunctions( + TInfoSinkBase& out) const { - if (mFunctions.size() == 0) - return; - out << "// BEGIN: Generated code for built-in function emulation\n\n"; - if (withPrecision) { - out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" - << "#define webgl_emu_precision highp\n" - << "#else\n" - << "#define webgl_emu_precision mediump\n" - << "#endif\n\n"; - } else { - out << "#define webgl_emu_precision\n\n"; - } for (size_t i = 0; i < mFunctions.size(); ++i) { - out << mFunctionSource[mFunctions[i]] << "\n\n"; + out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n"; } - out << "// END: Generated code for built-in function emulation\n\n"; } -BuiltInFunctionEmulator::TBuiltInFunction -BuiltInFunctionEmulator::IdentifyFunction( +bool BuiltInFunctionEmulator::SetFunctionCalled( TOperator op, const TType& param) { - if (param.getNominalSize() > 4 || param.getSecondarySize() > 4) - return TFunctionUnknown; - unsigned int function = TFunctionUnknown; - switch (op) { - case EOpCos: - function = TFunctionCos1; - break; - case EOpLength: - function = TFunctionLength1; - break; - case EOpNormalize: - function = TFunctionNormalize1; - break; - default: - break; - } - if (function == TFunctionUnknown) - return TFunctionUnknown; - if (param.isVector()) - function += param.getNominalSize() - 1; - return static_cast<TBuiltInFunction>(function); + return SetFunctionCalled(FunctionId(op, param)); } -BuiltInFunctionEmulator::TBuiltInFunction -BuiltInFunctionEmulator::IdentifyFunction( +bool BuiltInFunctionEmulator::SetFunctionCalled( TOperator op, const TType& param1, const TType& param2) { - // Right now for all the emulated functions with two parameters, the two - // parameters have the same type. - if (param1.getNominalSize() != param2.getNominalSize() || - param1.getSecondarySize() != param2.getSecondarySize() || - param1.getNominalSize() > 4 || param1.getSecondarySize() > 4) - return TFunctionUnknown; + return SetFunctionCalled(FunctionId(op, param1, param2)); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3) +{ + return SetFunctionCalled(FunctionId(op, param1, param2, param3)); +} - unsigned int function = TFunctionUnknown; - switch (op) { - case EOpDistance: - function = TFunctionDistance1_1; - break; - case EOpDot: - function = TFunctionDot1_1; - break; - case EOpReflect: - function = TFunctionReflect1_1; - break; - default: - break; +bool BuiltInFunctionEmulator::SetFunctionCalled( + const FunctionId& functionId) { + if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end()) + { + for (size_t i = 0; i < mFunctions.size(); ++i) { + if (mFunctions[i] == functionId) + return true; + } + mFunctions.push_back(functionId); + return true; } - if (function == TFunctionUnknown) - return TFunctionUnknown; - if (param1.isVector()) - function += param1.getNominalSize() - 1; - return static_cast<TBuiltInFunction>(function); + return false; } void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( @@ -387,6 +174,9 @@ void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( { ASSERT(root); + if (mEmulatedFunctions.empty()) + return; + BuiltInFunctionEmulationMarker marker(*this); root->traverse(&marker); } @@ -404,3 +194,52 @@ TString BuiltInFunctionEmulator::GetEmulatedFunctionName( return "webgl_" + name.substr(0, name.length() - 1) + "_emu("; } +BuiltInFunctionEmulator::FunctionId::FunctionId + (TOperator op, const TType& param) + : mOp(op), + mParam1(param), + mParam2(EbtVoid), + mParam3(EbtVoid) +{ +} + +BuiltInFunctionEmulator::FunctionId::FunctionId + (TOperator op, const TType& param1, const TType& param2) + : mOp(op), + mParam1(param1), + mParam2(param2), + mParam3(EbtVoid) +{ +} + +BuiltInFunctionEmulator::FunctionId::FunctionId + (TOperator op, const TType& param1, const TType& param2, const TType& param3) + : mOp(op), + mParam1(param1), + mParam2(param2), + mParam3(param3) +{ +} + +bool BuiltInFunctionEmulator::FunctionId::operator== + (const BuiltInFunctionEmulator::FunctionId& other) const +{ + return (mOp == other.mOp && + mParam1 == other.mParam1 && + mParam2 == other.mParam2 && + mParam3 == other.mParam3); +} + +bool BuiltInFunctionEmulator::FunctionId::operator< + (const BuiltInFunctionEmulator::FunctionId& other) const +{ + if (mOp != other.mOp) + return mOp < other.mOp; + if (mParam1 != other.mParam1) + return mParam1 < other.mParam1; + if (mParam2 != other.mParam2) + return mParam2 < other.mParam2; + if (mParam3 != other.mParam3) + return mParam3 < other.mParam3; + return false; // all fields are equal +} diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index c6bf77c386..df556985e1 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ -#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ +#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" @@ -13,23 +13,13 @@ // // This class decides which built-in functions need to be replaced with the // emulated ones. -// It's only a workaround for OpenGL driver bugs, and isn't needed in general. +// It can be used to work around driver bugs or implement functions that are +// not natively implemented on a specific platform. // -class BuiltInFunctionEmulator { -public: - BuiltInFunctionEmulator(sh::GLenum shaderType); - // Records that a function is called by the shader and might needs to be - // emulated. If the function's group is not in mFunctionGroupFilter, this - // becomes an no-op. - // Returns true if the function call needs to be replaced with an emulated - // one. - bool SetFunctionCalled(TOperator op, const TType& param); - bool SetFunctionCalled( - TOperator op, const TType& param1, const TType& param2); - - // Output function emulation definition. This should be before any other - // shader source. - void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; +class BuiltInFunctionEmulator +{ + public: + BuiltInFunctionEmulator(); void MarkBuiltInFunctionsForEmulation(TIntermNode* root); @@ -38,54 +28,52 @@ public: // "name(" becomes "webgl_name_emu(". static TString GetEmulatedFunctionName(const TString& name); -private: - // - // Built-in functions. - // - enum TBuiltInFunction { - TFunctionCos1 = 0, // float cos(float); - TFunctionCos2, // vec2 cos(vec2); - TFunctionCos3, // vec3 cos(vec3); - TFunctionCos4, // vec4 cos(vec4); - - TFunctionDistance1_1, // float distance(float, float); - TFunctionDistance2_2, // vec2 distance(vec2, vec2); - TFunctionDistance3_3, // vec3 distance(vec3, vec3); - TFunctionDistance4_4, // vec4 distance(vec4, vec4); - - TFunctionDot1_1, // float dot(float, float); - TFunctionDot2_2, // vec2 dot(vec2, vec2); - TFunctionDot3_3, // vec3 dot(vec3, vec3); - TFunctionDot4_4, // vec4 dot(vec4, vec4); - - TFunctionLength1, // float length(float); - TFunctionLength2, // float length(vec2); - TFunctionLength3, // float length(vec3); - TFunctionLength4, // float length(vec4); - - TFunctionNormalize1, // float normalize(float); - TFunctionNormalize2, // vec2 normalize(vec2); - TFunctionNormalize3, // vec3 normalize(vec3); - TFunctionNormalize4, // vec4 normalize(vec4); - - TFunctionReflect1_1, // float reflect(float, float); - TFunctionReflect2_2, // vec2 reflect(vec2, vec2); - TFunctionReflect3_3, // vec3 reflect(vec3, vec3); - TFunctionReflect4_4, // vec4 reflect(vec4, vec4); - - TFunctionUnknown - }; + bool IsOutputEmpty() const; + + // Output function emulation definition. This should be before any other + // shader source. + void OutputEmulatedFunctions(TInfoSinkBase& out) const; + + // Add functions that need to be emulated. + void addEmulatedFunction(TOperator op, const TType& param, const char* emulatedFunctionDefinition); + void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const char* emulatedFunctionDefinition); + void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const TType& param3, const char* emulatedFunctionDefinition); - TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); - TBuiltInFunction IdentifyFunction( + private: + class BuiltInFunctionEmulationMarker; + + // Records that a function is called by the shader and might need to be + // emulated. If the function is not in mEmulatedFunctions, this becomes a + // no-op. Returns true if the function call needs to be replaced with an + // emulated one. + bool SetFunctionCalled(TOperator op, const TType& param); + bool SetFunctionCalled( TOperator op, const TType& param1, const TType& param2); + bool SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3); + + class FunctionId { + public: + FunctionId(TOperator op, const TType& param); + FunctionId(TOperator op, const TType& param1, const TType& param2); + FunctionId(TOperator op, const TType& param1, const TType& param2, const TType& param3); + + bool operator==(const FunctionId& other) const; + bool operator<(const FunctionId& other) const; + private: + TOperator mOp; + TType mParam1; + TType mParam2; + TType mParam3; + }; - bool SetFunctionCalled(TBuiltInFunction function); + bool SetFunctionCalled(const FunctionId& functionId); - std::vector<TBuiltInFunction> mFunctions; + // Map from function id to emulated function definition + std::map<FunctionId, std::string> mEmulatedFunctions; - const bool* mFunctionMask; // a boolean flag for each function. - const char** mFunctionSource; + // Called function ids + std::vector<FunctionId> mFunctions; }; -#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp new file mode 100644 index 0000000000..9de99831ad --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2011 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 "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/SymbolTable.h" + +void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType) +{ + // we use macros here instead of function definitions to work around more GLSL + // compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are + // problematic because if the argument has side-effects they will be repeatedly + // evaluated. This is unlikely to show up in real shaders, but is something to + // consider. + + TType float1(EbtFloat); + TType float2(EbtFloat, 2); + TType float3(EbtFloat, 3); + TType float4(EbtFloat, 4); + + if (shaderType == GL_FRAGMENT_SHADER) + { + emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }"); + } + emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))"); + emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))"); + emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))"); + emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))"); + emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))"); +} diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h new file mode 100644 index 0000000000..5707a4b35a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h @@ -0,0 +1,19 @@ +// +// Copyright (c) 2011 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 COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ + +#include "GLSLANG/ShaderLang.h" + +class BuiltInFunctionEmulator; + +// +// This is only a workaround for OpenGL driver bugs, and isn't needed in general. +// +void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType); + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp new file mode 100644 index 0000000000..7123a0d5c0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp @@ -0,0 +1,410 @@ +// +// 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 "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" +#include "compiler/translator/SymbolTable.h" + +void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) +{ + TType float1(EbtFloat); + TType float2(EbtFloat, 2); + TType float3(EbtFloat, 3); + TType float4(EbtFloat, 4); + + emu->addEmulatedFunction(EOpMod, float1, float1, + "float webgl_mod_emu(float x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float2, float2, + "float2 webgl_mod_emu(float2 x, float2 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float2, float1, + "float2 webgl_mod_emu(float2 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float3, float3, + "float3 webgl_mod_emu(float3 x, float3 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float3, float1, + "float3 webgl_mod_emu(float3 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float4, float4, + "float4 webgl_mod_emu(float4 x, float4 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float4, float1, + "float4 webgl_mod_emu(float4 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + + emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1, + "float webgl_faceforward_emu(float N, float I, float Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2, + "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3, + "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4, + "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + + emu->addEmulatedFunction(EOpAtan, float1, float1, + "float webgl_atan_emu(float y, float x)\n" + "{\n" + " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN + " return atan2(y, x);\n" + "}\n"); + emu->addEmulatedFunction(EOpAtan, float2, float2, + "float2 webgl_atan_emu(float2 y, float2 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtan, float3, float3, + "float3 webgl_atan_emu(float3 y, float3 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtan, float4, float4, + "float4 webgl_atan_emu(float4 y, float4 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" + " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" + "}\n"); + + emu->addEmulatedFunction(EOpAsinh, float1, + "float webgl_asinh_emu(in float x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAsinh, float2, + "float2 webgl_asinh_emu(in float2 x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAsinh, float3, + "float3 webgl_asinh_emu(in float3 x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAsinh, float4, + "float4 webgl_asinh_emu(in float4 x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + + emu->addEmulatedFunction(EOpAcosh, float1, + "float webgl_acosh_emu(in float x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAcosh, float2, + "float2 webgl_acosh_emu(in float2 x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAcosh, float3, + "float3 webgl_acosh_emu(in float3 x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAcosh, float4, + "float4 webgl_acosh_emu(in float4 x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + + emu->addEmulatedFunction(EOpAtanh, float1, + "float webgl_atanh_emu(in float x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtanh, float2, + "float2 webgl_atanh_emu(in float2 x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtanh, float3, + "float3 webgl_atanh_emu(in float3 x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtanh, float4, + "float4 webgl_atanh_emu(in float4 x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + + emu->addEmulatedFunction(EOpRoundEven, float1, + "float webgl_roundEven_emu(in float x) {\n" + " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" + "}\n"); + emu->addEmulatedFunction(EOpRoundEven, float2, + "float2 webgl_roundEven_emu(in float2 x) {\n" + " float2 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " return v;\n" + "}\n"); + emu->addEmulatedFunction(EOpRoundEven, float3, + "float3 webgl_roundEven_emu(in float3 x) {\n" + " float3 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" + " return v;\n" + "}\n"); + emu->addEmulatedFunction(EOpRoundEven, float4, + "float4 webgl_roundEven_emu(in float4 x) {\n" + " float4 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" + " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" + " return v;\n" + "}\n"); + + emu->addEmulatedFunction(EOpPackSnorm2x16, float2, + "int webgl_toSnorm(in float x) {\n" + " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" + "}\n" + "\n" + "uint webgl_packSnorm2x16_emu(in float2 v) {\n" + " int x = webgl_toSnorm(v.x);\n" + " int y = webgl_toSnorm(v.y);\n" + " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" + "}\n"); + emu->addEmulatedFunction(EOpPackUnorm2x16, float2, + "uint webgl_toUnorm(in float x) {\n" + " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" + "}\n" + "\n" + "uint webgl_packUnorm2x16_emu(in float2 v) {\n" + " uint x = webgl_toUnorm(v.x);\n" + " uint y = webgl_toUnorm(v.y);\n" + " return (y << 16) | x;\n" + "}\n"); + emu->addEmulatedFunction(EOpPackHalf2x16, float2, + "uint webgl_packHalf2x16_emu(in float2 v) {\n" + " uint x = f32tof16(v.x);\n" + " uint y = f32tof16(v.y);\n" + " return (y << 16) | x;\n" + "}\n"); + + TType uint1(EbtUInt); + + emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, + "float webgl_fromSnorm(in uint x) {\n" + " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" + " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" + "}\n" + "\n" + "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n" + " uint y = (u >> 16);\n" + " uint x = u;\n" + " return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n" + "}\n"); + emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, + "float webgl_fromUnorm(in uint x) {\n" + " return float(x) / 65535.0;\n" + "}\n" + "\n" + "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xffffu;\n" + " return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n" + "}\n"); + emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, + "float2 webgl_unpackHalf2x16_emu(in uint u) {\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xffffu;\n" + " return float2(f16tof32(x), f16tof32(y));\n" + "}\n"); + + // The matrix resulting from outer product needs to be transposed + // (matrices are stored as transposed to simplify element access in HLSL). + // So the function should return transpose(c * r) where c is a column vector + // and r is a row vector. This can be simplified by using the following + // formula: + // transpose(c * r) = transpose(r) * transpose(c) + // transpose(r) and transpose(c) are in a sense free, since to get the + // transpose of r, we simply can build a column matrix out of the original + // vector instead of a row matrix. + emu->addEmulatedFunction(EOpOuterProduct, float2, float2, + "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n" + " return mul(float2x1(r), float1x2(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float3, float3, + "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n" + " return mul(float3x1(r), float1x3(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float4, float4, + "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n" + " return mul(float4x1(r), float1x4(c));\n" + "}\n"); + + emu->addEmulatedFunction(EOpOuterProduct, float3, float2, + "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n" + " return mul(float2x1(r), float1x3(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float2, float3, + "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n" + " return mul(float3x1(r), float1x2(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float4, float2, + "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n" + " return mul(float2x1(r), float1x4(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float2, float4, + "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n" + " return mul(float4x1(r), float1x2(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float4, float3, + "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n" + " return mul(float3x1(r), float1x4(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float3, float4, + "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n" + " return mul(float4x1(r), float1x3(c));\n" + "}\n"); + + TType mat2(EbtFloat, 2, 2); + TType mat3(EbtFloat, 3, 3); + TType mat4(EbtFloat, 4, 4); + + // Remember here that the parameter matrix is actually the transpose + // of the matrix that we're trying to invert, and the resulting matrix + // should also be the transpose of the inverse. + + // When accessing the parameter matrix with m[a][b] it can be thought of so + // that a is the column and b is the row of the matrix that we're inverting. + + // We calculate the inverse as the adjugate matrix divided by the + // determinant of the matrix being inverted. However, as the result needs + // to be transposed, we actually use of the transpose of the adjugate matrix + // which happens to be the cofactor matrix. That's stored in "cof". + + // We don't need to care about divide-by-zero since results are undefined + // for singular or poorly-conditioned matrices. + + emu->addEmulatedFunction(EOpInverse, mat2, + "float2x2 webgl_inverse_emu(in float2x2 m) {\n" + " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" + " return cof / determinant(transpose(m));\n" + "}\n"); + + // cofAB is the cofactor for column A and row B. + + emu->addEmulatedFunction(EOpInverse, mat3, + "float3x3 webgl_inverse_emu(in float3x3 m) {\n" + " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" + " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n" + " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n" + " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n" + " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n" + " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n" + " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n" + " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n" + " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n" + " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" + " return cof / determinant(transpose(m));\n" + "}\n"); + + emu->addEmulatedFunction(EOpInverse, mat4, + "float4x4 webgl_inverse_emu(in float4x4 m) {\n" + " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]" + " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n" + " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]" + " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n" + " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]" + " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n" + " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]" + " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n" + " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]" + " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n" + " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]" + " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n" + " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]" + " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n" + " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]" + " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n" + " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]" + " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n" + " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]" + " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n" + " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]" + " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n" + " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]" + " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n" + " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]" + " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n" + " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]" + " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n" + " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]" + " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n" + " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]" + " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n" + " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31," + " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n" + " return cof / determinant(transpose(m));\n" + "}\n"); +} diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h new file mode 100644 index 0000000000..4c45a93dc4 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h @@ -0,0 +1,16 @@ +// +// 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 COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ + +#include "GLSLANG/ShaderLang.h" + +class BuiltInFunctionEmulator; + +void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu); + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp index 71056f4297..5e3eb1cc05 100644 --- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp +++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp @@ -6,7 +6,9 @@ #include "compiler/translator/TranslatorESSL.h" #include "compiler/translator/TranslatorGLSL.h" +#ifdef ANGLE_ENABLE_HLSL #include "compiler/translator/TranslatorHLSL.h" +#endif // ANGLE_ENABLE_HLSL // // This function must be provided to create the actual @@ -17,14 +19,22 @@ TCompiler* ConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) { switch (output) { - case SH_ESSL_OUTPUT: + case SH_ESSL_OUTPUT: return new TranslatorESSL(type, spec); - case SH_GLSL_OUTPUT: - return new TranslatorGLSL(type, spec); - case SH_HLSL9_OUTPUT: - case SH_HLSL11_OUTPUT: + case SH_GLSL_CORE_OUTPUT: + case SH_GLSL_COMPATIBILITY_OUTPUT: + return new TranslatorGLSL(type, spec, output); + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: +#ifdef ANGLE_ENABLE_HLSL return new TranslatorHLSL(type, spec, output); - default: +#else + // This compiler is not supported in this + // configuration. Return NULL per the ShConstructCompiler API. + return NULL; +#endif // ANGLE_ENABLE_HLSL + default: + // Unknown format. Return NULL per the ShConstructCompiler API. return NULL; } } diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h index 1e4503e340..ac1aef0f4c 100644 --- a/src/3rdparty/angle/src/compiler/translator/Common.h +++ b/src/3rdparty/angle/src/compiler/translator/Common.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _COMMON_INCLUDED_ -#define _COMMON_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_COMMON_H_ +#define COMPILER_TRANSLATOR_COMMON_H_ #include <map> #include <sstream> @@ -89,4 +89,4 @@ inline TString str(T i) return buffer; } -#endif // _COMMON_INCLUDED_ +#endif // COMPILER_TRANSLATOR_COMMON_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 5c62a64d10..534861ca70 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -4,7 +4,6 @@ // found in the LICENSE file. // -#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/DetectCallDepth.h" #include "compiler/translator/ForLoopUnroll.h" @@ -126,7 +125,8 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) maxCallStackDepth(0), fragmentPrecisionHigh(false), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), - builtInFunctionEmulator(type) + builtInFunctionEmulator(), + mSourcePath(NULL) { } @@ -159,33 +159,41 @@ bool TCompiler::Init(const ShBuiltInResources& resources) return true; } -bool TCompiler::compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions) +TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[], + size_t numStrings, int compileOptions) +{ + return compileTreeImpl(shaderStrings, numStrings, compileOptions); +} + +TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[], + size_t numStrings, int compileOptions) { - TScopedPoolAllocator scopedAlloc(&allocator); clearResults(); - if (numStrings == 0) - return true; + ASSERT(numStrings > 0); + ASSERT(GetGlobalPoolAllocator()); + + // Reset the extension behavior for each compilation unit. + ResetExtensionBehavior(extensionBehavior); // If compiling for WebGL, validate loop and indexing as well. if (IsWebGLBasedSpec(shaderSpec)) compileOptions |= SH_VALIDATE_LOOP_INDEXING; // First string is path of source file if flag is set. The actual source follows. - const char* sourcePath = NULL; size_t firstSource = 0; if (compileOptions & SH_SOURCE_PATH) { - sourcePath = shaderStrings[0]; + mSourcePath = shaderStrings[0]; ++firstSource; } + bool debugShaderPrecision = getResources().WEBGL_debug_shader_precision == 1; TIntermediate intermediate(infoSink); TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec, compileOptions, true, - sourcePath, infoSink); + infoSink, debugShaderPrecision); + parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; SetGlobalParseContext(&parseContext); @@ -206,6 +214,8 @@ bool TCompiler::compile(const char* const shaderStrings[], success = false; } + TIntermNode *root = NULL; + if (success) { mPragma = parseContext.pragma(); @@ -214,7 +224,7 @@ bool TCompiler::compile(const char* const shaderStrings[], symbolTable.setGlobalInvariant(); } - TIntermNode* root = parseContext.treeRoot; + root = parseContext.treeRoot; success = intermediate.postProcess(root); // Disallow expressions deemed too complex. @@ -255,8 +265,11 @@ bool TCompiler::compile(const char* const shaderStrings[], } // Built-in function emulation needs to happen after validateLimitations pass. - if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) + if (success) + { + initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions); builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root); + } // Clamping uniform array bounds needs to happen after validateLimitations pass. if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) @@ -301,18 +314,37 @@ bool TCompiler::compile(const char* const shaderStrings[], RegenerateStructNames gen(symbolTable, shaderVersion); root->traverse(&gen); } - - if (success && (compileOptions & SH_INTERMEDIATE_TREE)) - intermediate.outputTree(root); - - if (success && (compileOptions & SH_OBJECT_CODE)) - translate(root); } - // Cleanup memory. - intermediate.remove(parseContext.treeRoot); SetGlobalParseContext(NULL); - return success; + if (success) + return root; + + return NULL; +} + +bool TCompiler::compile(const char* const shaderStrings[], + size_t numStrings, int compileOptions) +{ + if (numStrings == 0) + return true; + + TScopedPoolAllocator scopedAlloc(&allocator); + TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); + + if (root) + { + if (compileOptions & SH_INTERMEDIATE_TREE) + TIntermediate::outputTree(root, infoSink.info); + + if (compileOptions & SH_OBJECT_CODE) + translate(root, compileOptions); + + // The IntermNode tree doesn't need to be deleted here, since the + // memory will be freed in a big chunk by the PoolAllocator. + return true; + } + return false; } bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) @@ -390,11 +422,15 @@ void TCompiler::setResourceString() << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth << ":EXT_frag_depth:" << compileResources.EXT_frag_depth << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod + << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch + << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch + << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset - << ":NV_draw_buffers:" << compileResources.NV_draw_buffers; + << ":NV_draw_buffers:" << compileResources.NV_draw_buffers + << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision; builtInResourcesString = strstream.str(); } @@ -416,27 +452,29 @@ void TCompiler::clearResults() builtInFunctionEmulator.Cleanup(); nameMap.clear(); + + mSourcePath = NULL; } -bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) +bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth) { - DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); - root->traverse(&detect); + DetectCallDepth detect(inputInfoSink, limitCallStackDepth, maxCallStackDepth); + inputRoot->traverse(&detect); switch (detect.detectCallDepth()) { case DetectCallDepth::kErrorNone: return true; case DetectCallDepth::kErrorMissingMain: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Missing main()"; + inputInfoSink.info.prefix(EPrefixError); + inputInfoSink.info << "Missing main()"; return false; case DetectCallDepth::kErrorRecursion: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function recursion detected"; + inputInfoSink.info.prefix(EPrefixError); + inputInfoSink.info << "Function recursion detected"; return false; case DetectCallDepth::kErrorMaxDepthExceeded: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function call stack too deep"; + inputInfoSink.info.prefix(EPrefixError); + inputInfoSink.info << "Function call stack too deep"; return false; default: UNREACHABLE(); @@ -594,6 +632,11 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const return extensionBehavior; } +const char *TCompiler::getSourcePath() const +{ + return mSourcePath; +} + const ShBuiltInResources& TCompiler::getResources() const { return compileResources; diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index b6c9d13ed0..bcdb0d4c9d 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _SHHANDLE_INCLUDED_ -#define _SHHANDLE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_COMPILER_H_ +#define COMPILER_TRANSLATOR_COMPILER_H_ // // Machine independent part of the compiler private objects @@ -25,7 +25,9 @@ class TCompiler; class TDependencyGraph; +#ifdef ANGLE_ENABLE_HLSL class TranslatorHLSL; +#endif // ANGLE_ENABLE_HLSL // // Helper function to identify specs that are based on the WebGL spec, @@ -41,7 +43,9 @@ public: TShHandleBase(); virtual ~TShHandleBase(); virtual TCompiler* getAsCompiler() { return 0; } +#ifdef ANGLE_ENABLE_HLSL virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } +#endif // ANGLE_ENABLE_HLSL protected: // Memory allocator. Allocates and tracks memory required by the compiler. @@ -61,9 +65,15 @@ class TCompiler : public TShHandleBase virtual TCompiler* getAsCompiler() { return this; } bool Init(const ShBuiltInResources& resources); + + // compileTreeForTesting should be used only when tests require access to + // the AST. Users of this function need to manually manage the global pool + // allocator. Returns NULL whenever there are compilation errors. + TIntermNode *compileTreeForTesting(const char* const shaderStrings[], + size_t numStrings, int compileOptions); + bool compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions); + size_t numStrings, int compileOptions); // Get results of the last compilation. int getShaderVersion() const { return shaderVersion; } @@ -104,8 +114,10 @@ class TCompiler : public TShHandleBase bool validateLimitations(TIntermNode* root); // Collect info for all attribs, uniforms, varyings. void collectVariables(TIntermNode* root); + // Add emulated functions to the built-in function emulator. + virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {}; // Translate to object code. - virtual void translate(TIntermNode* root) = 0; + virtual void translate(TIntermNode *root, int compileOptions) = 0; // Returns true if, after applying the packing rules in the GLSL 1.017 spec // Appendix A, section 7, the shader does not use too many uniforms. bool enforcePackingRestrictions(); @@ -130,6 +142,7 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; + const char *getSourcePath() const; const TPragma& getPragma() const { return mPragma; } void writePragma(); @@ -145,6 +158,9 @@ class TCompiler : public TShHandleBase std::vector<sh::InterfaceBlock> interfaceBlocks; private: + TIntermNode *compileTreeImpl(const char* const shaderStrings[], + size_t numStrings, int compileOptions); + sh::GLenum shaderType; ShShaderSpec shaderSpec; ShShaderOutput outputType; @@ -170,6 +186,7 @@ class TCompiler : public TShHandleBase // Results of compilation. int shaderVersion; TInfoSink infoSink; // Output sink. + const char *mSourcePath; // Path of source file or NULL // name hashing. ShHashFunction64 hashFunction; @@ -191,4 +208,4 @@ TCompiler* ConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); void DeleteCompiler(TCompiler*); -#endif // _SHHANDLE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_COMPILER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h index 5e86c64805..31ff2ccfa7 100644 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h +++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _CONSTANT_UNION_INCLUDED_ -#define _CONSTANT_UNION_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_ +#define COMPILER_TRANSLATOR_CONSTANTUNION_H_ #include <assert.h> @@ -254,7 +254,10 @@ public: ConstantUnion operator<<(const ConstantUnion& constant) const { ConstantUnion returnValue; - assert(type == constant.type); + // The signedness of the second parameter might be different, but we + // don't care, since the result is undefined if the second parameter is + // negative, and aliasing should not be a problem with unions. + assert(constant.type == EbtInt || constant.type == EbtUInt); switch (type) { case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; @@ -267,7 +270,7 @@ public: ConstantUnion operator&(const ConstantUnion& constant) const { ConstantUnion returnValue; - assert(type == constant.type); + assert(constant.type == EbtInt || constant.type == EbtUInt); switch (type) { case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; @@ -340,4 +343,4 @@ private: TBasicType type; }; -#endif // _CONSTANT_UNION_INCLUDED_ +#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp index bfc1d5852f..0dc5d22709 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp @@ -33,7 +33,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe ASSERT(visit == PreVisit); ASSERT(detectCallDepth); - int maxDepth = depth; + int retMaxDepth = depth; visit = InVisit; for (size_t i = 0; i < callees.size(); ++i) { switch (callees[i]->visit) { @@ -52,7 +52,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName(); return callDepth; } - maxDepth = std::max(callDepth, maxDepth); + retMaxDepth = std::max(callDepth, retMaxDepth); break; } default: @@ -61,7 +61,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe } } visit = PostVisit; - return maxDepth; + return retMaxDepth; } void DetectCallDepth::FunctionNode::reset() diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index 86810650dc..8dd1391e67 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_DETECT_RECURSION_H_ -#define COMPILER_DETECT_RECURSION_H_ +#ifndef COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_ +#define COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_ #include <limits.h> #include "compiler/translator/IntermNode.h" @@ -75,4 +75,4 @@ private: void operator=(const DetectCallDepth&); }; -#endif // COMPILER_DETECT_RECURSION_H_ +#endif // COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 67e37be398..623be13533 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -8,8 +8,8 @@ // gradients of functions with discontinuities. // -#ifndef COMPILER_DETECTDISCONTINUITY_H_ -#define COMPILER_DETECTDISCONTINUITY_H_ +#ifndef COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_ +#define COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_ #include "compiler/translator/IntermNode.h" @@ -68,4 +68,4 @@ bool containsGradientOperation(TIntermNode *node); } -#endif // COMPILER_DETECTDISCONTINUITY_H_ +#endif // COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h index 664da7803b..078bc97772 100644 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h @@ -4,14 +4,15 @@ // found in the LICENSE file. // -#ifndef COMPILER_DIAGNOSTICS_H_ -#define COMPILER_DIAGNOSTICS_H_ +#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_ +#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_ +#include "common/angleutils.h" #include "compiler/preprocessor/DiagnosticsBase.h" class TInfoSink; -class TDiagnostics : public pp::Diagnostics +class TDiagnostics : public pp::Diagnostics, angle::NonCopyable { public: TDiagnostics(TInfoSink& infoSink); @@ -41,4 +42,4 @@ class TDiagnostics : public pp::Diagnostics int mNumWarnings; }; -#endif // COMPILER_DIAGNOSTICS_H_ +#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp index f67a03aa93..936c00a56c 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -27,10 +27,12 @@ static TBehavior getBehavior(const std::string& str) TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, TDiagnostics& diagnostics, - int& shaderVersion) + int& shaderVersion, + bool debugShaderPrecisionSupported) : mExtensionBehavior(extBehavior), mDiagnostics(diagnostics), - mShaderVersion(shaderVersion) + mShaderVersion(shaderVersion), + mDebugShaderPrecisionSupported(debugShaderPrecisionSupported) { } @@ -65,6 +67,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, { const char kOptimize[] = "optimize"; const char kDebug[] = "debug"; + const char kDebugShaderPrecision[] = "webgl_debug_shader_precision"; const char kOn[] = "on"; const char kOff[] = "off"; @@ -81,6 +84,12 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, else if (value == kOff) mPragma.debug = false; else invalidValue = true; } + else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported) + { + if (value == kOn) mPragma.debugShaderPrecision = true; + else if (value == kOff) mPragma.debugShaderPrecision = false; + else invalidValue = true; + } else { mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h index 0433c3bf89..2a81ee5707 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -4,21 +4,23 @@ // found in the LICENSE file. // -#ifndef COMPILER_DIRECTIVE_HANDLER_H_ -#define COMPILER_DIRECTIVE_HANDLER_H_ +#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ +#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ +#include "common/angleutils.h" #include "compiler/translator/ExtensionBehavior.h" #include "compiler/translator/Pragma.h" #include "compiler/preprocessor/DirectiveHandlerBase.h" class TDiagnostics; -class TDirectiveHandler : public pp::DirectiveHandler +class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable { public: TDirectiveHandler(TExtensionBehavior& extBehavior, TDiagnostics& diagnostics, - int& shaderVersion); + int& shaderVersion, + bool debugShaderPrecisionSupported); virtual ~TDirectiveHandler(); const TPragma& pragma() const { return mPragma; } @@ -44,6 +46,7 @@ class TDirectiveHandler : public pp::DirectiveHandler TExtensionBehavior& mExtensionBehavior; TDiagnostics& mDiagnostics; int& mShaderVersion; + bool mDebugShaderPrecisionSupported; }; -#endif // COMPILER_DIRECTIVE_HANDLER_H_ +#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp new file mode 100644 index 0000000000..697e042954 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp @@ -0,0 +1,528 @@ +// +// Copyright (c) 2002-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 "compiler/translator/EmulatePrecision.h" + +namespace +{ + +static void writeVectorPrecisionEmulationHelpers( + TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size) +{ + std::stringstream vecTypeStrStr; + if (outputLanguage == SH_ESSL_OUTPUT) + vecTypeStrStr << "highp "; + vecTypeStrStr << "vec" << size; + std::string vecType = vecTypeStrStr.str(); + + sink << + vecType << " angle_frm(in " << vecType << " v) {\n" + " v = clamp(v, -65504.0, 65504.0);\n" + " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n" + " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n" + " v = v * exp2(-exponent);\n" + " v = sign(v) * floor(abs(v));\n" + " return v * exp2(exponent) * vec" << size << "(isNonZero);\n" + "}\n"; + + sink << + vecType << " angle_frl(in " << vecType << " v) {\n" + " v = clamp(v, -2.0, 2.0);\n" + " v = v * 256.0;\n" + " v = sign(v) * floor(abs(v));\n" + " return v * 0.00390625;\n" + "}\n"; +} + +static void writeMatrixPrecisionEmulationHelper( + TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName) +{ + std::stringstream matTypeStrStr; + if (outputLanguage == SH_ESSL_OUTPUT) + matTypeStrStr << "highp "; + matTypeStrStr << "mat" << size; + std::string matType = matTypeStrStr.str(); + + sink << matType << " " << functionName << "(in " << matType << " m) {\n" + " " << matType << " rounded;\n"; + + for (unsigned int i = 0; i < size; ++i) + { + sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n"; + } + + sink << " return rounded;\n" + "}\n"; +} + +static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage) +{ + // Write the angle_frm functions that round floating point numbers to + // half precision, and angle_frl functions that round them to minimum lowp + // precision. + + // Unoptimized version of angle_frm for single floats: + // + // int webgl_maxNormalExponent(in int exponentBits) { + // int possibleExponents = int(exp2(float(exponentBits))); + // int exponentBias = possibleExponents / 2 - 1; + // int allExponentBitsOne = possibleExponents - 1; + // return (allExponentBitsOne - 1) - exponentBias; + // } + // + // float angle_frm(in float x) { + // int mantissaBits = 10; + // int exponentBits = 5; + // float possibleMantissas = exp2(float(mantissaBits)); + // float mantissaMax = 2.0 - 1.0 / possibleMantissas; + // int maxNE = webgl_maxNormalExponent(exponentBits); + // float max = exp2(float(maxNE)) * mantissaMax; + // if (x > max) { + // return max; + // } + // if (x < -max) { + // return -max; + // } + // float exponent = floor(log2(abs(x))); + // if (abs(x) == 0.0 || exponent < -float(maxNE)) { + // return 0.0 * sign(x) + // } + // x = x * exp2(-(exponent - float(mantissaBits))); + // x = sign(x) * floor(abs(x)); + // return x * exp2(exponent - float(mantissaBits)); + // } + + // All numbers with a magnitude less than 2^-15 are subnormal, and are + // flushed to zero. + + // Note the constant numbers below: + // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times + // 2^15, the maximum normal exponent. + // b) 10.0 is the number of mantissa bits. + // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number + // of mantissa bits. + // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can + // only affect the result of log2 on x where abs(x) < 1e-22. Since these + // numbers will be flushed to zero either way (2^-15 is the smallest + // normal positive number), this does not introduce any error. + + std::string floatType = "float"; + if (outputLanguage == SH_ESSL_OUTPUT) + floatType = "highp float"; + + sink << + floatType << " angle_frm(in " << floatType << " x) {\n" + " x = clamp(x, -65504.0, 65504.0);\n" + " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n" + " bool isNonZero = (exponent >= -25.0);\n" + " x = x * exp2(-exponent);\n" + " x = sign(x) * floor(abs(x));\n" + " return x * exp2(exponent) * float(isNonZero);\n" + "}\n"; + + sink << + floatType << " angle_frl(in " << floatType << " x) {\n" + " x = clamp(x, -2.0, 2.0);\n" + " x = x * 256.0;\n" + " x = sign(x) * floor(abs(x));\n" + " return x * 0.00390625;\n" + "}\n"; + + writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2); + writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3); + writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4); + for (unsigned int size = 2; size <= 4; ++size) + { + writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm"); + writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl"); + } +} + +static void writeCompoundAssignmentPrecisionEmulation( + TInfoSinkBase& sink, ShShaderOutput outputLanguage, + const char *lType, const char *rType, const char *opStr, const char *opNameStr) +{ + std::string lTypeStr = lType; + std::string rTypeStr = rType; + if (outputLanguage == SH_ESSL_OUTPUT) + { + std::stringstream lTypeStrStr; + lTypeStrStr << "highp " << lType; + lTypeStr = lTypeStrStr.str(); + std::stringstream rTypeStrStr; + rTypeStrStr << "highp " << rType; + rTypeStr = rTypeStrStr.str(); + } + + // Note that y should be passed through angle_frm at the function call site, + // but x can't be passed through angle_frm there since it is an inout parameter. + // So only pass x and the result through angle_frm here. + sink << + lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" + " x = angle_frm(angle_frm(x) " << opStr << " y);\n" + " return x;\n" + "}\n"; + sink << + lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" + " x = angle_frl(angle_frm(x) " << opStr << " y);\n" + " return x;\n" + "}\n"; +} + +const char *getFloatTypeStr(const TType& type) +{ + switch (type.getNominalSize()) + { + case 1: + return "float"; + case 2: + return type.getSecondarySize() > 1 ? "mat2" : "vec2"; + case 3: + return type.getSecondarySize() > 1 ? "mat3" : "vec3"; + case 4: + return type.getSecondarySize() > 1 ? "mat4" : "vec4"; + default: + UNREACHABLE(); + return NULL; + } +} + +bool canRoundFloat(const TType &type) +{ + return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() && + (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium); +} + +TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child) +{ + TIntermAggregate *callNode = new TIntermAggregate(); + callNode->setOp(EOpInternalFunctionCall); + callNode->setName(name); + callNode->getSequence()->push_back(child); + return callNode; +} + +TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild) +{ + TString roundFunctionName; + if (roundedChild->getPrecision() == EbpMedium) + roundFunctionName = "angle_frm"; + else + roundFunctionName = "angle_frl"; + return createInternalFunctionCallNode(roundFunctionName, roundedChild); +} + +TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr) +{ + std::stringstream strstr; + if (left->getPrecision() == EbpMedium) + strstr << "angle_compound_" << opNameStr << "_frm"; + else + strstr << "angle_compound_" << opNameStr << "_frl"; + TString functionName = strstr.str().c_str(); + TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left); + callNode->getSequence()->push_back(right); + return callNode; +} + +bool parentUsesResult(TIntermNode* parent, TIntermNode* node) +{ + if (!parent) + { + return false; + } + + TIntermAggregate *aggParent = parent->getAsAggregate(); + // If the parent's op is EOpSequence, the result is not assigned anywhere, + // so rounding it is not needed. In particular, this can avoid a lot of + // unnecessary rounding of unused return values of assignment. + if (aggParent && aggParent->getOp() == EOpSequence) + { + return false; + } + if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node)) + { + return false; + } + return true; +} + +} // namespace anonymous + +EmulatePrecision::EmulatePrecision() + : TIntermTraverser(true, true, true), + mDeclaringVariables(false), + mInLValue(false), + mInFunctionCallOutParameter(false) +{} + +void EmulatePrecision::visitSymbol(TIntermSymbol *node) +{ + if (canRoundFloat(node->getType()) && + !mDeclaringVariables && !mInLValue && !mInFunctionCallOutParameter) + { + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } +} + + +bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) +{ + bool visitChildren = true; + + if (node->isAssignment()) + { + if (visit == PreVisit) + mInLValue = true; + else if (visit == InVisit) + mInLValue = false; + } + + TOperator op = node->getOp(); + + // RHS of initialize is not being declared. + if (op == EOpInitialize && visit == InVisit) + mDeclaringVariables = false; + + if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit) + visitChildren = false; + + if (visit != PreVisit) + return visitChildren; + + const TType& type = node->getType(); + bool roundFloat = canRoundFloat(type); + + if (roundFloat) { + switch (op) { + // Math operators that can result in a float may need to apply rounding to the return + // value. Note that in the case of assignment, the rounding is applied to its return + // value here, not the value being assigned. + case EOpAssign: + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + { + TIntermNode *parent = getParentNode(); + if (!parentUsesResult(parent, node)) + { + break; + } + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + break; + } + + // Compound assignment cases need to replace the operator with a function call. + case EOpAddAssign: + { + mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + case EOpSubAssign: + { + mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + { + mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + case EOpDivAssign: + { + mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + default: + // The rest of the binary operations should not need precision emulation. + break; + } + } + return visitChildren; +} + +bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) +{ + bool visitChildren = true; + switch (node->getOp()) + { + case EOpSequence: + case EOpConstructStruct: + // No special handling + break; + case EOpFunction: + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + TIntermSequence::const_iterator seqIter = sequence.begin(); + TIntermAggregate *params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + mFunctionMap[node->getName()] = params->getSequence(); + } + break; + case EOpPrototype: + if (visit == PreVisit) + mFunctionMap[node->getName()] = node->getSequence(); + visitChildren = false; + break; + case EOpParameters: + visitChildren = false; + break; + case EOpInvariantDeclaration: + visitChildren = false; + break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; + case EOpFunctionCall: + { + // Function call. + bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end()); + if (visit == PreVisit) + { + // User-defined function return values are not rounded, this relies on that + // calculations producing the value were rounded. + TIntermNode *parent = getParentNode(); + if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node)) + { + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } + + if (inFunctionMap) + { + mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin()); + if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end()) + { + TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier(); + mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut); + } + } + else + { + // The function is not user-defined - it is likely built-in texture function. + // Assume that those do not have out parameters. + mInFunctionCallOutParameter = false; + } + } + else if (visit == InVisit) + { + if (inFunctionMap) + { + ++mSeqIterStack.back(); + TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier(); + mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut); + } + } + else + { + if (inFunctionMap) + { + mSeqIterStack.pop_back(); + mInFunctionCallOutParameter = false; + } + } + break; + } + default: + TIntermNode *parent = getParentNode(); + if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node)) + { + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } + break; + } + return visitChildren; +} + +bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node) +{ + switch (node->getOp()) + { + case EOpNegative: + case EOpVectorLogicalNot: + case EOpLogicalNot: + break; + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (visit == PreVisit) + mInLValue = true; + else if (visit == PostVisit) + mInLValue = false; + break; + default: + if (canRoundFloat(node->getType()) && visit == PreVisit) + { + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } + break; + } + + return true; +} + +void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage) +{ + // Other languages not yet supported + ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || + outputLanguage == SH_GLSL_CORE_OUTPUT || + outputLanguage == SH_ESSL_OUTPUT); + writeCommonPrecisionEmulationHelpers(sink, outputLanguage); + + EmulationSet::const_iterator it; + for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add"); + for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub"); + for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div"); + for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul"); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h new file mode 100644 index 0000000000..f1f560aa85 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2002-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 COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ +#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ + +#include "common/angleutils.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" +#include "GLSLANG/ShaderLang.h" + +// This class gathers all compound assignments from the AST and can then write +// the functions required for their precision emulation. This way there is no +// need to write a huge number of variations of the emulated compound assignment +// to every translated shader with emulation enabled. + +class EmulatePrecision : public TIntermTraverser +{ + public: + EmulatePrecision(); + + virtual void visitSymbol(TIntermSymbol *node); + virtual bool visitBinary(Visit visit, TIntermBinary *node); + virtual bool visitUnary(Visit visit, TIntermUnary *node); + virtual bool visitAggregate(Visit visit, TIntermAggregate *node); + + void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage); + + private: + struct TypePair + { + TypePair(const char *l, const char *r) + : lType(l), rType(r) { } + + const char *lType; + const char *rType; + }; + + struct TypePairComparator + { + bool operator() (const TypePair& l, const TypePair& r) const + { + if (l.lType == r.lType) + return l.rType < r.rType; + return l.lType < r.lType; + } + }; + + typedef std::set<TypePair, TypePairComparator> EmulationSet; + EmulationSet mEmulateCompoundAdd; + EmulationSet mEmulateCompoundSub; + EmulationSet mEmulateCompoundMul; + EmulationSet mEmulateCompoundDiv; + + // Stack of function call parameter iterators + std::vector<TIntermSequence::const_iterator> mSeqIterStack; + + bool mDeclaringVariables; + bool mInLValue; + bool mInFunctionCallOutParameter; + + struct TStringComparator + { + bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; } + }; + + // Map from function names to their parameter sequences + std::map<TString, TIntermSequence*, TStringComparator> mFunctionMap; +}; + +#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h index 5c1595fb21..cf4d7fba31 100644 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h +++ b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _EXTENSION_BEHAVIOR_INCLUDED_ -#define _EXTENSION_BEHAVIOR_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ +#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ #include <map> #include <string> @@ -34,4 +34,4 @@ inline const char* getBehaviorString(TBehavior b) // Mapping between extension name and behavior. typedef std::map<std::string, TBehavior> TExtensionBehavior; -#endif // _EXTENSION_TABLE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h index c93a6f808e..07b9a72c5c 100644 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_FLAGSTD140STRUCTS_H_ -#define COMPILER_FLAGSTD140STRUCTS_H_ +#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ +#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ #include "compiler/translator/IntermNode.h" @@ -34,4 +34,4 @@ std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node); } -#endif // COMPILER_FLAGSTD140STRUCTS_H_ +#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h index a820d2a20d..c8787d55a0 100644 --- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_FORLOOPUNROLL_H_ -#define COMPILER_FORLOOPUNROLL_H_ +#ifndef COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ +#define COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ #include "compiler/translator/LoopInfo.h" @@ -47,4 +47,4 @@ class ForLoopUnrollMarker : public TIntermTraverser bool mVisitSamplerArrayIndexNodeInsideLoop; }; -#endif +#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h index 26546a3e7b..09c959f9da 100644 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_HASH_NAMES_H_ -#define COMPILER_HASH_NAMES_H_ +#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_ +#define COMPILER_TRANSLATOR_HASHNAMES_H_ #include <map> @@ -15,4 +15,4 @@ typedef std::map<TPersistString, TPersistString> NameMap; -#endif // COMPILER_HASH_NAMES_H_ +#endif // COMPILER_TRANSLATOR_HASHNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h index 698a8b454b..f47fafa8ee 100644 --- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h +++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _INFOSINK_INCLUDED_ -#define _INFOSINK_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INFOSINK_H_ +#define COMPILER_TRANSLATOR_INFOSINK_H_ #include <math.h> #include <stdlib.h> @@ -113,4 +113,4 @@ public: TInfoSinkBase obj; }; -#endif // _INFOSINK_INCLUDED_ +#endif // COMPILER_TRANSLATOR_INFOSINK_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp index 10b21e6d28..9e11405758 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -21,307 +21,208 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR TType *float2 = new TType(EbtFloat, 2); TType *float3 = new TType(EbtFloat, 3); TType *float4 = new TType(EbtFloat, 4); - TType *int1 = new TType(EbtInt); TType *int2 = new TType(EbtInt, 2); TType *int3 = new TType(EbtInt, 3); - TType *int4 = new TType(EbtInt, 4); + TType *uint1 = new TType(EbtUInt); + TType *bool1 = new TType(EbtBool); + TType *genType = new TType(EbtGenType); + TType *genIType = new TType(EbtGenIType); + TType *genUType = new TType(EbtGenUType); + TType *genBType = new TType(EbtGenBType); // // Angle and Trigonometric Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "radians", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "radians", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "radians", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "radians", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "degrees", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "degrees", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "degrees", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "degrees", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sin", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sin", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sin", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sin", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "cos", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "cos", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cos", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "cos", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "tan", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "tan", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "tan", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "tan", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "asin", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "asin", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "asin", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "asin", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "acos", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "acos", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "acos", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "acos", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType); // // Exponential Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "pow", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "pow", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "pow", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "pow", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp2", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp2", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp2", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp2", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log2", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log2", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log2", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log2", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sqrt", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sqrt", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sqrt", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sqrt", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "inversesqrt", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "inversesqrt", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "inversesqrt", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "inversesqrt", float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType); // // Common Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "abs", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "abs", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "abs", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "abs", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sign", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sign", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sign", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sign", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "floor", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "floor", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "floor", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "floor", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "ceil", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "ceil", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "ceil", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "ceil", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "fract", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "fract", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "fract", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "fract", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mod", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "min", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "max", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "clamp", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mix", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "step", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float4, float4); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float1, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float1, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float1, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "smoothstep", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float4, float4, float4); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float1, float1, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float1, float1, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float1, float1, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType); + + TType *outFloat1 = new TType(EbtFloat); + TType *outFloat2 = new TType(EbtFloat, 2); + TType *outFloat3 = new TType(EbtFloat, 3); + TType *outFloat4 = new TType(EbtFloat, 4); + outFloat1->setQualifier(EvqOut); + outFloat2->setQualifier(EvqOut); + outFloat3->setQualifier(EvqOut); + outFloat4->setQualifier(EvqOut); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float1, "modf", float1, outFloat1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float2, "modf", float2, outFloat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float3, "modf", float3, outFloat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float4, "modf", float4, outFloat4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1); // // Geometric Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cross", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "normalize", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "normalize", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "normalize", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "normalize", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "faceforward", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "faceforward", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "faceforward", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "faceforward", float4, float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "reflect", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "reflect", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "reflect", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "reflect", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "refract", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "refract", float2, float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "refract", float3, float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "refract", float4, float4, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1); TType *mat2 = new TType(EbtFloat, 2, 2); TType *mat3 = new TType(EbtFloat, 3, 3); TType *mat4 = new TType(EbtFloat, 4, 4); + TType *mat2x3 = new TType(EbtFloat, 2, 3); + TType *mat3x2 = new TType(EbtFloat, 3, 2); + TType *mat2x4 = new TType(EbtFloat, 2, 4); + TType *mat4x2 = new TType(EbtFloat, 4, 2); + TType *mat3x4 = new TType(EbtFloat, 3, 4); + TType *mat4x3 = new TType(EbtFloat, 4, 3); // // Matrix Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, mat2, "matrixCompMult", mat2, mat2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, mat3, "matrixCompMult", mat3, mat3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, mat4, "matrixCompMult", mat4, mat4); - - TType *bool1 = new TType(EbtBool); - TType *bool2 = new TType(EbtBool, 2); - TType *bool3 = new TType(EbtBool, 3); - TType *bool4 = new TType(EbtBool, 4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4); + + TType *vec = new TType(EbtVec); + TType *ivec = new TType(EbtIVec); + TType *uvec = new TType(EbtUVec); + TType *bvec = new TType(EbtBVec); // // Vector relational functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", bool2, bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", bool3, bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", bool4, bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", bool2, bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", bool3, bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", bool4, bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "not", bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "not", bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "not", bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec); TType *sampler2D = new TType(EbtSampler2D); TType *samplerCube = new TType(EbtSamplerCube); @@ -357,10 +258,10 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR /* The *Grad* variants are new to both vertex and fragment shaders; the fragment * shader specific pieces are added separately below. */ - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DGradEXT", sampler2D, float2, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DGradEXT", sampler2D, float2, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeGradEXT", samplerCube, float3, float3, float3); } if (type == GL_FRAGMENT_SHADER) @@ -372,32 +273,21 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR if (resources.OES_standard_derivatives) { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdx", float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdx", float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdx", float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdx", float4); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdy", float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdy", float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdy", float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdy", float4); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "fwidth", float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "fwidth", float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "fwidth", float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "fwidth", float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives", genType, "dFdx", genType); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives", genType, "dFdy", genType); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives", genType, "fwidth", genType); } if (resources.EXT_shader_texture_lod) { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLodEXT", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLodEXT", samplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DLodEXT", sampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeLodEXT", samplerCube, float3, float1); } } - if(type == GL_VERTEX_SHADER) + if (type == GL_VERTEX_SHADER) { symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1); symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1); @@ -463,22 +353,11 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1); - if(type == GL_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdx", float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdx", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdx", float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdx", float4); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdy", float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdy", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdy", float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdy", float4); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "fwidth", float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "fwidth", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "fwidth", float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "fwidth", float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdy, genType, "dFdy", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFwidth, genType, "fwidth", genType); } symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2); @@ -486,7 +365,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2); - if(type == GL_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1); @@ -499,7 +378,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2); - if(type == GL_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1); @@ -600,146 +479,84 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, TSymbolTable &symbolTable) { // - // First, insert some special built-in variables that are not in + // Insert some special built-in variables that are not in // the built-in header files. // - switch(type) { - case GL_FRAGMENT_SHADER: - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + switch (type) + { + case GL_FRAGMENT_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), + TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), + TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), + TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); // // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. // Instead, css_MixColor and css_ColorMatrix are available. // - if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); - if (resources.EXT_frag_depth) { - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); - symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth"); - } - } else { - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); - } - - break; - - case GL_VERTEX_SHADER: - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); - break; - - default: assert(false && "Language not supported"); - } - - // - // Next, identify which built-ins from the already loaded headers have - // a mapping to an operator. Those that are not identified as such are - // expected to be resolved through a library of functions, versus as - // operations. - // - symbolTable.relateToOperator(COMMON_BUILTINS, "matrixCompMult", EOpMul); - - symbolTable.relateToOperator(COMMON_BUILTINS, "equal", EOpVectorEqual); - symbolTable.relateToOperator(COMMON_BUILTINS, "notEqual", EOpVectorNotEqual); - symbolTable.relateToOperator(COMMON_BUILTINS, "lessThan", EOpLessThan); - symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThan", EOpGreaterThan); - symbolTable.relateToOperator(COMMON_BUILTINS, "lessThanEqual", EOpLessThanEqual); - symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThanEqual", EOpGreaterThanEqual); - - symbolTable.relateToOperator(COMMON_BUILTINS, "radians", EOpRadians); - symbolTable.relateToOperator(COMMON_BUILTINS, "degrees", EOpDegrees); - symbolTable.relateToOperator(COMMON_BUILTINS, "sin", EOpSin); - symbolTable.relateToOperator(COMMON_BUILTINS, "cos", EOpCos); - symbolTable.relateToOperator(COMMON_BUILTINS, "tan", EOpTan); - symbolTable.relateToOperator(COMMON_BUILTINS, "asin", EOpAsin); - symbolTable.relateToOperator(COMMON_BUILTINS, "acos", EOpAcos); - symbolTable.relateToOperator(COMMON_BUILTINS, "atan", EOpAtan); - - symbolTable.relateToOperator(COMMON_BUILTINS, "pow", EOpPow); - symbolTable.relateToOperator(COMMON_BUILTINS, "exp2", EOpExp2); - symbolTable.relateToOperator(COMMON_BUILTINS, "log", EOpLog); - symbolTable.relateToOperator(COMMON_BUILTINS, "exp", EOpExp); - symbolTable.relateToOperator(COMMON_BUILTINS, "log2", EOpLog2); - symbolTable.relateToOperator(COMMON_BUILTINS, "sqrt", EOpSqrt); - symbolTable.relateToOperator(COMMON_BUILTINS, "inversesqrt", EOpInverseSqrt); - - symbolTable.relateToOperator(COMMON_BUILTINS, "abs", EOpAbs); - symbolTable.relateToOperator(COMMON_BUILTINS, "sign", EOpSign); - symbolTable.relateToOperator(COMMON_BUILTINS, "floor", EOpFloor); - symbolTable.relateToOperator(COMMON_BUILTINS, "ceil", EOpCeil); - symbolTable.relateToOperator(COMMON_BUILTINS, "fract", EOpFract); - symbolTable.relateToOperator(COMMON_BUILTINS, "mod", EOpMod); - symbolTable.relateToOperator(COMMON_BUILTINS, "min", EOpMin); - symbolTable.relateToOperator(COMMON_BUILTINS, "max", EOpMax); - symbolTable.relateToOperator(COMMON_BUILTINS, "clamp", EOpClamp); - symbolTable.relateToOperator(COMMON_BUILTINS, "mix", EOpMix); - symbolTable.relateToOperator(COMMON_BUILTINS, "step", EOpStep); - symbolTable.relateToOperator(COMMON_BUILTINS, "smoothstep", EOpSmoothStep); - - symbolTable.relateToOperator(COMMON_BUILTINS, "length", EOpLength); - symbolTable.relateToOperator(COMMON_BUILTINS, "distance", EOpDistance); - symbolTable.relateToOperator(COMMON_BUILTINS, "dot", EOpDot); - symbolTable.relateToOperator(COMMON_BUILTINS, "cross", EOpCross); - symbolTable.relateToOperator(COMMON_BUILTINS, "normalize", EOpNormalize); - symbolTable.relateToOperator(COMMON_BUILTINS, "faceforward", EOpFaceForward); - symbolTable.relateToOperator(COMMON_BUILTINS, "reflect", EOpReflect); - symbolTable.relateToOperator(COMMON_BUILTINS, "refract", EOpRefract); - - symbolTable.relateToOperator(COMMON_BUILTINS, "any", EOpAny); - symbolTable.relateToOperator(COMMON_BUILTINS, "all", EOpAll); - symbolTable.relateToOperator(COMMON_BUILTINS, "not", EOpVectorLogicalNot); - - // Map language-specific operators. - switch(type) { - case GL_VERTEX_SHADER: - break; - case GL_FRAGMENT_SHADER: - if (resources.OES_standard_derivatives) + if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx", EOpDFdx); - symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdy", EOpDFdy); - symbolTable.relateToOperator(ESSL1_BUILTINS, "fwidth", EOpFwidth); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), + TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); + fragData.setArraySize(resources.MaxDrawBuffers); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); + + if (resources.EXT_frag_depth) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"), + TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + } - symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdx", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdy", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "fwidth", "GL_OES_standard_derivatives"); + if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) + { + TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true); + lastFragData.setArraySize(resources.MaxDrawBuffers); + + if (resources.EXT_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); + } + else if (resources.NV_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragColor"), + TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); + symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); + } + } + else if (resources.ARM_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragColorARM"), + TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); + } } - if (resources.EXT_shader_texture_lod) + else { - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DLodEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod"); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), + TType(EbtFloat, EbpMedium, EvqGlobal, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), + TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); } - break; - default: break; - } - symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdx", EOpDFdx); - symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdy", EOpDFdy); - symbolTable.relateToOperator(ESSL3_BUILTINS, "fwidth", EOpFwidth); - - if (resources.EXT_shader_texture_lod) - { - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DGradEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjGradEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeGradEXT", "GL_EXT_shader_texture_lod"); - } + break; - // Finally add resource-specific variables. - switch(type) { - case GL_FRAGMENT_SHADER: - if (spec != SH_CSS_SHADERS_SPEC) { - // Set up gl_FragData. The array size. - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); - fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); - } + case GL_VERTEX_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), + TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), + TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + symbolTable.insert(ESSL3_BUILTINS, new TVariable(NewPoolTString("gl_InstanceID"), + TType(EbtInt, EbpHigh, EvqInstanceID, 1))); break; - default: break; + + default: + assert(false && "Language not supported"); } } @@ -758,4 +575,20 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, extBehavior["GL_EXT_frag_depth"] = EBhUndefined; if (resources.EXT_shader_texture_lod) extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined; + if (resources.EXT_shader_framebuffer_fetch) + extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined; + if (resources.NV_shader_framebuffer_fetch) + extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined; + if (resources.ARM_shader_framebuffer_fetch) + extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined; +} + +void ResetExtensionBehavior(TExtensionBehavior &extBehavior) +{ + for (auto ext_iter = extBehavior.begin(); + ext_iter != extBehavior.end(); + ++ext_iter) + { + ext_iter->second = EBhUndefined; + } } diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h index cc1862c90e..c43ce3417a 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.h +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _INITIALIZE_INCLUDED_ -#define _INITIALIZE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_ +#define COMPILER_TRANSLATOR_INITIALIZE_H_ #include "compiler/translator/Common.h" #include "compiler/translator/Compiler.h" @@ -20,4 +20,10 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, void InitExtensionBehavior(const ShBuiltInResources& resources, TExtensionBehavior& extensionBehavior); -#endif // _INITIALIZE_INCLUDED_ +// Resets the behavior of the extensions listed in |extensionBehavior| to the +// undefined state. These extensions will only be those initially supported in +// the ShBuiltInResources object for this compiler instance. All other +// extensions will remain unsupported. +void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior); + +#endif // COMPILER_TRANSLATOR_INITIALIZE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h index 43070cc3ff..4c400760f6 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h @@ -3,11 +3,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef __INITIALIZEDLL_H -#define __INITIALIZEDLL_H +#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ +#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ bool InitProcess(); void DetachProcess(); -#endif // __INITIALIZEDLL_H +#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h index 0715941424..8c65cb28da 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#ifndef __INITIALIZE_GLOBALS_INCLUDED_ -#define __INITIALIZE_GLOBALS_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ +#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ bool InitializePoolIndex(); void FreePoolIndex(); -#endif // __INITIALIZE_GLOBALS_INCLUDED_ +#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h index bffbab87d0..fa9b885e80 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_ -#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ +#define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ bool InitializeParseContextIndex(); void FreeParseContextIndex(); @@ -14,4 +14,4 @@ struct TParseContext; extern void SetGlobalParseContext(TParseContext* context); extern TParseContext* GetGlobalParseContext(); -#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h index 59c3ea0a39..4a81266498 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_INITIALIZE_VARIABLES_H_ -#define COMPILER_INITIALIZE_VARIABLES_H_ +#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ +#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ #include "compiler/translator/IntermNode.h" @@ -47,4 +47,4 @@ class InitializeVariables : public TIntermTraverser bool mCodeInserted; }; -#endif // COMPILER_INITIALIZE_VARIABLES_H_ +#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp index aa0f31d170..266e3c8e3d 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -157,26 +157,6 @@ bool TIntermLoop::replaceChildNode( return false; } -void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mInit) - { - nodeQueue->push(mInit); - } - if (mCond) - { - nodeQueue->push(mCond); - } - if (mExpr) - { - nodeQueue->push(mExpr); - } - if (mBody) - { - nodeQueue->push(mBody); - } -} - bool TIntermBranch::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -184,14 +164,6 @@ bool TIntermBranch::replaceChildNode( return false; } -void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mExpression) - { - nodeQueue->push(mExpression); - } -} - bool TIntermBinary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -200,18 +172,6 @@ bool TIntermBinary::replaceChildNode( return false; } -void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mLeft) - { - nodeQueue->push(mLeft); - } - if (mRight) - { - nodeQueue->push(mRight); - } -} - bool TIntermUnary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -219,14 +179,6 @@ bool TIntermUnary::replaceChildNode( return false; } -void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mOperand) - { - nodeQueue->push(mOperand); - } -} - bool TIntermAggregate::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -237,14 +189,6 @@ bool TIntermAggregate::replaceChildNode( return false; } -void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) - { - nodeQueue->push(mSequence[childIndex]); - } -} - void TIntermAggregate::setPrecisionFromChildren() { if (getBasicType() == EbtBool) @@ -300,20 +244,19 @@ bool TIntermSelection::replaceChildNode( return false; } -void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +bool TIntermSwitch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) { - if (mCondition) - { - nodeQueue->push(mCondition); - } - if (mTrueBlock) - { - nodeQueue->push(mTrueBlock); - } - if (mFalseBlock) - { - nodeQueue->push(mFalseBlock); - } + REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); + REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement); + return false; +} + +bool TIntermCase::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + return false; } // @@ -336,6 +279,12 @@ bool TIntermOperator::isAssignment() const case EOpMatrixTimesScalarAssign: case EOpMatrixTimesMatrixAssign: case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: return true; default: return false; @@ -379,65 +328,55 @@ bool TIntermOperator::isConstructor() const // Make sure the type of a unary operator is appropriate for its // combination of operation and operand type. // -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink &) +void TIntermUnary::promote(const TType *funcReturnType) { switch (mOp) { - case EOpLogicalNot: - if (mOperand->getBasicType() != EbtBool) - return false; + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + mType.setPrecision(EbpHigh); break; - case EOpNegative: - case EOpPositive: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (mOperand->getBasicType() == EbtBool) - return false; + case EOpUnpackHalf2x16: + mType.setPrecision(EbpMedium); break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - default: - if (mOperand->getBasicType() != EbtFloat) - return false; + setType(mOperand->getType()); } - setType(mOperand->getType()); - mType.setQualifier(EvqTemporary); + if (funcReturnType != nullptr) + { + if (funcReturnType->getBasicType() == EbtBool) + { + // Bool types should not have precision. + setType(*funcReturnType); + } + else + { + // Precision of the node has been set based on the operand. + setTypePreservePrecision(*funcReturnType); + } + } - return true; + mType.setQualifier(EvqTemporary); } // // Establishes the type of the resultant operation, as well as // makes the operator the correct one for the operands. // -// Returns false if operator can't work on operands. +// For lots of operations it should already be established that the operand +// combination is valid, but returns false if operator can't work on operands. // bool TIntermBinary::promote(TInfoSink &infoSink) { - // This function only handles scalars, vectors, and matrices. - if (mLeft->isArray() || mRight->isArray()) - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (mLeft->getBasicType() != mRight->getBasicType()) - { - return false; - } + ASSERT(mLeft->isArray() == mRight->isArray()); // // Base assumption: just make the type the same as the left @@ -483,12 +422,9 @@ bool TIntermBinary::promote(TInfoSink &infoSink) // And and Or operate on conditionals // case EOpLogicalAnd: + case EOpLogicalXor: case EOpLogicalOr: - // Both operands must be of type bool. - if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) - { - return false; - } + ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); setType(TType(EbtBool, EbpUndefined)); break; @@ -625,12 +561,28 @@ bool TIntermBinary::promote(TInfoSink &infoSink) case EOpAssign: case EOpInitialize: + // No more additional checks are needed. + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); + break; case EOpAdd: case EOpSub: case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: case EOpAddAssign: case EOpSubAssign: case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: if ((mLeft->isMatrix() && mRight->isVector()) || (mLeft->isVector() && mRight->isMatrix())) { @@ -641,13 +593,19 @@ bool TIntermBinary::promote(TInfoSink &infoSink) if (mLeft->getNominalSize() != mRight->getNominalSize() || mLeft->getSecondarySize() != mRight->getSecondarySize()) { - // If the nominal size of operands do not match: - // One of them must be scalar. + // If the nominal sizes of operands do not match: + // One of them must be a scalar. if (!mLeft->isScalar() && !mRight->isScalar()) return false; - // Operator cannot be of type pure assignment. - if (mOp == EOpAssign || mOp == EOpInitialize) + // In the case of compound assignment other than multiply-assign, + // the right side needs to be a scalar. Otherwise a vector/matrix + // would be assigned to a scalar. A scalar can't be shifted by a + // vector either. + if (!mRight->isScalar() && + (isAssignment() || + mOp == EOpBitShiftLeft || + mOp == EOpBitShiftRight)) return false; } @@ -656,6 +614,11 @@ bool TIntermBinary::promote(TInfoSink &infoSink) mLeft->getSecondarySize(), mRight->getSecondarySize()); setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize)); + if (mLeft->isArray()) + { + ASSERT(mLeft->getArraySize() == mRight->getArraySize()); + mType.setArraySize(mLeft->getArraySize()); + } } break; @@ -665,11 +628,8 @@ bool TIntermBinary::promote(TInfoSink &infoSink) case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: - if ((mLeft->getNominalSize() != mRight->getNominalSize()) || - (mLeft->getSecondarySize() != mRight->getSecondarySize())) - { - return false; - } + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); setType(TType(EbtBool, EbpUndefined)); break; @@ -793,6 +753,7 @@ TIntermTyped *TIntermConstantUnion::fold( break; case EOpDiv: + case EOpIMod: { tempConstArray = new ConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) @@ -810,6 +771,7 @@ TIntermTyped *TIntermConstantUnion::fold( } else { + ASSERT(op == EOpDiv); tempConstArray[i].setFConst( unionArray[i].getFConst() / rightUnionArray[i].getFConst()); @@ -826,9 +788,19 @@ TIntermTyped *TIntermConstantUnion::fold( } else { - tempConstArray[i].setIConst( - unionArray[i].getIConst() / - rightUnionArray[i].getIConst()); + if (op == EOpDiv) + { + tempConstArray[i].setIConst( + unionArray[i].getIConst() / + rightUnionArray[i].getIConst()); + } + else + { + ASSERT(op == EOpIMod); + tempConstArray[i].setIConst( + unionArray[i].getIConst() % + rightUnionArray[i].getIConst()); + } } break; @@ -842,9 +814,19 @@ TIntermTyped *TIntermConstantUnion::fold( } else { - tempConstArray[i].setUConst( - unionArray[i].getUConst() / - rightUnionArray[i].getUConst()); + if (op == EOpDiv) + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + else + { + ASSERT(op == EOpIMod); + tempConstArray[i].setUConst( + unionArray[i].getUConst() % + rightUnionArray[i].getUConst()); + } } break; @@ -968,6 +950,32 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpBitwiseAnd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] & rightUnionArray[i]; + break; + case EOpBitwiseXor: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] ^ rightUnionArray[i]; + break; + case EOpBitwiseOr: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] | rightUnionArray[i]; + break; + case EOpBitShiftLeft: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] << rightUnionArray[i]; + break; + case EOpBitShiftRight: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] >> rightUnionArray[i]; + break; + case EOpLessThan: ASSERT(objectSize == 1); tempConstArray = new ConstantUnion[1]; @@ -1160,6 +1168,23 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpBitwiseNot: + switch (getType().getBasicType()) + { + case EbtInt: + tempConstArray[i].setIConst(~unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(~unionArray[i].getUConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + default: return NULL; } @@ -1181,3 +1206,29 @@ TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunctio TString hashedName = stream.str(); return hashedName; } + +void TIntermTraverser::updateTree() +{ + for (size_t ii = 0; ii < mReplacements.size(); ++ii) + { + const NodeUpdateEntry& entry = mReplacements[ii]; + ASSERT(entry.parent); + bool replaced = entry.parent->replaceChildNode( + entry.original, entry.replacement); + ASSERT(replaced); + + if (!entry.originalBecomesChildOfReplacement) + { + // In AST traversing, a parent is visited before its children. + // After we replace a node, if an immediate child is to + // be replaced, we need to make sure we don't update the replaced + // node; instead, we update the replacement node. + for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) + { + NodeUpdateEntry& entry2 = mReplacements[jj]; + if (entry2.parent == entry.original) + entry2.parent = entry.replacement; + } + } + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h index 32c70f4671..9f732cbb00 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -13,182 +13,19 @@ // each node can have it's own type of list of children. // -#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_ +#define COMPILER_TRANSLATOR_INTERMNODE_H_ #include "GLSLANG/ShaderLang.h" #include <algorithm> #include <queue> +#include "common/angleutils.h" #include "compiler/translator/Common.h" #include "compiler/translator/Types.h" #include "compiler/translator/ConstantUnion.h" - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator -{ - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpInvariantDeclaration, // Specialized declarations for attributing invariance - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpPositive, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - EOpVectorSwizzle, - - // - // Built-in functions potentially mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpCeil, - EOpFract, - EOpMod, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMatrixTimesMatrix, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructors - // - - EOpConstructInt, - EOpConstructUInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructMat2, - EOpConstructMat3, - EOpConstructMat4, - EOpConstructStruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign -}; +#include "compiler/translator/Operator.h" class TIntermTraverser; class TIntermAggregate; @@ -196,10 +33,13 @@ class TIntermBinary; class TIntermUnary; class TIntermConstantUnion; class TIntermSelection; +class TIntermSwitch; +class TIntermCase; class TIntermTyped; class TIntermSymbol; class TIntermLoop; class TInfoSink; +class TInfoSinkBase; class TIntermRaw; // @@ -228,6 +68,8 @@ class TIntermNode virtual TIntermBinary *getAsBinaryNode() { return 0; } virtual TIntermUnary *getAsUnaryNode() { return 0; } virtual TIntermSelection *getAsSelectionNode() { return 0; } + virtual TIntermSwitch *getAsSwitchNode() { return 0; } + virtual TIntermCase *getAsCaseNode() { return 0; } virtual TIntermSymbol *getAsSymbolNode() { return 0; } virtual TIntermLoop *getAsLoopNode() { return 0; } virtual TIntermRaw *getAsRawNode() { return 0; } @@ -237,10 +79,6 @@ class TIntermNode virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement) = 0; - // For traversing a tree in no particular order, but using - // heap memory. - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0; - protected: TSourceLoc mLine; }; @@ -331,8 +169,6 @@ class TIntermLoop : public TIntermNode void setUnrollFlag(bool flag) { mUnrollFlag = flag; } bool getUnrollFlag() const { return mUnrollFlag; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - protected: TLoopType mType; TIntermNode *mInit; // for-loop initialization @@ -360,8 +196,6 @@ class TIntermBranch : public TIntermNode TOperator getFlowOp() { return mFlowOp; } TIntermTyped* getExpression() { return mExpression; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - protected: TOperator mFlowOp; TIntermTyped *mExpression; // non-zero except for "return exp;" statements @@ -394,8 +228,6 @@ class TIntermSymbol : public TIntermTyped virtual TIntermSymbol *getAsSymbolNode() { return this; } virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} - protected: int mId; TString mSymbol; @@ -419,7 +251,6 @@ class TIntermRaw : public TIntermTyped virtual TIntermRaw *getAsRawNode() { return this; } virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} protected: TString mRawText; @@ -459,8 +290,6 @@ class TIntermConstantUnion : public TIntermTyped TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {} - protected: ConstantUnion *mUnionArrayPointer; }; @@ -519,8 +348,6 @@ class TIntermBinary : public TIntermOperator void setAddIndexClamp() { mAddIndexClamp = true; } bool getAddIndexClamp() { return mAddIndexClamp; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - protected: TIntermTyped* mLeft; TIntermTyped* mRight; @@ -556,13 +383,11 @@ class TIntermUnary : public TIntermOperator void setOperand(TIntermTyped *operand) { mOperand = operand; } TIntermTyped *getOperand() { return mOperand; } - bool promote(TInfoSink &); + void promote(const TType *funcReturnType); void setUseEmulatedFunction() { mUseEmulatedFunction = true; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - protected: TIntermTyped *mOperand; @@ -613,8 +438,6 @@ class TIntermAggregate : public TIntermOperator void setUseEmulatedFunction() { mUseEmulatedFunction = true; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - void setPrecisionFromChildren(); void setBuiltInFunctionPrecision(); @@ -634,7 +457,7 @@ class TIntermAggregate : public TIntermOperator }; // -// For if tests. Simplified since there is no switch statement. +// For if tests. // class TIntermSelection : public TIntermTyped { @@ -664,14 +487,64 @@ class TIntermSelection : public TIntermTyped TIntermNode *getFalseBlock() const { return mFalseBlock; } TIntermSelection *getAsSelectionNode() { return this; } - virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const; - protected: TIntermTyped *mCondition; TIntermNode *mTrueBlock; TIntermNode *mFalseBlock; }; +// +// Switch statement. +// +class TIntermSwitch : public TIntermNode +{ + public: + TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList) + : TIntermNode(), + mInit(init), + mStatementList(statementList) + { + } + + void traverse(TIntermTraverser *it) override; + bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) override; + + TIntermSwitch *getAsSwitchNode() override { return this; } + + TIntermAggregate *getStatementList() { return mStatementList; } + void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; } + + protected: + TIntermTyped *mInit; + TIntermAggregate *mStatementList; +}; + +// +// Case label. +// +class TIntermCase : public TIntermNode +{ + public: + TIntermCase(TIntermTyped *condition) + : TIntermNode(), + mCondition(condition) + { + } + + void traverse(TIntermTraverser *it) override; + bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) override; + + TIntermCase *getAsCaseNode() override { return this; } + + bool hasCondition() const { return mCondition != nullptr; } + TIntermTyped *getCondition() const { return mCondition; } + + protected: + TIntermTyped *mCondition; +}; + enum Visit { PreVisit, @@ -687,7 +560,7 @@ enum Visit // When using this, just fill in the methods for nodes you want visited. // Return false from a pre-visit to skip visiting that node's subtree. // -class TIntermTraverser +class TIntermTraverser : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); @@ -708,6 +581,8 @@ class TIntermTraverser virtual bool visitBinary(Visit, TIntermBinary *) { return true; } virtual bool visitUnary(Visit, TIntermUnary *) { return true; } virtual bool visitSelection(Visit, TIntermSelection *) { return true; } + virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; } + virtual bool visitCase(Visit, TIntermCase *) { return true; } virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } virtual bool visitLoop(Visit, TIntermLoop *) { return true; } virtual bool visitBranch(Visit, TIntermBranch *) { return true; } @@ -741,12 +616,38 @@ class TIntermTraverser const bool postVisit; const bool rightToLeft; + // If traversers need to replace nodes, they can add the replacements in + // mReplacements during traversal and the user of the traverser should call + // this function after traversal to perform them. + void updateTree(); + protected: int mDepth; int mMaxDepth; // All the nodes from root to the current node's parent during traversing. TVector<TIntermNode *> mPath; + + struct NodeUpdateEntry + { + NodeUpdateEntry(TIntermNode *_parent, + TIntermNode *_original, + TIntermNode *_replacement, + bool _originalBecomesChildOfReplacement) + : parent(_parent), + original(_original), + replacement(_replacement), + originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {} + + TIntermNode *parent; + TIntermNode *original; + TIntermNode *replacement; + bool originalBecomesChildOfReplacement; + }; + + // During traversing, save all the changes that need to happen into + // mReplacements, then do them by calling updateTree(). + std::vector<NodeUpdateEntry> mReplacements; }; // @@ -768,10 +669,10 @@ class TMaxDepthTraverser : public TIntermTraverser virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } -protected: + protected: bool depthCheck() const { return mMaxDepth < mDepthLimit; } int mDepthLimit; }; -#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#endif // COMPILER_TRANSLATOR_INTERMNODE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp index 72b2033fb3..7a7efb71f5 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -194,6 +194,60 @@ void TIntermSelection::traverse(TIntermTraverser *it) } // +// Traverse a switch node. Same comments in binary node apply here. +// +void TIntermSwitch::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitSwitch(PreVisit, this); + + if (visit) + { + it->incrementDepth(this); + if (it->rightToLeft) + { + if (mStatementList) + mStatementList->traverse(it); + if (it->inVisit) + visit = it->visitSwitch(InVisit, this); + if (visit) + mInit->traverse(it); + } + else + { + mInit->traverse(it); + if (it->inVisit) + visit = it->visitSwitch(InVisit, this); + if (visit && mStatementList) + mStatementList->traverse(it); + } + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitSwitch(PostVisit, this); +} + +// +// Traverse a switch node. Same comments in binary node apply here. +// +void TIntermCase::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitCase(PreVisit, this); + + if (visit && mCondition) + mCondition->traverse(it); + + if (visit && it->postVisit) + it->visitCase(PostVisit, this); +} + +// // Traverse a loop node. Same comments in binary node apply here. // void TIntermLoop::traverse(TIntermTraverser *it) diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index e558683c55..320056f8ce 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -13,7 +13,6 @@ #include <algorithm> #include "compiler/translator/Intermediate.h" -#include "compiler/translator/RemoveTree.h" #include "compiler/translator/SymbolTable.h" //////////////////////////////////////////////////////////////////////////// @@ -46,47 +45,6 @@ TIntermSymbol *TIntermediate::addSymbol( TIntermTyped *TIntermediate::addBinaryMath( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - switch (op) - { - case EOpEqual: - case EOpNotEqual: - if (left->isArray()) - return NULL; - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (left->isMatrix() || left->isArray() || left->isVector() || - left->getBasicType() == EbtStruct) - { - return NULL; - } - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - if (left->getBasicType() != EbtBool || - left->isMatrix() || left->isArray() || left->isVector()) - { - return NULL; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) - return NULL; - default: - break; - } - - if (left->getBasicType() != right->getBasicType()) - { - return NULL; - } - // // Need a new node holding things together then. Make // one and promote it to the right type. @@ -169,45 +127,8 @@ TIntermTyped *TIntermediate::addIndex( // Returns the added node. // TIntermTyped *TIntermediate::addUnaryMath( - TOperator op, TIntermNode *childNode, const TSourceLoc &line) + TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType) { - TIntermUnary *node; - TIntermTyped *child = childNode->getAsTyped(); - - if (child == NULL) - { - mInfoSink.info.message(EPrefixInternalError, line, - "Bad type in AddUnaryMath"); - return NULL; - } - - switch (op) - { - case EOpLogicalNot: - if (child->getType().getBasicType() != EbtBool || - child->getType().isMatrix() || - child->getType().isArray() || - child->getType().isVector()) - { - return NULL; - } - break; - - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - case EOpPositive: - if (child->getType().getBasicType() == EbtStruct || - child->getType().isArray()) - { - return NULL; - } - default: - break; - } - TIntermConstantUnion *childTempConstant = 0; if (child->getAsConstantUnion()) childTempConstant = child->getAsConstantUnion(); @@ -215,12 +136,10 @@ TIntermTyped *TIntermediate::addUnaryMath( // // Make a new node for the operator. // - node = new TIntermUnary(op); + TIntermUnary *node = new TIntermUnary(op); node->setLine(line); node->setOperand(child); - - if (!node->promote(mInfoSink)) - return 0; + node->promote(funcReturnType); if (childTempConstant) { @@ -423,6 +342,24 @@ TIntermTyped *TIntermediate::addSelection( return node; } +TIntermSwitch *TIntermediate::addSwitch( + TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line) +{ + TIntermSwitch *node = new TIntermSwitch(init, statementList); + node->setLine(line); + + return node; +} + +TIntermCase *TIntermediate::addCase( + TIntermTyped *condition, const TSourceLoc &line) +{ + TIntermCase *node = new TIntermCase(condition); + node->setLine(line); + + return node; +} + // // Constant terminal nodes. Has a union that contains bool, float or int constants // @@ -510,12 +447,3 @@ bool TIntermediate::postProcess(TIntermNode *root) return true; } - -// -// This deletes the tree. -// -void TIntermediate::remove(TIntermNode *root) -{ - if (root) - RemoveAllTreeNodes(root); -} diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/Intermediate.h index 3b7e7bd802..ec73e22834 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ #include "compiler/translator/IntermNode.h" @@ -35,7 +35,7 @@ class TIntermediate TIntermTyped *addIndex( TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &); TIntermTyped *addUnaryMath( - TOperator op, TIntermNode *child, const TSourceLoc &); + TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType); TIntermAggregate *growAggregate( TIntermNode *left, TIntermNode *right, const TSourceLoc &); TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &); @@ -43,6 +43,10 @@ class TIntermediate TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &); TIntermTyped *addSelection( TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &); + TIntermSwitch *addSwitch( + TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line); + TIntermCase *addCase( + TIntermTyped *condition, const TSourceLoc &line); TIntermTyped *addComma( TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &); @@ -55,8 +59,8 @@ class TIntermediate TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); bool postProcess(TIntermNode *); - void remove(TIntermNode *); - void outputTree(TIntermNode *); + + static void outputTree(TIntermNode *, TInfoSinkBase &); private: void operator=(TIntermediate &); // prevent assignments @@ -64,4 +68,4 @@ class TIntermediate TInfoSink & mInfoSink; }; -#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h index 5f72a6e944..ec73fd0fa5 100644 --- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_ -#define COMPILER_TRANSLATOR_LOOP_INFO_H_ +#ifndef COMPILER_TRANSLATOR_LOOPINFO_H_ +#define COMPILER_TRANSLATOR_LOOPINFO_H_ #include "compiler/translator/IntermNode.h" @@ -76,5 +76,5 @@ class TLoopStack : public TVector<TLoopInfo> void pop(); }; -#endif // COMPILER_TRANSLATOR_LOOP_INDEX_H_ +#endif // COMPILER_TRANSLATOR_LOOPINFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/MMap.h b/src/3rdparty/angle/src/compiler/translator/MMap.h index a308671514..fca843992b 100644 --- a/src/3rdparty/angle/src/compiler/translator/MMap.h +++ b/src/3rdparty/angle/src/compiler/translator/MMap.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _MMAP_INCLUDED_ -#define _MMAP_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_MMAP_H_ +#define COMPILER_TRANSLATOR_MMAP_H_ // // Encapsulate memory mapped files @@ -53,4 +53,4 @@ private: char* fBuff; // the actual data; }; -#endif // _MMAP_INCLUDED_ +#endif // COMPILER_TRANSLATOR_MMAP_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h index 60070c9d33..8ffed614c3 100644 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -6,8 +6,8 @@ // NodeSearch.h: Utilities for searching translator node graphs // -#ifndef TRANSLATOR_NODESEARCH_H_ -#define TRANSLATOR_NODESEARCH_H_ +#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_ +#define COMPILER_TRANSLATOR_NODESEARCH_H_ #include "compiler/translator/IntermNode.h" @@ -77,4 +77,4 @@ class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriti } -#endif // TRANSLATOR_NODESEARCH_H_ +#endif // COMPILER_TRANSLATOR_NODESEARCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.cpp b/src/3rdparty/angle/src/compiler/translator/Operator.cpp new file mode 100644 index 0000000000..ae4512bd44 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Operator.cpp @@ -0,0 +1,195 @@ +// +// Copyright (c) 2002-2015 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 "compiler/translator/Operator.h" + +const char *GetOperatorString(TOperator op) +{ + switch (op) + { + // Note: ops from EOpNull to EOpPrototype can't be handled here. + + case EOpNegative: return "-"; + case EOpPositive: return "+"; + case EOpLogicalNot: return "!"; + case EOpVectorLogicalNot: return "not"; + case EOpBitwiseNot: return "~"; + + case EOpPostIncrement: return "++"; + case EOpPostDecrement: return "--"; + case EOpPreIncrement: return "++"; + case EOpPreDecrement: return "--"; + + case EOpAdd: return "+"; + case EOpSub: return "-"; + case EOpMul: return "*"; + case EOpDiv: return "/"; + case EOpIMod: return "%"; + case EOpEqual: return "=="; + case EOpNotEqual: return "!="; + case EOpVectorEqual: return "equal"; + case EOpVectorNotEqual: return "notEqual"; + case EOpLessThan: return "<"; + case EOpGreaterThan: return ">"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; + case EOpComma: return ","; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: return "*"; + + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + + case EOpBitShiftLeft: return "<<"; + case EOpBitShiftRight: return ">>"; + + case EOpBitwiseAnd: return "&"; + case EOpBitwiseXor: return "^"; + case EOpBitwiseOr: return "|"; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; + + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: return "."; + + case EOpVectorSwizzle: return "."; + + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + + case EOpSinh: return "sinh"; + case EOpCosh: return "cosh"; + case EOpTanh: return "tanh"; + case EOpAsinh: return "asinh"; + case EOpAcosh: return "acosh"; + case EOpAtanh: return "atanh"; + + case EOpPow: return "pow"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpTrunc: return "trunc"; + case EOpRound: return "round"; + case EOpRoundEven: return "roundEven"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpMod: return "mod"; + case EOpModf: return "modf"; + case EOpMin: return "min"; + case EOpMax: return "max"; + case EOpClamp: return "clamp"; + case EOpMix: return "mix"; + case EOpStep: return "step"; + case EOpSmoothStep: return "smoothstep"; + case EOpIsNan: return "isnan"; + case EOpIsInf: return "isinf"; + + case EOpFloatBitsToInt: return "floatBitsToInt"; + case EOpFloatBitsToUint: return "floatBitsToUint"; + case EOpIntBitsToFloat: return "intBitsToFloat"; + case EOpUintBitsToFloat: return "uintBitsToFloat"; + + case EOpPackSnorm2x16: return "packSnorm2x16"; + case EOpPackUnorm2x16: return "packUnorm2x16"; + case EOpPackHalf2x16: return "packHalf2x16"; + case EOpUnpackSnorm2x16: return "unpackSnorm2x16"; + case EOpUnpackUnorm2x16: return "unpackUnorm2x16"; + case EOpUnpackHalf2x16: return "unpackHalf2x16"; + + case EOpLength: return "length"; + case EOpDistance: return "distance"; + case EOpDot: return "dot"; + case EOpCross: return "cross"; + case EOpNormalize: return "normalize"; + case EOpFaceForward: return "faceforward"; + case EOpReflect: return "reflect"; + case EOpRefract: return "refract"; + + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + + case EOpMatrixTimesMatrix: return "*"; + + case EOpOuterProduct: return "outerProduct"; + case EOpTranspose: return "transpose"; + case EOpDeterminant: return "determinant"; + case EOpInverse: return "inverse"; + + case EOpAny: return "any"; + case EOpAll: return "all"; + + case EOpKill: return "kill"; + case EOpReturn: return "return"; + case EOpBreak: return "break"; + case EOpContinue: return "continue"; + + case EOpConstructInt: return "int"; + case EOpConstructUInt: return "uint"; + case EOpConstructBool: return "bool"; + case EOpConstructFloat: return "float"; + case EOpConstructVec2: return "vec2"; + case EOpConstructVec3: return "vec3"; + case EOpConstructVec4: return "vec4"; + case EOpConstructBVec2: return "bvec2"; + case EOpConstructBVec3: return "bvec3"; + case EOpConstructBVec4: return "bvec4"; + case EOpConstructIVec2: return "ivec2"; + case EOpConstructIVec3: return "ivec3"; + case EOpConstructIVec4: return "ivec4"; + case EOpConstructUVec2: return "uvec2"; + case EOpConstructUVec3: return "uvec3"; + case EOpConstructUVec4: return "uvec4"; + case EOpConstructMat2: return "mat2"; + case EOpConstructMat3: return "mat3"; + case EOpConstructMat4: return "mat4"; + // Note: EOpConstructStruct can't be handled here + + case EOpAssign: return "="; + case EOpInitialize: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; + + case EOpDivAssign: return "/="; + case EOpIModAssign: return "%="; + case EOpBitShiftLeftAssign: return "<<="; + case EOpBitShiftRightAssign: return ">>="; + case EOpBitwiseAndAssign: return "&="; + case EOpBitwiseXorAssign: return "^="; + case EOpBitwiseOrAssign: return "|="; + + default: break; + } + return ""; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h new file mode 100644 index 0000000000..8290f952fc --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Operator.h @@ -0,0 +1,226 @@ +// +// Copyright (c) 2002-2015 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 COMPILER_TRANSLATOR_OPERATOR_H_ +#define COMPILER_TRANSLATOR_OPERATOR_H_ + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator +{ + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpInternalFunctionCall, // Call to an internal helper function + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpPositive, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpIMod, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpBitShiftLeft, + EOpBitShiftRight, + + EOpBitwiseAnd, + EOpBitwiseXor, + EOpBitwiseOr, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpMod, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + EOpIsNan, + EOpIsInf, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + + EOpPackSnorm2x16, + EOpPackUnorm2x16, + EOpPackHalf2x16, + EOpUnpackSnorm2x16, + EOpUnpackUnorm2x16, + EOpUnpackHalf2x16, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension + + EOpMatrixTimesMatrix, + + EOpOuterProduct, + EOpTranspose, + EOpDeterminant, + EOpInverse, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructUInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + + EOpDivAssign, + EOpIModAssign, + EOpBitShiftLeftAssign, + EOpBitShiftRightAssign, + EOpBitwiseAndAssign, + EOpBitwiseXorAssign, + EOpBitwiseOrAssign +}; + +// Returns the string corresponding to the operator in GLSL +const char* GetOperatorString(TOperator op); + +#endif // COMPILER_TRANSLATOR_OPERATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp index 65635af1ff..77e0a8fb37 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp @@ -6,13 +6,21 @@ #include "compiler/translator/OutputESSL.h" -TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, +TOutputESSL::TOutputESSL(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable, - int shaderVersion) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion) + NameMap &nameMap, + TSymbolTable &symbolTable, + int shaderVersion, + bool forceHighp) + : TOutputGLSLBase(objSink, + clampingStrategy, + hashFunction, + nameMap, + symbolTable, + shaderVersion, + SH_ESSL_OUTPUT), + mForceHighp(forceHighp) { } @@ -22,6 +30,9 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision) return false; TInfoSinkBase& out = objSink(); - out << getPrecisionString(precision); + if (mForceHighp) + out << getPrecisionString(EbpHigh); + else + out << getPrecisionString(precision); return true; } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h index 8a567fb8aa..813f1e944b 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_ -#define CROSSCOMPILERGLSL_OUTPUTESSL_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTESSL_H_ #include "compiler/translator/OutputGLSLBase.h" @@ -17,10 +17,13 @@ public: ShHashFunction64 hashFunction, NameMap& nameMap, TSymbolTable& symbolTable, - int shaderVersion); + int shaderVersion, + bool forceHighp); protected: virtual bool writeVariablePrecision(TPrecision precision); +private: + bool mForceHighp; }; -#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp index eb7cbb4ae8..9badf0e2fc 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp @@ -11,8 +11,15 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, ShHashFunction64 hashFunction, NameMap& nameMap, TSymbolTable& symbolTable, - int shaderVersion) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion) + int shaderVersion, + ShShaderOutput output) + : TOutputGLSLBase(objSink, + clampingStrategy, + hashFunction, + nameMap, + symbolTable, + shaderVersion, + output) { } @@ -21,21 +28,30 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision) return false; } -void TOutputGLSL::visitSymbol(TIntermSymbol* node) +void TOutputGLSL::visitSymbol(TIntermSymbol *node) { TInfoSinkBase& out = objSink(); - if (node->getSymbol() == "gl_FragDepthEXT") + const TString &symbol = node->getSymbol(); + if (symbol == "gl_FragDepthEXT") { out << "gl_FragDepth"; } + else if (symbol == "gl_FragColor" && getShaderOutput() == SH_GLSL_CORE_OUTPUT) + { + out << "webgl_FragColor"; + } + else if (symbol == "gl_FragData" && getShaderOutput() == SH_GLSL_CORE_OUTPUT) + { + out << "webgl_FragData"; + } else { TOutputGLSLBase::visitSymbol(node); } } -TString TOutputGLSL::translateTextureFunction(TString& name) +TString TOutputGLSL::translateTextureFunction(TString &name) { static const char *simpleRename[] = { "texture2DLodEXT", "texture2DLod", @@ -46,10 +62,30 @@ TString TOutputGLSL::translateTextureFunction(TString& name) "textureCubeGradEXT", "textureCubeGradARB", NULL, NULL }; + static const char *legacyToCoreRename[] = { + "texture2D", "texture", + "texture2DProj", "textureProj", + "texture2DLod", "textureLod", + "texture2DProjLod", "textureProjLod", + "textureCube", "texture", + "textureCubeLod", "textureLod", + // Extensions + "texture2DLodEXT", "textureLod", + "texture2DProjLodEXT", "textureProjLod", + "textureCubeLodEXT", "textureLod", + "texture2DGradEXT", "textureGrad", + "texture2DProjGradEXT", "textureProjGrad", + "textureCubeGradEXT", "textureGrad", + NULL, NULL + }; + const char **mapping = (getShaderOutput() == SH_GLSL_CORE_OUTPUT) ? + legacyToCoreRename : simpleRename; - for (int i = 0; simpleRename[i] != NULL; i += 2) { - if (name == simpleRename[i]) { - return simpleRename[i+1]; + for (int i = 0; mapping[i] != NULL; i += 2) + { + if (name == mapping[i]) + { + return mapping[i+1]; } } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h index bceebe397d..21b2d079d3 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h @@ -4,25 +4,26 @@ // found in the LICENSE file. // -#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_ -#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_ #include "compiler/translator/OutputGLSLBase.h" class TOutputGLSL : public TOutputGLSLBase { -public: + public: TOutputGLSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap& nameMap, TSymbolTable& symbolTable, - int shaderVersion); + int shaderVersion, + ShShaderOutput output); -protected: + protected: virtual bool writeVariablePrecision(TPrecision); virtual void visitSymbol(TIntermSymbol* node); virtual TString translateTextureFunction(TString& name); }; -#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index ed590967b1..4bb6305d05 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -36,8 +36,17 @@ bool isSingleStatement(TIntermNode *node) { return false; } + else if (node->getAsSwitchNode()) + { + return false; + } + else if (node->getAsCaseNode()) + { + return false; + } return true; } + } // namespace TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, @@ -45,7 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable &symbolTable, - int shaderVersion) + int shaderVersion, + ShShaderOutput output) : TIntermTraverser(true, true, true), mObjSink(objSink), mDeclaringVariables(false), @@ -53,7 +63,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, mHashFunction(hashFunction), mNameMap(nameMap), mSymbolTable(symbolTable), - mShaderVersion(shaderVersion) + mShaderVersion(shaderVersion), + mOutput(output) { } @@ -83,7 +94,34 @@ void TOutputGLSLBase::writeVariableType(const TType &type) TQualifier qualifier = type.getQualifier(); if (qualifier != EvqTemporary && qualifier != EvqGlobal) { - out << type.getQualifierString() << " "; + if (mOutput == SH_GLSL_CORE_OUTPUT) + { + switch (qualifier) + { + case EvqAttribute: + out << "in" << " "; + break; + case EvqVaryingIn: + out << "in" << " "; + break; + case EvqVaryingOut: + out << "out" << " "; + break; + case EvqInvariantVaryingIn: + out << "invariant in" << " "; + break; + case EvqInvariantVaryingOut: + out << "invariant out" << " "; + break; + default: + out << type.getQualifierString() << " "; + break; + } + } + else + { + out << type.getQualifierString() << " "; + } } // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) @@ -166,6 +204,9 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion( case EbtInt: out << pConstUnion->getIConst(); break; + case EbtUInt: + out << pConstUnion->getUConst() << "u"; + break; case EbtBool: out << pConstUnion->getBConst(); break; @@ -223,6 +264,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; + case EOpIModAssign: + writeTriplet(visit, "(", " %= ", ")"); + break; // Notice the fall-through. case EOpMulAssign: case EOpVectorTimesMatrixAssign: @@ -231,6 +275,21 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpMatrixTimesMatrixAssign: writeTriplet(visit, "(", " *= ", ")"); break; + case EOpBitShiftLeftAssign: + writeTriplet(visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + writeTriplet(visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + writeTriplet(visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + writeTriplet(visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + writeTriplet(visit, "(", " |= ", ")"); + break; case EOpIndexDirect: writeTriplet(visit, NULL, "[", "]"); @@ -340,9 +399,25 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; - case EOpMod: - UNIMPLEMENTED(); + case EOpIMod: + writeTriplet(visit, "(", " % ", ")"); + break; + case EOpBitShiftLeft: + writeTriplet(visit, "(", " << ", ")"); break; + case EOpBitShiftRight: + writeTriplet(visit, "(", " >> ", ")"); + break; + case EOpBitwiseAnd: + writeTriplet(visit, "(", " & ", ")"); + break; + case EOpBitwiseXor: + writeTriplet(visit, "(", " ^ ", ")"); + break; + case EOpBitwiseOr: + writeTriplet(visit, "(", " | ", ")"); + break; + case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; @@ -398,6 +473,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) case EOpPositive: preString = "(+"; break; case EOpVectorLogicalNot: preString = "not("; break; case EOpLogicalNot: preString = "(!"; break; + case EOpBitwiseNot: preString = "(~"; break; case EOpPostIncrement: preString = "("; postString = "++)"; break; case EOpPostDecrement: preString = "("; postString = "--)"; break; @@ -429,6 +505,25 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) preString = "atan("; break; + case EOpSinh: + preString = "sinh("; + break; + case EOpCosh: + preString = "cosh("; + break; + case EOpTanh: + preString = "tanh("; + break; + case EOpAsinh: + preString = "asinh("; + break; + case EOpAcosh: + preString = "acosh("; + break; + case EOpAtanh: + preString = "atanh("; + break; + case EOpExp: preString = "exp("; break; @@ -457,12 +552,59 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) case EOpFloor: preString = "floor("; break; + case EOpTrunc: + preString = "trunc("; + break; + case EOpRound: + preString = "round("; + break; + case EOpRoundEven: + preString = "roundEven("; + break; case EOpCeil: preString = "ceil("; break; case EOpFract: preString = "fract("; break; + case EOpIsNan: + preString = "isnan("; + break; + case EOpIsInf: + preString = "isinf("; + break; + + case EOpFloatBitsToInt: + preString = "floatBitsToInt("; + break; + case EOpFloatBitsToUint: + preString = "floatBitsToUint("; + break; + case EOpIntBitsToFloat: + preString = "intBitsToFloat("; + break; + case EOpUintBitsToFloat: + preString = "uintBitsToFloat("; + break; + + case EOpPackSnorm2x16: + preString = "packSnorm2x16("; + break; + case EOpPackUnorm2x16: + preString = "packUnorm2x16("; + break; + case EOpPackHalf2x16: + preString = "packHalf2x16("; + break; + case EOpUnpackSnorm2x16: + preString = "unpackSnorm2x16("; + break; + case EOpUnpackUnorm2x16: + preString = "unpackUnorm2x16("; + break; + case EOpUnpackHalf2x16: + preString = "unpackHalf2x16("; + break; case EOpLength: preString = "length("; @@ -481,6 +623,16 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) preString = "fwidth("; break; + case EOpTranspose: + preString = "transpose("; + break; + case EOpDeterminant: + preString = "determinant("; + break; + case EOpInverse: + preString = "inverse("; + break; + case EOpAny: preString = "any("; break; @@ -536,6 +688,36 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node) return false; } +bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node) +{ + if (node->getStatementList()) + { + writeTriplet(visit, "switch (", ") ", nullptr); + // The curly braces get written when visiting the statementList aggregate + } + else + { + // No statementList, so it won't output curly braces + writeTriplet(visit, "switch (", ") {", "}\n"); + } + return true; +} + +bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) +{ + if (node->hasCondition()) + { + writeTriplet(visit, "case (", nullptr, "):\n"); + return true; + } + else + { + TInfoSinkBase &out = objSink(); + out << "default:\n"; + return false; + } +} + bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; @@ -555,11 +737,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); iter != node->getSequence()->end(); ++iter) { - TIntermNode *node = *iter; - ASSERT(node != NULL); - node->traverse(this); + TIntermNode *curNode = *iter; + ASSERT(curNode != NULL); + curNode->traverse(this); - if (isSingleStatement(node)) + if (isSingleStatement(curNode)) out << ";\n"; } decrementDepth(); @@ -622,6 +804,15 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) else out << ")"; break; + case EOpInternalFunctionCall: + // Function call to an internal helper function. + if (visit == PreVisit) + out << node->getName() << "("; + else if (visit == InVisit) + out << ", "; + else + out << ")"; + break; case EOpParameters: // Function parameters. ASSERT(visit == PreVisit); @@ -724,6 +915,10 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) } break; + case EOpOuterProduct: + writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction); + break; + case EOpLessThan: writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction); break; @@ -749,6 +944,9 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMod: writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); break; + case EOpModf: + writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction); + break; case EOpPow: writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction); break; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index e5174f5660..4e66059c21 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ -#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ +#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ #include <set> @@ -21,7 +21,13 @@ class TOutputGLSLBase : public TIntermTraverser ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable& symbolTable, - int shaderVersion); + int shaderVersion, + ShShaderOutput output); + + ShShaderOutput getShaderOutput() const + { + return mOutput; + } protected: TInfoSinkBase &objSink() { return mObjSink; } @@ -37,6 +43,8 @@ class TOutputGLSLBase : public TIntermTraverser virtual bool visitBinary(Visit visit, TIntermBinary *node); virtual bool visitUnary(Visit visit, TIntermUnary *node); virtual bool visitSelection(Visit visit, TIntermSelection *node); + virtual bool visitSwitch(Visit visit, TIntermSwitch *node); + virtual bool visitCase(Visit visit, TIntermCase *node); virtual bool visitAggregate(Visit visit, TIntermAggregate *node); virtual bool visitLoop(Visit visit, TIntermLoop *node); virtual bool visitBranch(Visit visit, TIntermBranch *node); @@ -78,6 +86,8 @@ class TOutputGLSLBase : public TIntermTraverser TSymbolTable &mSymbolTable; const int mShaderVersion; + + ShShaderOutput mOutput; }; -#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index 30bbbff0f5..94225b81c4 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -6,26 +6,29 @@ #include "compiler/translator/OutputHLSL.h" +#include <algorithm> +#include <cfloat> +#include <stdio.h> + #include "common/angleutils.h" #include "common/utilities.h" -#include "common/blocklayout.h" -#include "compiler/translator/compilerdebug.h" -#include "compiler/translator/InfoSink.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" #include "compiler/translator/DetectDiscontinuity.h" -#include "compiler/translator/SearchSymbol.h" -#include "compiler/translator/UnfoldShortCircuit.h" #include "compiler/translator/FlagStd140Structs.h" +#include "compiler/translator/InfoSink.h" #include "compiler/translator/NodeSearch.h" +#include "compiler/translator/RemoveSwitchFallThrough.h" #include "compiler/translator/RewriteElseBlocks.h" -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/util.h" -#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/SearchSymbol.h" #include "compiler/translator/StructureHLSL.h" #include "compiler/translator/TranslatorHLSL.h" - -#include <algorithm> -#include <cfloat> -#include <stdio.h> +#include "compiler/translator/UnfoldShortCircuit.h" +#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/blocklayout.h" +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/util.h" namespace sh { @@ -94,12 +97,21 @@ bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const return false; } -OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) +OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, ShShaderOutput outputType, + int numRenderTargets, const std::vector<Uniform> &uniforms, + int compileOptions) : TIntermTraverser(true, true, true), - mContext(context), - mOutputType(parentTranslator->getOutputType()) + mShaderType(shaderType), + mShaderVersion(shaderVersion), + mExtensionBehavior(extensionBehavior), + mSourcePath(sourcePath), + mOutputType(outputType), + mNumRenderTargets(numRenderTargets), + mCompileOptions(compileOptions) { - mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); + mUnfoldShortCircuit = new UnfoldShortCircuit(this); mInsideFunction = false; mUsesFragColor = false; @@ -109,28 +121,12 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) mUsesPointCoord = false; mUsesFrontFacing = false; mUsesPointSize = false; + mUsesInstanceID = false; mUsesFragDepth = false; mUsesXor = false; - mUsesMod1 = false; - mUsesMod2v = false; - mUsesMod2f = false; - mUsesMod3v = false; - mUsesMod3f = false; - mUsesMod4v = false; - mUsesMod4f = false; - mUsesFaceforward1 = false; - mUsesFaceforward2 = false; - mUsesFaceforward3 = false; - mUsesFaceforward4 = false; - mUsesAtan2_1 = false; - mUsesAtan2_2 = false; - mUsesAtan2_3 = false; - mUsesAtan2_4 = false; mUsesDiscardRewriting = false; mUsesNestedBreak = false; - - const ShBuiltInResources &resources = parentTranslator->getResources(); - mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; + mRequiresIEEEStrictCompiling = false; mUniqueIndex = 0; @@ -143,20 +139,14 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) mExcessiveLoopIndex = NULL; mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator); + mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms); if (mOutputType == SH_HLSL9_OUTPUT) { - if (mContext.shaderType == GL_FRAGMENT_SHADER) - { - // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront - mUniformHLSL->reserveUniformRegisters(3); - } - else - { - // Reserve registers for dx_DepthRange and dx_ViewAdjust - mUniformHLSL->reserveUniformRegisters(2); - } + // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront. + // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and dx_ViewAdjust. + // In both cases total 3 uniform registers need to be reserved. + mUniformHLSL->reserveUniformRegisters(3); } // Reserve registers for the default uniform block and driver constants @@ -168,27 +158,55 @@ OutputHLSL::~OutputHLSL() SafeDelete(mUnfoldShortCircuit); SafeDelete(mStructureHLSL); SafeDelete(mUniformHLSL); + for (auto it = mStructEqualityFunctions.begin(); it != mStructEqualityFunctions.end(); ++it) + { + SafeDelete(*it); + } + for (auto it = mArrayEqualityFunctions.begin(); it != mArrayEqualityFunctions.end(); ++it) + { + SafeDelete(*it); + } } -void OutputHLSL::output() +void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) { - mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); - mContainsAnyLoop = containsAnyLoop(mContext.treeRoot); - const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot); + mContainsLoopDiscontinuity = mShaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(treeRoot); + mContainsAnyLoop = containsAnyLoop(treeRoot); + const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(treeRoot); makeFlaggedStructMaps(flaggedStructs); // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which // use a vertex attribute as a condition, and some related computation in the else block. - if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == GL_VERTEX_SHADER) + if (mOutputType == SH_HLSL9_OUTPUT && mShaderType == GL_VERTEX_SHADER) + { + RewriteElseBlocks(treeRoot); + } + + BuiltInFunctionEmulator builtInFunctionEmulator; + InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator); + builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot); + + // Output the body and footer first to determine what has to go in the header + mInfoSinkStack.push(&mBody); + treeRoot->traverse(this); + mInfoSinkStack.pop(); + + mInfoSinkStack.push(&mFooter); + if (!mDeferredGlobalInitializers.empty()) { - RewriteElseBlocks(mContext.treeRoot); + writeDeferredGlobalInitializers(mFooter); } + mInfoSinkStack.pop(); + + mInfoSinkStack.push(&mHeader); + header(&builtInFunctionEmulator); + mInfoSinkStack.pop(); - mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header - header(); + objSink << mHeader.c_str(); + objSink << mBody.c_str(); + objSink << mFooter.c_str(); - mContext.infoSink().obj << mHeader.c_str(); - mContext.infoSink().obj << mBody.c_str(); + builtInFunctionEmulator.Cleanup(); } void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs) @@ -197,10 +215,14 @@ void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flagge { TIntermTyped *flaggedNode = flaggedStructs[structIndex]; + TInfoSinkBase structInfoSink; + mInfoSinkStack.push(&structInfoSink); + // This will mark the necessary block elements as referenced flaggedNode->traverse(this); - TString structName(mBody.c_str()); - mBody.erase(); + + TString structName(structInfoSink.c_str()); + mInfoSinkStack.pop(); mFlaggedStructOriginalNames[flaggedNode] = structName; @@ -213,11 +235,6 @@ void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flagge } } -TInfoSinkBase &OutputHLSL::getBodyStream() -{ - return mBody; -} - const std::map<std::string, unsigned int> &OutputHLSL::getInterfaceBlockRegisterMap() const { return mUniformHLSL->getInterfaceBlockRegisterMap(); @@ -277,9 +294,9 @@ TString OutputHLSL::structInitializerString(int indent, const TStructure &struct return init; } -void OutputHLSL::header() +void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator) { - TInfoSinkBase &out = mHeader; + TInfoSinkBase &out = getInfoSink(); TString varyings; TString attributes; @@ -320,6 +337,23 @@ void OutputHLSL::header() out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms); out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks); + if (!mEqualityFunctions.empty()) + { + out << "\n// Equality functions\n\n"; + for (auto it = mEqualityFunctions.cbegin(); it != mEqualityFunctions.cend(); ++it) + { + out << (*it)->functionDefinition << "\n"; + } + } + if (!mArrayAssignmentFunctions.empty()) + { + out << "\n// Assignment functions\n\n"; + for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it) + { + out << it->functionDefinition << "\n"; + } + } + if (mUsesDiscardRewriting) { out << "#define ANGLE_USES_DISCARD_REWRITING\n"; @@ -330,6 +364,11 @@ void OutputHLSL::header() out << "#define ANGLE_USES_NESTED_BREAK\n"; } + if (mRequiresIEEEStrictCompiling) + { + out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n"; + } + out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" "#define LOOP [loop]\n" "#define FLATTEN [flatten]\n" @@ -338,16 +377,16 @@ void OutputHLSL::header() "#define FLATTEN\n" "#endif\n"; - if (mContext.shaderType == GL_FRAGMENT_SHADER) + if (mShaderType == GL_FRAGMENT_SHADER) { - TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); - const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); + TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers"); + const bool usingMRTExtension = (iter != mExtensionBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire)); out << "// Varyings\n"; out << varyings; out << "\n"; - if (mContext.getShaderVersion() >= 300) + if (mShaderVersion >= 300) { for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++) { @@ -493,6 +532,11 @@ void OutputHLSL::header() out << "static float gl_PointSize = float(1);\n"; } + if (mUsesInstanceID) + { + out << "static int gl_InstanceID;"; + } + out << "\n" "// Varyings\n"; out << varyings; @@ -511,14 +555,22 @@ void OutputHLSL::header() if (mOutputType == SH_HLSL11_OUTPUT) { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + if (mUsesDepthRange) { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n" - " float3 dx_DepthRange : packoffset(c0);\n" - "};\n" - "\n"; + out << " float3 dx_DepthRange : packoffset(c0);\n"; } + + // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 shaders. + // However, we declare it for all shaders (including Feature Level 10+). + // The bytecode is the same whether we declare it or not, since D3DCompiler removes it if it's unused. + out << " float4 dx_ViewAdjust : packoffset(c1);\n"; + out << " float2 dx_ViewCoords : packoffset(c2);\n"; + + out << "};\n" + "\n"; } else { @@ -527,7 +579,8 @@ void OutputHLSL::header() out << "uniform float3 dx_DepthRange : register(c0);\n"; } - out << "uniform float4 dx_ViewAdjust : register(c1);\n" + out << "uniform float4 dx_ViewAdjust : register(c1);\n"; + out << "uniform float2 dx_ViewCoords : register(c2);\n" "\n"; } @@ -980,7 +1033,15 @@ void OutputHLSL::header() } else if (IsShadowSampler(textureFunction->sampler)) { - out << "x.SampleCmp(s, "; + switch(textureFunction->method) + { + case TextureFunction::IMPLICIT: out << "x.SampleCmp(s, "; break; + case TextureFunction::BIAS: out << "x.SampleCmp(s, "; break; + case TextureFunction::LOD: out << "x.SampleCmp(s, "; break; + case TextureFunction::LOD0: out << "x.SampleCmpLevelZero(s, "; break; + case TextureFunction::LOD0BIAS: out << "x.SampleCmpLevelZero(s, "; break; + default: UNREACHABLE(); + } } else { @@ -1111,11 +1172,20 @@ void OutputHLSL::header() else if (IsShadowSampler(textureFunction->sampler)) { // Compare value - switch(textureFunction->coords) + if (textureFunction->proj) { - case 3: out << "), t.z"; break; - case 4: out << "), t.w"; break; - default: UNREACHABLE(); + // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: + // The resulting third component of P' in the shadow forms is used as Dref + out << "), t.z" << proj; + } + else + { + switch(textureFunction->coords) + { + case 3: out << "), t.z"; break; + case 4: out << "), t.w"; break; + default: UNREACHABLE(); + } } } else @@ -1131,11 +1201,20 @@ void OutputHLSL::header() else if (IsShadowSampler(textureFunction->sampler)) { // Compare value - switch(textureFunction->coords) + if (textureFunction->proj) { - case 3: out << "), t.z"; break; - case 4: out << "), t.w"; break; - default: UNREACHABLE(); + // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: + // The resulting third component of P' in the shadow forms is used as Dref + out << "), t.z" << proj; + } + else + { + switch(textureFunction->coords) + { + case 3: out << "), t.z"; break; + case 4: out << "), t.w"; break; + default: UNREACHABLE(); + } } } else @@ -1205,179 +1284,12 @@ void OutputHLSL::header() "\n"; } - if (mUsesMod1) - { - out << "float mod(float x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod2v) - { - out << "float2 mod(float2 x, float2 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod2f) - { - out << "float2 mod(float2 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod3v) - { - out << "float3 mod(float3 x, float3 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod3f) - { - out << "float3 mod(float3 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod4v) - { - out << "float4 mod(float4 x, float4 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod4f) - { - out << "float4 mod(float4 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward1) - { - out << "float faceforward(float N, float I, float Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward2) - { - out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward3) - { - out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward4) - { - out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesAtan2_1) - { - out << "float atanyx(float y, float x)\n" - "{\n" - " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN - " return atan2(y, x);\n" - "}\n"; - } - - if (mUsesAtan2_2) - { - out << "float2 atanyx(float2 y, float2 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" - "}\n"; - } - - if (mUsesAtan2_3) - { - out << "float3 atanyx(float3 y, float3 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" - "}\n"; - } - - if (mUsesAtan2_4) - { - out << "float4 atanyx(float4 y, float4 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" - " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" - "}\n"; - } + builtInFunctionEmulator->OutputEmulatedFunctions(out); } void OutputHLSL::visitSymbol(TIntermSymbol *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); // Handle accessing std140 structs by value if (mFlaggedStructMappedNames.count(node) > 0) @@ -1458,6 +1370,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesPointSize = true; out << name; } + else if (qualifier == EvqInstanceID) + { + mUsesInstanceID = true; + out << name; + } else if (name == "gl_FragDepthEXT") { mUsesFragDepth = true; @@ -1476,12 +1393,51 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) void OutputHLSL::visitRaw(TIntermRaw *node) { - mBody << node->getRawText(); + getInfoSink() << node->getRawText(); +} + +void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out) +{ + if (type.isScalar() && !type.isArray()) + { + if (op == EOpEqual) + { + outputTriplet(visit, "(", " == ", ")", out); + } + else + { + outputTriplet(visit, "(", " != ", ")", out); + } + } + else + { + if (visit == PreVisit && op == EOpNotEqual) + { + out << "!"; + } + + if (type.isArray()) + { + const TString &functionName = addArrayEqualityFunction(type); + outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out); + } + else if (type.getBasicType() == EbtStruct) + { + const TStructure &structure = *type.getStruct(); + const TString &functionName = addStructEqualityFunction(structure); + outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out); + } + else + { + ASSERT(type.isMatrix() || type.isVector()); + outputTriplet(visit, "all(", " == ", ")", out); + } + } } bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); // Handle accessing std140 structs by value if (mFlaggedStructMappedNames.count(node) > 0) @@ -1492,7 +1448,17 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) switch (node->getOp()) { - case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; + case EOpAssign: + if (node->getLeft()->isArray()) + { + const TString &functionName = addArrayAssignmentFunction(node->getType()); + outputTriplet(visit, (functionName + "(").c_str(), ", ", ")"); + } + else + { + outputTriplet(visit, "(", " = ", ")"); + } + break; case EOpInitialize: if (visit == PreVisit) { @@ -1502,22 +1468,21 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) // this to "float t = x, x = t;". TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); + ASSERT(symbolNode); TIntermTyped *expression = node->getRight(); - sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); - expression->traverse(&searchSymbol); - bool sameSymbol = searchSymbol.foundMatch(); - - if (sameSymbol) + // TODO (jmadill): do a 'deep' scan to know if an expression is statically const + if (symbolNode->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst) { - // Type already printed - out << "t" + str(mUniqueIndex) + " = "; - expression->traverse(this); - out << ", "; - symbolNode->traverse(this); - out << " = t" + str(mUniqueIndex); - - mUniqueIndex++; + // For variables which are not constant, defer their real initialization until + // after we initialize other globals: uniforms, attributes and varyings. + mDeferredGlobalInitializers.push_back(std::make_pair(symbolNode, expression)); + const TString &initString = initializer(node->getType()); + node->setRight(new TIntermRaw(node->getType(), initString)); + } + else if (writeSameSymbolInitializer(out, symbolNode, expression)) + { + // Skip initializing the rest of the expression return false; } } @@ -1554,16 +1519,22 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) } else if (visit == InVisit) { - out << " = mul("; + out << " = transpose(mul(transpose("; node->getLeft()->traverse(this); - out << ", "; + out << "), transpose("; } else { - out << "))"; + out << "))))"; } break; case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; + case EOpIModAssign: outputTriplet(visit, "(", " %= ", ")"); break; + case EOpBitShiftLeftAssign: outputTriplet(visit, "(", " <<= ", ")"); break; + case EOpBitShiftRightAssign: outputTriplet(visit, "(", " >>= ", ")"); break; + case EOpBitwiseAndAssign: outputTriplet(visit, "(", " &= ", ")"); break; + case EOpBitwiseXorAssign: outputTriplet(visit, "(", " ^= ", ")"); break; + case EOpBitwiseOrAssign: outputTriplet(visit, "(", " |= ", ")"); break; case EOpIndexDirect: { const TType& leftType = node->getLeft()->getType(); @@ -1651,65 +1622,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) case EOpSub: outputTriplet(visit, "(", " - ", ")"); break; case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; + case EOpIMod: outputTriplet(visit, "(", " % ", ")"); break; + case EOpBitShiftLeft: outputTriplet(visit, "(", " << ", ")"); break; + case EOpBitShiftRight: outputTriplet(visit, "(", " >> ", ")"); break; + case EOpBitwiseAnd: outputTriplet(visit, "(", " & ", ")"); break; + case EOpBitwiseXor: outputTriplet(visit, "(", " ^ ", ")"); break; + case EOpBitwiseOr: outputTriplet(visit, "(", " | ", ")"); break; case EOpEqual: case EOpNotEqual: - if (node->getLeft()->isScalar()) - { - if (node->getOp() == EOpEqual) - { - outputTriplet(visit, "(", " == ", ")"); - } - else - { - outputTriplet(visit, "(", " != ", ")"); - } - } - else if (node->getLeft()->getBasicType() == EbtStruct) - { - if (node->getOp() == EOpEqual) - { - out << "("; - } - else - { - out << "!("; - } - - const TStructure &structure = *node->getLeft()->getType().getStruct(); - const TFieldList &fields = structure.fields(); - - for (size_t i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - - node->getLeft()->traverse(this); - out << "." + DecorateField(field->name(), structure) + " == "; - node->getRight()->traverse(this); - out << "." + DecorateField(field->name(), structure); - - if (i < fields.size() - 1) - { - out << " && "; - } - } - - out << ")"; - - return false; - } - else - { - ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); - - if (node->getOp() == EOpEqual) - { - outputTriplet(visit, "all(", " == ", ")"); - } - else - { - outputTriplet(visit, "!all(", " == ", ")"); - } - } + outputEqual(visit, node->getLeft()->getType(), node->getOp(), out); break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; @@ -1760,6 +1681,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpPositive: outputTriplet(visit, "(+", "", ")"); break; case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpBitwiseNot: outputTriplet(visit, "(~", "", ")"); break; case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; @@ -1772,6 +1694,21 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break; case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break; case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break; + case EOpSinh: outputTriplet(visit, "sinh(", "", ")"); break; + case EOpCosh: outputTriplet(visit, "cosh(", "", ")"); break; + case EOpTanh: outputTriplet(visit, "tanh(", "", ")"); break; + case EOpAsinh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "asinh("); + break; + case EOpAcosh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "acosh("); + break; + case EOpAtanh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "atanh("); + break; case EOpExp: outputTriplet(visit, "exp(", "", ")"); break; case EOpLog: outputTriplet(visit, "log(", "", ")"); break; case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break; @@ -1781,8 +1718,47 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break; case EOpSign: outputTriplet(visit, "sign(", "", ")"); break; case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break; + case EOpTrunc: outputTriplet(visit, "trunc(", "", ")"); break; + case EOpRound: outputTriplet(visit, "round(", "", ")"); break; + case EOpRoundEven: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "roundEven("); + break; case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break; case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; + case EOpIsNan: + outputTriplet(visit, "isnan(", "", ")"); + mRequiresIEEEStrictCompiling = true; + break; + case EOpIsInf: outputTriplet(visit, "isinf(", "", ")"); break; + case EOpFloatBitsToInt: outputTriplet(visit, "asint(", "", ")"); break; + case EOpFloatBitsToUint: outputTriplet(visit, "asuint(", "", ")"); break; + case EOpIntBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break; + case EOpUintBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break; + case EOpPackSnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "packSnorm2x16("); + break; + case EOpPackUnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "packUnorm2x16("); + break; + case EOpPackHalf2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "packHalf2x16("); + break; + case EOpUnpackSnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "unpackSnorm2x16("); + break; + case EOpUnpackUnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "unpackUnorm2x16("); + break; + case EOpUnpackHalf2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "unpackHalf2x16("); + break; case EOpLength: outputTriplet(visit, "length(", "", ")"); break; case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; case EOpDFdx: @@ -1815,6 +1791,13 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) outputTriplet(visit, "fwidth(", "", ")"); } break; + case EOpTranspose: outputTriplet(visit, "transpose(", "", ")"); break; + case EOpDeterminant: outputTriplet(visit, "determinant(transpose(", "", "))"); break; + case EOpInverse: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "inverse("); + break; + case EOpAny: outputTriplet(visit, "any(", "", ")"); break; case EOpAll: outputTriplet(visit, "all(", "", ")"); break; default: UNREACHABLE(); @@ -1825,7 +1808,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); switch (node->getOp()) { @@ -1843,7 +1826,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) traverseStatements(*sit); - out << ";\n"; + // Don't output ; after case labels, they're terminated by : + // This is needed especially since outputting a ; after a case statement would turn empty + // case statements into non-empty case statements, disallowing fall-through from them. + if ((*sit)->getAsCaseNode() == nullptr) + out << ";\n"; } if (mInsideFunction) @@ -1871,11 +1858,12 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration { - for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) + for (auto it = sequence->cbegin(); it != sequence->cend(); ++it) { - if (isSingleStatement(*sit)) + const auto &seqElement = *it; + if (isSingleStatement(seqElement)) { - mUnfoldShortCircuit->traverse(*sit); + mUnfoldShortCircuit->traverse(seqElement); } if (!mInsideFunction) @@ -1885,7 +1873,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << TypeString(variable->getType()) + " "; - TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + TIntermSymbol *symbol = seqElement->getAsSymbolNode(); if (symbol) { @@ -1895,10 +1883,10 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else { - (*sit)->traverse(this); + seqElement->traverse(this); } - if (*sit != sequence->back()) + if (seqElement != sequence->back()) { out << ";\n"; } @@ -2149,7 +2137,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) bool bias = (arguments->size() > mandatoryArgumentCount); // Bias argument is optional - if (lod0 || mContext.shaderType == GL_VERTEX_SHADER) + if (lod0 || mShaderType == GL_VERTEX_SHADER) { if (bias) { @@ -2217,7 +2205,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { const TString &structName = StructNameString(*node->getType().getStruct()); mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence()); - outputTriplet(visit, structName + "_ctor(", ", ", ")"); + outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")"); } break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; @@ -2227,37 +2215,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; case EOpMod: - { - // We need to look at the number of components in both arguments - const int modValue = (*node->getSequence())[0]->getAsTyped()->getNominalSize() * 10 + - (*node->getSequence())[1]->getAsTyped()->getNominalSize(); - switch (modValue) - { - case 11: mUsesMod1 = true; break; - case 22: mUsesMod2v = true; break; - case 21: mUsesMod2f = true; break; - case 33: mUsesMod3v = true; break; - case 31: mUsesMod3f = true; break; - case 44: mUsesMod4v = true; break; - case 41: mUsesMod4f = true; break; - default: UNREACHABLE(); - } - - outputTriplet(visit, "mod(", ", ", ")"); - } + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "mod("); break; + case EOpModf: outputTriplet(visit, "modf(", ", ", ")"); break; case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; case EOpAtan: ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator - switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) - { - case 1: mUsesAtan2_1 = true; break; - case 2: mUsesAtan2_2 = true; break; - case 3: mUsesAtan2_3 = true; break; - case 4: mUsesAtan2_4 = true; break; - default: UNREACHABLE(); - } - outputTriplet(visit, "atanyx(", ", ", ")"); + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "atan("); break; case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; @@ -2269,21 +2235,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break; case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; case EOpFaceForward: - { - switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument - { - case 1: mUsesFaceforward1 = true; break; - case 2: mUsesFaceforward2 = true; break; - case 3: mUsesFaceforward3 = true; break; - case 4: mUsesFaceforward4 = true; break; - default: UNREACHABLE(); - } - - outputTriplet(visit, "faceforward(", ", ", ")"); - } + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "faceforward("); break; case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break; case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break; + case EOpOuterProduct: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "outerProduct("); + break; case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; default: UNREACHABLE(); } @@ -2293,7 +2253,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); if (node->usesTernaryOperator()) { @@ -2307,7 +2267,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) // 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) + if (mShaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop) { out << "FLATTEN "; } @@ -2361,6 +2321,37 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) return false; } +bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node) +{ + if (node->getStatementList()) + { + node->setStatementList(RemoveSwitchFallThrough::removeFallThrough(node->getStatementList())); + outputTriplet(visit, "switch (", ") ", ""); + // The curly braces get written when visiting the statementList aggregate + } + else + { + // No statementList, so it won't output curly braces + outputTriplet(visit, "switch (", ") {", "}\n"); + } + return true; +} + +bool OutputHLSL::visitCase(Visit visit, TIntermCase *node) +{ + if (node->hasCondition()) + { + outputTriplet(visit, "case (", "", "):\n"); + return true; + } + else + { + TInfoSinkBase &out = getInfoSink(); + out << "default:\n"; + return false; + } +} + void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) { writeConstantUnion(node->getType(), node->getUnionArrayPointer()); @@ -2388,7 +2379,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) } } - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); if (node->getType() == ELoopDoWhile) { @@ -2454,7 +2445,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); switch (node->getFlowOp()) { @@ -2556,7 +2547,7 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node) bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { const int MAX_LOOP_ITERATIONS = 254; - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); // Parse loops of the form: // for(int index = initial; index [comparator] limit; index += increment) @@ -2756,10 +2747,8 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) return false; // Not handled as an excessive loop } -void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) +void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out) { - TInfoSinkBase &out = mBody; - if (visit == PreVisit) { out << preString; @@ -2774,19 +2763,26 @@ void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TStr } } +void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString) +{ + outputTriplet(visit, preString, inString, postString, getInfoSink()); +} + void OutputHLSL::outputLineDirective(int line) { - if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) + if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0)) { - mBody << "\n"; - mBody << "#line " << line; + TInfoSinkBase &out = getInfoSink(); + + out << "\n"; + out << "#line " << line; - if (mContext.sourcePath) + if (mSourcePath) { - mBody << " \"" << mContext.sourcePath << "\""; + out << " \"" << mSourcePath << "\""; } - mBody << "\n"; + out << "\n"; } } @@ -2832,15 +2828,15 @@ TString OutputHLSL::initializer(const TType &type) return "{" + string + "}"; } -void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters) +void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); if (visit == PreVisit) { mStructureHLSL->addConstructor(type, name, parameters); - out << name + "("; + out << name << "("; } else if (visit == InVisit) { @@ -2854,7 +2850,7 @@ void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); const TStructure* structure = type.getStruct(); if (structure) @@ -2912,4 +2908,209 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } +void OutputHLSL::writeEmulatedFunctionTriplet(Visit visit, const char *preStr) +{ + TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr); + outputTriplet(visit, preString.c_str(), ", ", ")"); +} + +bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression) +{ + sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); + expression->traverse(&searchSymbol); + + if (searchSymbol.foundMatch()) + { + // Type already printed + out << "t" + str(mUniqueIndex) + " = "; + expression->traverse(this); + out << ", "; + symbolNode->traverse(this); + out << " = t" + str(mUniqueIndex); + + mUniqueIndex++; + return true; + } + + return false; +} + +void OutputHLSL::writeDeferredGlobalInitializers(TInfoSinkBase &out) +{ + out << "#define ANGLE_USES_DEFERRED_INIT\n" + << "\n" + << "void initializeDeferredGlobals()\n" + << "{\n"; + + for (auto it = mDeferredGlobalInitializers.cbegin(); it != mDeferredGlobalInitializers.cend(); ++it) + { + const auto &deferredGlobal = *it; + TIntermSymbol *symbol = deferredGlobal.first; + TIntermTyped *expression = deferredGlobal.second; + ASSERT(symbol); + ASSERT(symbol->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst); + + out << " " << Decorate(symbol->getSymbol()) << " = "; + + if (!writeSameSymbolInitializer(out, symbol, expression)) + { + ASSERT(mInfoSinkStack.top() == &out); + expression->traverse(this); + } + + out << ";\n"; + } + + out << "}\n" + << "\n"; +} + +TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) +{ + const TFieldList &fields = structure.fields(); + + for (auto it = mStructEqualityFunctions.cbegin(); it != mStructEqualityFunctions.cend(); ++it) + { + auto *eqFunction = *it; + if (eqFunction->structure == &structure) + { + return eqFunction->functionName; + } + } + + const TString &structNameString = StructNameString(structure); + + StructEqualityFunction *function = new StructEqualityFunction(); + function->structure = &structure; + function->functionName = "angle_eq_" + structNameString; + + TInfoSinkBase fnOut; + + fnOut << "bool " << function->functionName << "(" << structNameString << " a, " << structNameString + " b)\n" + << "{\n" + " return "; + + for (size_t i = 0; i < fields.size(); i++) + { + const TField *field = fields[i]; + const TType *fieldType = field->type(); + + const TString &fieldNameA = "a." + Decorate(field->name()); + const TString &fieldNameB = "b." + Decorate(field->name()); + + if (i > 0) + { + fnOut << " && "; + } + + fnOut << "("; + outputEqual(PreVisit, *fieldType, EOpEqual, fnOut); + fnOut << fieldNameA; + outputEqual(InVisit, *fieldType, EOpEqual, fnOut); + fnOut << fieldNameB; + outputEqual(PostVisit, *fieldType, EOpEqual, fnOut); + fnOut << ")"; + } + + fnOut << ";\n" << "}\n"; + + function->functionDefinition = fnOut.c_str(); + + mStructEqualityFunctions.push_back(function); + mEqualityFunctions.push_back(function); + + return function->functionName; +} + +TString OutputHLSL::addArrayEqualityFunction(const TType& type) +{ + for (auto it = mArrayEqualityFunctions.cbegin(); it != mArrayEqualityFunctions.cend(); ++it) + { + const auto &eqFunction = *it; + if (eqFunction->type == type) + { + return eqFunction->functionName; + } + } + + const TString &typeName = TypeString(type); + + ArrayHelperFunction *function = new ArrayHelperFunction(); + function->type = type; + + TInfoSinkBase fnNameOut; + fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName; + function->functionName = fnNameOut.c_str(); + + TType nonArrayType = type; + nonArrayType.clearArrayness(); + + TInfoSinkBase fnOut; + + fnOut << "bool " << function->functionName << "(" + << typeName << " a[" << type.getArraySize() << "], " + << typeName << " b[" << type.getArraySize() << "])\n" + << "{\n" + " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n" + " {\n" + " if ("; + + outputEqual(PreVisit, nonArrayType, EOpNotEqual, fnOut); + fnOut << "a[i]"; + outputEqual(InVisit, nonArrayType, EOpNotEqual, fnOut); + fnOut << "b[i]"; + outputEqual(PostVisit, nonArrayType, EOpNotEqual, fnOut); + + fnOut << ") { return false; }\n" + " }\n" + " return true;\n" + "}\n"; + + function->functionDefinition = fnOut.c_str(); + + mArrayEqualityFunctions.push_back(function); + mEqualityFunctions.push_back(function); + + return function->functionName; +} + +TString OutputHLSL::addArrayAssignmentFunction(const TType& type) +{ + for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it) + { + const auto &assignFunction = *it; + if (assignFunction.type == type) + { + return assignFunction.functionName; + } + } + + const TString &typeName = TypeString(type); + + ArrayHelperFunction function; + function.type = type; + + TInfoSinkBase fnNameOut; + fnNameOut << "angle_assign_" << type.getArraySize() << "_" << typeName; + function.functionName = fnNameOut.c_str(); + + TInfoSinkBase fnOut; + + fnOut << "void " << function.functionName << "(out " + << typeName << " a[" << type.getArraySize() << "], " + << typeName << " b[" << type.getArraySize() << "])\n" + << "{\n" + " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n" + " {\n" + " a[i] = b[i];\n" + " }\n" + "}\n"; + + function.functionDefinition = fnOut.c_str(); + + mArrayAssignmentFunctions.push_back(function); + + return function.functionName; +} + } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index 5525e6eaa6..51da877c72 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -4,18 +4,20 @@ // found in the LICENSE file. // -#ifndef COMPILER_OUTPUTHLSL_H_ -#define COMPILER_OUTPUTHLSL_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_ #include <list> #include <set> #include <map> +#include <stack> #include "angle_gl.h" - #include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" +class BuiltInFunctionEmulator; + namespace sh { class UnfoldShortCircuit; @@ -27,20 +29,25 @@ typedef std::map<TString, TIntermSymbol*> ReferencedSymbols; class OutputHLSL : public TIntermTraverser { public: - OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator); - ~OutputHLSL(); + OutputHLSL(sh::GLenum shaderType, int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, ShShaderOutput outputType, + int numRenderTargets, const std::vector<Uniform> &uniforms, + int compileOptions); - void output(); + ~OutputHLSL(); - TInfoSinkBase &getBodyStream(); + void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const; const std::map<std::string, unsigned int> &getUniformRegisterMap() const; static TString initializer(const TType &type); + TInfoSinkBase &getInfoSink() { ASSERT(!mInfoSinkStack.empty()); return *mInfoSinkStack.top(); } + protected: - void header(); + void header(const BuiltInFunctionEmulator *builtInFunctionEmulator); // Visit AST nodes and output their code to the body stream void visitSymbol(TIntermSymbol*); @@ -49,6 +56,8 @@ class OutputHLSL : public TIntermTraverser bool visitBinary(Visit visit, TIntermBinary*); bool visitUnary(Visit visit, TIntermUnary*); bool visitSelection(Visit visit, TIntermSelection*); + bool visitSwitch(Visit visit, TIntermSwitch *); + bool visitCase(Visit visit, TIntermCase *); bool visitAggregate(Visit visit, TIntermAggregate*); bool visitLoop(Visit visit, TIntermLoop*); bool visitBranch(Visit visit, TIntermBranch*); @@ -56,16 +65,39 @@ class OutputHLSL : public TIntermTraverser void traverseStatements(TIntermNode *node); bool isSingleStatement(TIntermNode *node); bool handleExcessiveLoop(TIntermLoop *node); - void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString); + + // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString. + void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out); + void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString); void outputLineDirective(int line); TString argumentString(const TIntermSymbol *symbol); int vectorSize(const TType &type) const; - void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters); + // Emit constructor. Called with literal names so using const char* instead of TString. + void outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); - TParseContext &mContext; + void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out); + + void writeEmulatedFunctionTriplet(Visit visit, const char *preStr); + void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs); + + // Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting) + bool writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression); + void writeDeferredGlobalInitializers(TInfoSinkBase &out); + + // Returns the function name + TString addStructEqualityFunction(const TStructure &structure); + TString addArrayEqualityFunction(const TType &type); + TString addArrayAssignmentFunction(const TType &type); + + sh::GLenum mShaderType; + int mShaderVersion; + const TExtensionBehavior &mExtensionBehavior; + const char *mSourcePath; const ShShaderOutput mOutputType; + int mCompileOptions; + UnfoldShortCircuit *mUnfoldShortCircuit; bool mInsideFunction; @@ -74,6 +106,11 @@ class OutputHLSL : public TIntermTraverser TInfoSinkBase mBody; TInfoSinkBase mFooter; + // A stack is useful when we want to traverse in the header, or in helper functions, but not always + // write to the body. Instead use an InfoSink stack to keep our current state intact. + // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler. + std::stack<TInfoSinkBase *> mInfoSinkStack; + ReferencedSymbols mReferencedUniforms; ReferencedSymbols mReferencedInterfaceBlocks; ReferencedSymbols mReferencedAttributes; @@ -119,25 +156,13 @@ class OutputHLSL : public TIntermTraverser bool mUsesPointCoord; bool mUsesFrontFacing; bool mUsesPointSize; + bool mUsesInstanceID; bool mUsesFragDepth; bool mUsesXor; - bool mUsesMod1; - bool mUsesMod2v; - bool mUsesMod2f; - bool mUsesMod3v; - bool mUsesMod3f; - bool mUsesMod4v; - bool mUsesMod4f; - bool mUsesFaceforward1; - bool mUsesFaceforward2; - bool mUsesFaceforward3; - bool mUsesFaceforward4; - bool mUsesAtan2_1; - bool mUsesAtan2_2; - bool mUsesAtan2_3; - bool mUsesAtan2_4; bool mUsesDiscardRewriting; bool mUsesNestedBreak; + bool mRequiresIEEEStrictCompiling; + int mNumRenderTargets; @@ -156,9 +181,41 @@ class OutputHLSL : public TIntermTraverser std::map<TIntermTyped*, TString> mFlaggedStructMappedNames; std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames; - void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs); + // Some initializers use varyings, uniforms or attributes, thus we can't evaluate some variables + // at global static scope in HLSL. These variables depend on values which we retrieve from the + // shader input structure, which we set in the D3D main function. Instead, we can initialize + // these static globals after we initialize our other globals. + std::vector<std::pair<TIntermSymbol*, TIntermTyped*>> mDeferredGlobalInitializers; + + struct HelperFunction + { + TString functionName; + TString functionDefinition; + + virtual ~HelperFunction() {} + }; + + // A list of all equality comparison functions. It's important to preserve the order at + // which we add the functions, since nested structures call each other recursively, and + // structure equality functions may need to call array equality functions and vice versa. + // The ownership of the pointers is maintained by the type-specific arrays. + std::vector<HelperFunction*> mEqualityFunctions; + + struct StructEqualityFunction : public HelperFunction + { + const TStructure *structure; + }; + std::vector<StructEqualityFunction*> mStructEqualityFunctions; + + struct ArrayHelperFunction : public HelperFunction + { + TType type; + }; + std::vector<ArrayHelperFunction*> mArrayEqualityFunctions; + + std::vector<ArrayHelperFunction> mArrayAssignmentFunctions; }; } -#endif // COMPILER_OUTPUTHLSL_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 37969b5468..7ad3f817ad 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -9,8 +9,9 @@ #include <stdarg.h> #include <stdio.h> -#include "compiler/translator/glslang.h" #include "compiler/preprocessor/SourceLocation.h" +#include "compiler/translator/glslang.h" +#include "compiler/translator/ValidateSwitch.h" /////////////////////////////////////////////////////////////////////// // @@ -796,9 +797,24 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& ident bool sameScope = false; TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope); if (symbol == 0 || !sameScope) { - if (reservedErrorCheck(line, identifier)) - return true; - + bool needsReservedErrorCheck = true; + + // gl_LastFragData may be redeclared with a new precision qualifier + if (identifier.compare(0, 15, "gl_LastFragData") == 0) { + if (type.arraySize == static_cast<const TVariable*>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion))->getConstPointer()->getIConst()) { + if (TSymbol* builtInSymbol = symbolTable.findBuiltIn(identifier, shaderVersion)) { + needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension()); + } + } else { + error(line, "redeclaration of array with size != gl_MaxDrawBuffers", identifier.c_str()); + return true; + } + } + + if (needsReservedErrorCheck) + if (reservedErrorCheck(line, identifier)) + return true; + variable = new TVariable(&identifier, TType(type)); if (type.arraySize) @@ -976,6 +992,26 @@ bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const T return false; } +bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate) +{ + for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) + { + TQualifier qual = fnCandidate->getParam(i).type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) + { + TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped(); + if (lValueErrorCheck(node->getLine(), "assign", node)) + { + error(node->getLine(), + "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); + recover(); + return true; + } + } + } + return false; +} + bool TParseContext::supportsExtension(const char* extension) { const TExtensionBehavior& extbehavior = extensionBehavior(); @@ -1062,14 +1098,14 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int inputShaderVersion, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. // If a function is found, check for one with a matching argument list. - const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn); + const TSymbol* symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn); if (symbol == 0 || symbol->isFunction()) { - symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn); + symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn); } if (symbol == 0) { @@ -1162,7 +1198,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id if (qualifier != EvqConst) { TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); - intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); + intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line); if (intermNode == 0) { assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); return true; @@ -1375,7 +1411,7 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv recover(); return NULL; } - symbolTable.addInvariantVarying(*identifier); + symbolTable.addInvariantVarying(std::string(identifier->c_str())); const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); ASSERT(variable); const TType &type = variable->getType(); @@ -1605,7 +1641,7 @@ TFunction *TParseContext::addConstructorFunc(TPublicType publicType) // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) +TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) { TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); @@ -1633,13 +1669,21 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType } // Turn the argument list itself into a constructor - TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); - TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); + TIntermTyped *constConstructor = foldConstConstructor(constructor, *type); if (constConstructor) { return constConstructor; } + // Structs should not be precision qualified, the individual members may be. + // Built-in types on the other hand should be precision qualified. + if (op != EOpConstructStruct) + { + constructor->setPrecisionFromChildren(); + type->setPrecision(constructor->getPrecision()); + } + return constructor; } @@ -2028,9 +2072,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co recover(); } - if (indexExpression->getQualifier() == EvqConst) + TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); + + if (indexExpression->getQualifier() == EvqConst && indexConstantUnion) { - int index = indexExpression->getAsConstantUnion()->getIConst(0); + int index = indexConstantUnion->getIConst(0); if (index < 0) { std::stringstream infoStream; @@ -2091,7 +2137,7 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co index = baseExpression->getType().getNominalSize() - 1; } - indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); + indexConstantUnion->getUnionArrayPointer()->setIConst(index); indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); } } @@ -2520,7 +2566,10 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou TStructure* structure = new TStructure(structName, fieldList); TType* structureType = new TType(structure); + // Store a bool in the struct if we're at global scope, to allow us to + // skip the local struct scoping workaround in HLSL. structure->setUniqueId(TSymbolTable::nextUniqueId()); + structure->setAtGlobalScope(symbolTable.atGlobalLevel()); if (!structName->empty()) { @@ -2560,6 +2609,553 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou return publicType; } +TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc) +{ + TBasicType switchType = init->getBasicType(); + if ((switchType != EbtInt && switchType != EbtUInt) || + init->isMatrix() || + init->isArray() || + init->isVector()) + { + error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch"); + recover(); + return nullptr; + } + + if (statementList) + { + if (!ValidateSwitch::validate(switchType, this, statementList, loc)) + { + recover(); + return nullptr; + } + } + + TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc); + if (node == nullptr) + { + error(loc, "erroneous switch statement", "switch"); + recover(); + return nullptr; + } + return node; +} + +TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) +{ + if (mSwitchNestingLevel == 0) + { + error(loc, "case labels need to be inside switch statements", "case"); + recover(); + return nullptr; + } + if (condition == nullptr) + { + error(loc, "case label must have a condition", "case"); + recover(); + return nullptr; + } + if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) || + condition->isMatrix() || + condition->isArray() || + condition->isVector()) + { + error(condition->getLine(), "case label must be a scalar integer", "case"); + recover(); + } + TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); + if (conditionConst == nullptr) + { + error(condition->getLine(), "case label must be constant", "case"); + recover(); + } + TIntermCase *node = intermediate.addCase(condition, loc); + if (node == nullptr) + { + error(loc, "erroneous case statement", "case"); + recover(); + return nullptr; + } + return node; +} + +TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) +{ + if (mSwitchNestingLevel == 0) + { + error(loc, "default labels need to be inside switch statements", "default"); + recover(); + return nullptr; + } + TIntermCase *node = intermediate.addCase(nullptr, loc); + if (node == nullptr) + { + error(loc, "erroneous default statement", "default"); + recover(); + return nullptr; + } + return node; +} + +TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, + const TType *funcReturnType) +{ + if (child == nullptr) + { + return nullptr; + } + + switch (op) + { + case EOpLogicalNot: + if (child->getBasicType() != EbtBool || + child->isMatrix() || + child->isArray() || + child->isVector()) + { + return nullptr; + } + break; + case EOpBitwiseNot: + if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) || + child->isMatrix() || + child->isArray()) + { + return nullptr; + } + break; + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + case EOpPositive: + if (child->getBasicType() == EbtStruct || + child->getBasicType() == EbtBool || + child->isArray()) + { + return nullptr; + } + // Operators for built-ins are already type checked against their prototype. + default: + break; + } + + return intermediate.addUnaryMath(op, child, loc, funcReturnType); +} + +TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) +{ + TIntermTyped *node = createUnaryMath(op, child, loc, nullptr); + if (node == nullptr) + { + unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); + recover(); + return child; + } + return node; +} + +TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc) +{ + if (lValueErrorCheck(loc, GetOperatorString(op), child)) + recover(); + return addUnaryMath(op, child, loc); +} + +bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + if (left->isArray() || right->isArray()) + { + if (shaderVersion < 300) + { + error(loc, "Invalid operation for arrays", GetOperatorString(op)); + return false; + } + + if (left->isArray() != right->isArray()) + { + error(loc, "array / non-array mismatch", GetOperatorString(op)); + return false; + } + + switch (op) + { + case EOpEqual: + case EOpNotEqual: + case EOpAssign: + case EOpInitialize: + break; + default: + error(loc, "Invalid operation for arrays", GetOperatorString(op)); + return false; + } + if (left->getArraySize() != right->getArraySize()) + { + error(loc, "array size mismatch", GetOperatorString(op)); + return false; + } + } + + // Check ops which require integer / ivec parameters + bool isBitShift = false; + switch (op) + { + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + // Unsigned can be bit-shifted by signed and vice versa, but we need to + // check that the basic type is an integer type. + isBitShift = true; + if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) + { + return false; + } + break; + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + // It is enough to check the type of only one operand, since later it + // is checked that the operand types match. + if (!IsInteger(left->getBasicType())) + { + return false; + } + break; + default: + break; + } + + // GLSL ES 1.00 and 3.00 do not support implicit type casting. + // So the basic type should usually match. + if (!isBitShift && left->getBasicType() != right->getBasicType()) + { + return false; + } + + // Check that type sizes match exactly on ops that require that. + // Also check restrictions for structs that contain arrays or samplers. + switch(op) + { + case EOpAssign: + case EOpInitialize: + case EOpEqual: + case EOpNotEqual: + // ESSL 1.00 sections 5.7, 5.8, 5.9 + if (shaderVersion < 300 && left->getType().isStructureContainingArrays()) + { + error(loc, "undefined operation for structs containing arrays", GetOperatorString(op)); + return false; + } + // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7, + // we interpret the spec so that this extends to structs containing samplers, + // similarly to ESSL 1.00 spec. + if ((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) && + left->getType().isStructureContainingSamplers()) + { + error(loc, "undefined operation for structs containing samplers", GetOperatorString(op)); + return false; + } + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((left->getNominalSize() != right->getNominalSize()) || + (left->getSecondarySize() != right->getSecondarySize())) + { + return false; + } + default: + break; + } + + return true; +} + +TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + if (!binaryOpCommonCheck(op, left, right, loc)) + return nullptr; + + switch (op) + { + case EOpEqual: + case EOpNotEqual: + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + ASSERT(!left->isArray() && !right->isArray()); + if (left->isMatrix() || left->isVector() || + left->getBasicType() == EbtStruct) + { + return nullptr; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + ASSERT(!left->isArray() && !right->isArray()); + if (left->getBasicType() != EbtBool || + left->isMatrix() || left->isVector()) + { + return nullptr; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + ASSERT(!left->isArray() && !right->isArray()); + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) + { + return nullptr; + } + break; + case EOpIMod: + ASSERT(!left->isArray() && !right->isArray()); + // Note that this is only for the % operator, not for mod() + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) + { + return nullptr; + } + break; + // Note that for bitwise ops, type checking is done in promote() to + // share code between ops and compound assignment + default: + break; + } + + return intermediate.addBinaryMath(op, left, right, loc); +} + +TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); + if (node == 0) + { + binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString()); + recover(); + return left; + } + return node; +} + +TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); + if (node == 0) + { + binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString()); + recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), loc); + } + return node; +} + +TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + if (binaryOpCommonCheck(op, left, right, loc)) + { + return intermediate.addAssign(op, left, right, loc); + } + return nullptr; +} + +TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = createAssign(op, left, right, loc); + if (node == nullptr) + { + assignError(loc, "assign", left->getCompleteString(), right->getCompleteString()); + recover(); + return left; + } + return node; +} + +TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) +{ + switch (op) + { + case EOpContinue: + if (mLoopNestingLevel <= 0) + { + error(loc, "continue statement only allowed in loops", ""); + recover(); + } + break; + case EOpBreak: + if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0) + { + error(loc, "break statement only allowed in loops and switch statements", ""); + recover(); + } + break; + case EOpReturn: + if (currentFunctionType->getBasicType() != EbtVoid) + { + error(loc, "non-void function must return a value", "return"); + recover(); + } + break; + default: + // No checks for discard + break; + } + return intermediate.addBranch(op, loc); +} + +TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc) +{ + ASSERT(op == EOpReturn); + mFunctionReturnsValue = true; + if (currentFunctionType->getBasicType() == EbtVoid) + { + error(loc, "void function cannot return a value", "return"); + recover(); + } + else if (*currentFunctionType != returnValue->getType()) + { + error(loc, "function return is not matching type:", "return"); + recover(); + } + return intermediate.addBranch(op, returnValue, loc); +} + +TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node, + const TSourceLoc &loc, bool *fatalError) +{ + *fatalError = false; + TOperator op = fnCall->getBuiltInOp(); + TIntermTyped *callNode = nullptr; + + if (op != EOpNull) + { + // + // Then this should be a constructor. + // Don't go through the symbol table for constructors. + // Their parameters will be verified algorithmically. + // + TType type(EbtVoid, EbpUndefined); // use this to get the type back + if (!constructorErrorCheck(loc, node, *fnCall, op, &type)) + { + // + // It's a constructor, of type 'type'. + // + callNode = addConstructor(node, &type, op, fnCall, loc); + } + + if (callNode == nullptr) + { + recover(); + callNode = intermediate.setAggregateOperator(nullptr, op, loc); + } + callNode->setType(type); + } + else + { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = findFunction(loc, fnCall, shaderVersion, &builtIn); + if (fnCandidate) + { + // + // A declared function. + // + if (builtIn && !fnCandidate->getExtension().empty() && + extensionErrorCheck(loc, fnCandidate->getExtension())) + { + recover(); + } + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) + { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) + { + // + // Treat it like a built-in unary operator. + // + callNode = createUnaryMath(op, node->getAsTyped(), loc, &fnCandidate->getReturnType()); + if (callNode == nullptr) + { + std::stringstream extraInfoStream; + extraInfoStream << "built in unary operator function. Type: " + << static_cast<TIntermTyped*>(node)->getCompleteString(); + std::string extraInfo = extraInfoStream.str(); + error(node->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str()); + *fatalError = true; + return nullptr; + } + } + else + { + TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, op, loc); + aggregate->setType(fnCandidate->getReturnType()); + aggregate->setPrecisionFromChildren(); + callNode = aggregate; + + // Some built-in functions have out parameters too. + functionCallLValueErrorCheck(fnCandidate, aggregate); + } + } + else + { + // This is a real function call + + TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, EOpFunctionCall, loc); + 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) + aggregate->setUserDefined(); + aggregate->setName(fnCandidate->getMangledName()); + + // This needs to happen after the name is set + if (builtIn) + aggregate->setBuiltInFunctionPrecision(); + + callNode = aggregate; + + functionCallLValueErrorCheck(fnCandidate, aggregate); + } + } + else + { + // error message was put out by findFunction() + // Put on a dummy node for error recovery + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), loc); + recover(); + } + } + delete fnCall; + return callNode; +} + + // // Parse an array of strings using yyparse. // diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index 414c475cbb..b6a0f4a637 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef _PARSER_HELPER_INCLUDED_ -#define _PARSER_HELPER_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ +#define COMPILER_TRANSLATOR_PARSECONTEXT_H_ #include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" @@ -25,24 +25,25 @@ struct TMatrixFields { // they can be passed to the parser without needing a global. // struct TParseContext { - TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, TInfoSink& is, bool debugShaderPrecisionSupported) : intermediate(interm), symbolTable(symt), shaderType(type), shaderSpec(spec), compileOptions(options), - sourcePath(sourcePath), treeRoot(0), - loopNestingLevel(0), + mLoopNestingLevel(0), structNestingLevel(0), + mSwitchNestingLevel(0), currentFunctionType(NULL), - functionReturnsValue(false), + mFunctionReturnsValue(false), checksPrecisionErrors(checksPrecErrors), + fragmentPrecisionHigh(false), defaultMatrixPacking(EmpColumnMajor), defaultBlockStorage(EbsShared), diagnostics(is), shaderVersion(100), - directiveHandler(ext, diagnostics, shaderVersion), + directiveHandler(ext, diagnostics, shaderVersion, debugShaderPrecisionSupported), preprocessor(&diagnostics, &directiveHandler), scanner(NULL) { } TIntermediate& intermediate; // to hold and build a parse tree @@ -51,12 +52,12 @@ struct TParseContext { ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. int shaderVersion; int compileOptions; - const char* sourcePath; // Path of source file or NULL. TIntermNode* treeRoot; // root of parse tree being created - int loopNestingLevel; // 0 if outside all loops + int mLoopNestingLevel; // 0 if outside all loops int structNestingLevel; // incremented while parsing a struct declaration + int mSwitchNestingLevel; // 0 if outside all switch statements const TType* currentFunctionType; // the return type of the function that's currently being parsed - bool functionReturnsValue; // true if a non-void function has a return + bool mFunctionReturnsValue; // true if a non-void function has a return bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language. TLayoutMatrixPacking defaultMatrixPacking; @@ -110,6 +111,7 @@ struct TParseContext { bool extensionErrorCheck(const TSourceLoc& line, const TString&); bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); + bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); const TPragma& pragma() const { return directiveHandler.pragma(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } @@ -120,7 +122,7 @@ struct TParseContext { bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); - const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0); + const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int inputShaderVersion, bool *builtIn = 0); bool executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); @@ -136,7 +138,7 @@ struct TParseContext { TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); TFunction *addConstructorFunc(TPublicType publicType); - TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); + TIntermTyped* addConstructor(TIntermNode*, TType*, TOperator, TFunction*, const TSourceLoc&); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); @@ -164,9 +166,42 @@ struct TParseContext { void exitStructDeclaration(); bool structNestingErrorCheck(const TSourceLoc& line, const TField& field); + + TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); + TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); + TIntermCase *addDefault(const TSourceLoc &loc); + + TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &); + TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &); + TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &); + TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &); + TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); + + TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); + TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); + + TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node, + const TSourceLoc &loc, bool *fatalError); + + private: + TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); + TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); + // The funcReturnType parameter is expected to be non-null when the operation is a built-in function. + // It is expected to be null for other unary operators. + TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, + const TType *funcReturnType); + + // Return true if the checks pass + bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); }; int PaParseStrings(size_t count, const char* const string[], const int length[], TParseContext* context); -#endif // _PARSER_HELPER_INCLUDED_ +#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h index edd249c4d3..6cd8d30114 100644 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h +++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _POOLALLOC_INCLUDED_ -#define _POOLALLOC_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_ +#define COMPILER_TRANSLATOR_POOLALLOC_H_ #ifdef _DEBUG #define GUARD_BLOCKS // define to enable guard block sanity checking @@ -297,4 +297,4 @@ protected: TPoolAllocator* allocator; }; -#endif // _POOLALLOC_INCLUDED_ +#endif // COMPILER_TRANSLATOR_POOLALLOC_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h index 4a930a2962..57b1134970 100644 --- a/src/3rdparty/angle/src/compiler/translator/Pragma.h +++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PRAGMA_H_ -#define COMPILER_PRAGMA_H_ +#ifndef COMPILER_TRANSLATOR_PRAGMA_H_ +#define COMPILER_TRANSLATOR_PRAGMA_H_ struct TPragma { @@ -18,12 +18,15 @@ struct TPragma // 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) { } + // Precision emulation is turned on by default, but has no effect unless + // the extension is enabled. + TPragma() : optimize(true), debug(false), debugShaderPrecision(true) { } + TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) { } bool optimize; bool debug; + bool debugShaderPrecision; STDGL stdgl; }; -#endif // COMPILER_PRAGMA_H_ +#endif // COMPILER_TRANSLATOR_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp index 1f6fb75821..3d950aab5a 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -49,7 +49,7 @@ void TAliveTraverser::visitSymbol(TIntermSymbol* node) found = true; } -bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node) +bool TAliveTraverser::visitSelection(Visit, TIntermSelection*) { if (wasFound()) return false; diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h index 872a06f721..3e4f18012a 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h @@ -4,4 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_QUALIFIERALIVE_H_ +#define COMPILER_TRANSLATOR_QUALIFIERALIVE_H_ + bool QualifierWritten(TIntermNode* root, TQualifier); + +#endif // COMPILER_TRANSLATOR_QUALIFIERALIVE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h index ac87600347..2acd68be34 100644 --- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ -#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ +#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ +#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ #include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" @@ -37,4 +37,4 @@ class RegenerateStructNames : public TIntermTraverser std::set<int> mDeclaredGlobalStructs; }; -#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ +#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp new file mode 100644 index 0000000000..b278b53436 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp @@ -0,0 +1,157 @@ +// +// Copyright (c) 2002-2015 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 "compiler/translator/RemoveSwitchFallThrough.h" + +TIntermAggregate *RemoveSwitchFallThrough::removeFallThrough(TIntermAggregate *statementList) +{ + RemoveSwitchFallThrough rm(statementList); + ASSERT(statementList); + statementList->traverse(&rm); + bool lastStatementWasBreak = rm.mLastStatementWasBreak; + rm.mLastStatementWasBreak = true; + rm.handlePreviousCase(); + if (!lastStatementWasBreak) + { + TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr); + rm.mStatementListOut->getSequence()->push_back(finalBreak); + } + return rm.mStatementListOut; +} + +RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermAggregate *statementList) + : TIntermTraverser(true, false, false), + mStatementList(statementList), + mLastStatementWasBreak(false), + mPreviousCase(nullptr) +{ + mStatementListOut = new TIntermAggregate(); + mStatementListOut->setOp(EOpSequence); +} + +void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node) +{ + // Note that this assumes that switch statements which don't begin by a case statement + // have already been weeded out in validation. + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; +} + +void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node) +{ + // Conditions of case labels are not traversed, so this is some other constant + // Could be just a statement like "0;" + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; +} + +bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitSelection(Visit, TIntermSelection *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + // Don't go into nested switch statements + return false; +} + +void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex) +{ + for (size_t i = startIndex; i < sequence->size(); ++i) + { + mStatementListOut->getSequence()->push_back(sequence->at(i)); + } +} + +void RemoveSwitchFallThrough::handlePreviousCase() +{ + if (mPreviousCase) + mCasesSharingBreak.push_back(mPreviousCase); + if (mLastStatementWasBreak) + { + bool labelsWithNoStatements = true; + for (size_t i = 0; i < mCasesSharingBreak.size(); ++i) + { + if (mCasesSharingBreak.at(i)->getSequence()->size() > 1) + { + labelsWithNoStatements = false; + } + if (labelsWithNoStatements) + { + // Fall-through is allowed in case the label has no statements. + outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0); + } + else + { + // Include all the statements that this case can fall through under the same label. + for (size_t j = i; j < mCasesSharingBreak.size(); ++j) + { + size_t startIndex = j > i ? 1 : 0; // Add the label only from the first sequence. + outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex); + + } + } + } + mCasesSharingBreak.clear(); + } + mLastStatementWasBreak = false; + mPreviousCase = nullptr; +} + +bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node) +{ + handlePreviousCase(); + mPreviousCase = new TIntermAggregate(); + mPreviousCase->setOp(EOpSequence); + mPreviousCase->getSequence()->push_back(node); + // Don't traverse the condition of the case statement + return false; +} + +bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node) +{ + if (node != mStatementList) + { + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; + } + return true; +} + +bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node) +{ + mPreviousCase->getSequence()->push_back(node); + // TODO: Verify that accepting return or continue statements here doesn't cause problems. + mLastStatementWasBreak = true; + return false; +} diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h new file mode 100644 index 0000000000..db8699327c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2002-2015 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 COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ +#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ + +#include "compiler/translator/IntermNode.h" + +class RemoveSwitchFallThrough : public TIntermTraverser +{ + public: + // When given a statementList from a switch AST node, return an updated + // statementList that has fall-through removed. + static TIntermAggregate *removeFallThrough(TIntermAggregate *statementList); + + private: + RemoveSwitchFallThrough(TIntermAggregate *statementList); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitBinary(Visit, TIntermBinary *node) override; + bool visitUnary(Visit, TIntermUnary *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; + bool visitSwitch(Visit, TIntermSwitch *node) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; + bool visitLoop(Visit, TIntermLoop *node) override; + bool visitBranch(Visit, TIntermBranch *node) override; + + void outputSequence(TIntermSequence *sequence, size_t startIndex); + void handlePreviousCase(); + + TIntermAggregate *mStatementList; + TIntermAggregate *mStatementListOut; + bool mLastStatementWasBreak; + TIntermAggregate *mPreviousCase; + std::vector<TIntermAggregate *> mCasesSharingBreak; +}; + +#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp deleted file mode 100644 index 0cf6910aa2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2002-2010 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 "compiler/translator/IntermNode.h" -#include "compiler/translator/RemoveTree.h" - -// -// Code to delete the intermediate tree. -// -void RemoveAllTreeNodes(TIntermNode* root) -{ - std::queue<TIntermNode*> nodeQueue; - - nodeQueue.push(root); - - while (!nodeQueue.empty()) - { - TIntermNode *node = nodeQueue.front(); - nodeQueue.pop(); - - node->enqueueChildren(&nodeQueue); - - delete node; - } -} - diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h b/src/3rdparty/angle/src/compiler/translator/RemoveTree.h deleted file mode 100644 index 97a821679c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h +++ /dev/null @@ -1,7 +0,0 @@ -// -// Copyright (c) 2002-2010 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. -// - -void RemoveAllTreeNodes(TIntermNode*); diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h index d43e6ef7be..868e5d566b 100644 --- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_RENAME_FUNCTION -#define COMPILER_RENAME_FUNCTION +#ifndef COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ +#define COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ #include "compiler/translator/IntermNode.h" @@ -33,4 +33,4 @@ private: const TString mNewFunctionName; }; -#endif // COMPILER_RENAME_FUNCTION +#endif // COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h index d87baea0fe..5527d27f83 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -7,8 +7,8 @@ // all if-else blocks to if-if blocks. // -#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ -#define COMPILER_REWRITE_ELSE_BLOCKS_H_ +#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ +#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ #include "compiler/translator/IntermNode.h" @@ -19,4 +19,4 @@ void RewriteElseBlocks(TIntermNode *node); } -#endif // COMPILER_REWRITE_ELSE_BLOCKS_H_ +#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h index 7c6d09c1bb..0726ed4c64 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ -#define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ +#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ +#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ #include "compiler/translator/IntermNode.h" @@ -44,4 +44,4 @@ class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser bool mFragmentPrecisionHigh; }; -#endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ +#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp index f78c84e370..fb7a6cdb9b 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp @@ -9,7 +9,6 @@ #include "compiler/translator/SearchSymbol.h" #include "compiler/translator/InfoSink.h" -#include "compiler/translator/OutputHLSL.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h index 029ac30b9a..36d5191058 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h @@ -6,8 +6,8 @@ // SearchSymbol is an AST traverser to detect the use of a given symbol name // -#ifndef COMPILER_SEARCHSYMBOL_H_ -#define COMPILER_SEARCHSYMBOL_H_ +#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ +#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" @@ -30,4 +30,4 @@ class SearchSymbol : public TIntermTraverser }; } -#endif // COMPILER_SEARCHSYMBOL_H_ +#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 0d6a1d64cf..b8040da7f9 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -14,7 +14,9 @@ #include "compiler/translator/Compiler.h" #include "compiler/translator/InitializeDll.h" #include "compiler/translator/length_limits.h" +#ifdef ANGLE_ENABLE_HLSL #include "compiler/translator/TranslatorHLSL.h" +#endif // ANGLE_ENABLE_HLSL #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" @@ -92,6 +94,7 @@ TCompiler *GetCompilerFromHandle(ShHandle handle) return base->getAsCompiler(); } +#ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) { if (!handle) @@ -99,6 +102,7 @@ TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) TShHandleBase *base = static_cast<TShHandleBase *>(handle); return base->getAsTranslatorHLSL(); } +#endif // ANGLE_ENABLE_HLSL } // namespace anonymous @@ -153,6 +157,10 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->EXT_draw_buffers = 0; resources->EXT_frag_depth = 0; resources->EXT_shader_texture_lod = 0; + resources->WEBGL_debug_shader_precision = 0; + resources->EXT_shader_framebuffer_fetch = 0; + resources->NV_shader_framebuffer_fetch = 0; + resources->ARM_shader_framebuffer_fetch = 0; resources->NV_draw_buffers = 0; @@ -323,6 +331,7 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle, const std::string &interfaceBlockName, unsigned int *indexOut) { +#ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); @@ -335,12 +344,16 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle, *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName); return true; +#else + return false; +#endif // ANGLE_ENABLE_HLSL } bool ShGetUniformRegister(const ShHandle handle, const std::string &uniformName, unsigned int *indexOut) { +#ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); @@ -352,4 +365,7 @@ bool ShGetUniformRegister(const ShHandle handle, *indexOut = translator->getUniformRegister(uniformName); return true; +#else + return false; +#endif // ANGLE_ENABLE_HLSL } diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp index 3098a7f0c9..0dbbc9e7f6 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -14,6 +14,23 @@ namespace sh { +namespace +{ + +InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation) +{ + return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation); +} + +} +// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion +// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error, +// but auxiliary qualifier mismatch (centroid) does not. +bool InterpolationTypesMatch(InterpolationType a, InterpolationType b) +{ + return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b)); +} + ShaderVariable::ShaderVariable() : type(0), precision(0), @@ -86,7 +103,6 @@ bool ShaderVariable::findInfoByMappedName( // 2) the top variable is an array; // 3) otherwise. size_t pos = mappedFullName.find_first_of(".["); - std::string topName; if (pos == std::string::npos) { diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp new file mode 100644 index 0000000000..ac5eb67070 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2002-2015 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 "compiler/translator/SimplifyArrayAssignment.h" + +bool SimplifyArrayAssignment::visitBinary(Visit visit, TIntermBinary *node) +{ + switch (node->getOp()) + { + case EOpAssign: + { + TIntermNode *parent = getParentNode(); + if (node->getLeft()->isArray() && parent != nullptr) + { + TIntermAggregate *parentAgg = parent->getAsAggregate(); + if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence) + { + // This case is fine, the result of the assignment is not used. + break; + } + + // The result of the assignment needs to be stored into a temporary variable, + // the assignment needs to be replaced with a reference to the temporary variable, + // and the temporary variable needs to finally be assigned to the target variable. + + // This also needs to interact correctly with unfolding short circuiting operators. + UNIMPLEMENTED(); + } + } + break; + default: + break; + } + return true; +} diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h new file mode 100644 index 0000000000..247eb88d72 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2002-2015 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. +// +// SimplifyArrayAssignment is an AST traverser to replace statements where +// the return value of array assignment is used with statements where +// the return value of array assignment is not used. +// + +#ifndef COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_ +#define COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_ + +#include "common/angleutils.h" +#include "compiler/translator/IntermNode.h" + +class SimplifyArrayAssignment : public TIntermTraverser +{ + public: + SimplifyArrayAssignment() { } + + virtual bool visitBinary(Visit visit, TIntermBinary *node); +}; + +#endif // COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp index 48929affe6..fd1a29c1cd 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp @@ -21,9 +21,23 @@ Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structEle unsigned *uniqueCounter) : mPaddingCounter(uniqueCounter), mElementIndex(0), - mStructElementIndexes(structElementIndexes) + mStructElementIndexes(&structElementIndexes) {} +Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other) + : mPaddingCounter(other.mPaddingCounter), + mElementIndex(other.mElementIndex), + mStructElementIndexes(other.mStructElementIndexes) +{} + +Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other) +{ + mPaddingCounter = other.mPaddingCounter; + mElementIndex = other.mElementIndex; + mStructElementIndexes = other.mStructElementIndexes; + return *this; +} + TString Std140PaddingHelper::next() { unsigned value = (*mPaddingCounter)++; @@ -107,7 +121,7 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo { const TString &structName = QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true); - numComponents = mStructElementIndexes.find(structName)->second; + numComponents = mStructElementIndexes->find(structName)->second; if (numComponents == 0) { @@ -274,9 +288,9 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) { - const TType &type = ctorParameters[parameter]; + const TType ¶mType = ctorParameters[parameter]; - constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type); + constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType); if (parameter < ctorParameters.size() - 1) { diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h index ed002fef30..cffe2a41ae 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h @@ -7,8 +7,8 @@ // Interfaces of methods for HLSL translation of GLSL structures. // -#ifndef TRANSLATOR_STRUCTUREHLSL_H_ -#define TRANSLATOR_STRUCTUREHLSL_H_ +#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ +#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ #include "compiler/translator/Common.h" #include "compiler/translator/IntermNode.h" @@ -27,7 +27,9 @@ class Std140PaddingHelper { public: explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes, - unsigned *uniqueCounter); + unsigned int *uniqueCounter); + Std140PaddingHelper(const Std140PaddingHelper &other); + Std140PaddingHelper &operator=(const Std140PaddingHelper &other); int elementIndex() const { return mElementIndex; } int prePadding(const TType &type); @@ -39,10 +41,10 @@ class Std140PaddingHelper unsigned *mPaddingCounter; int mElementIndex; - const std::map<TString, int> &mStructElementIndexes; + const std::map<TString, int> *mStructElementIndexes; }; -class StructureHLSL +class StructureHLSL : angle::NonCopyable { public: StructureHLSL(); @@ -76,4 +78,4 @@ class StructureHLSL } -#endif // COMPILER_STRUCTUREHLSL_H_ +#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index 028da21151..0eb663f018 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -48,6 +48,16 @@ bool TSymbolTableLevel::insert(TSymbol *symbol) return result.second; } +bool TSymbolTableLevel::insertUnmangled(TFunction *function) +{ + function->setUniqueId(TSymbolTable::nextUniqueId()); + + // returning true means symbol was added to the table + tInsertResult result = level.insert(tLevelPair(function->getName(), function)); + + return result.second; +} + TSymbol *TSymbolTableLevel::find(const TString &name) const { tLevel::const_iterator it = level.find(name); @@ -57,47 +67,6 @@ TSymbol *TSymbolTableLevel::find(const TString &name) const return (*it).second; } -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in operation. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToOperator(const char *name, TOperator op) -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - { - if ((*it).second->isFunction()) - { - TFunction *function = static_cast<TFunction*>((*it).second); - if (function->getName() == name) - function->relateToOperator(op); - } - } -} - -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in extension. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToExtension(const char *name, const TString &ext) -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - { - TSymbol *symbol = it->second; - if (symbol->getName() == name) - symbol->relateToExtension(ext); - } -} - -TSymbol::TSymbol(const TSymbol ©Of) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; -} - TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const { @@ -148,68 +117,149 @@ TSymbolTable::~TSymbolTable() pop(); } -void TSymbolTable::insertBuiltIn( - ESymbolLevel level, TType *rvalue, const char *name, - TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5) +bool IsGenType(const TType *type) +{ + if (type) + { + TBasicType basicType = type->getBasicType(); + return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType || basicType == EbtGenBType; + } + + return false; +} + +bool IsVecType(const TType *type) +{ + if (type) + { + TBasicType basicType = type->getBasicType(); + return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec || basicType == EbtBVec; + } + + return false; +} + +TType *SpecificType(TType *type, int size) +{ + ASSERT(size >= 1 && size <= 4); + + if (!type) + { + return nullptr; + } + + ASSERT(!IsVecType(type)); + + switch(type->getBasicType()) + { + case EbtGenType: return new TType(EbtFloat, size); + case EbtGenIType: return new TType(EbtInt, size); + case EbtGenUType: return new TType(EbtUInt, size); + case EbtGenBType: return new TType(EbtBool, size); + default: return type; + } +} + +TType *VectorType(TType *type, int size) +{ + ASSERT(size >= 2 && size <= 4); + + if (!type) + { + return nullptr; + } + + ASSERT(!IsGenType(type)); + + switch(type->getBasicType()) + { + case EbtVec: return new TType(EbtFloat, size); + case EbtIVec: return new TType(EbtInt, size); + case EbtUVec: return new TType(EbtUInt, size); + case EbtBVec: return new TType(EbtBool, size); + default: return type; + } +} + +void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5) { if (ptype1->getBasicType() == EbtGSampler2D) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); } - if (ptype1->getBasicType() == EbtGSampler3D) + else if (ptype1->getBasicType() == EbtGSampler3D) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); } - if (ptype1->getBasicType() == EbtGSamplerCube) + else if (ptype1->getBasicType() == EbtGSamplerCube) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); } - if (ptype1->getBasicType() == EbtGSampler2DArray) + else if (ptype1->getBasicType() == EbtGSampler2DArray) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); + } + else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3)) + { + ASSERT(!ptype4 && !ptype5); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), SpecificType(ptype2, 1), SpecificType(ptype3, 1)); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), SpecificType(ptype2, 2), SpecificType(ptype3, 2)); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), SpecificType(ptype2, 3), SpecificType(ptype3, 3)); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4), SpecificType(ptype2, 4), SpecificType(ptype3, 4)); + } + else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3)) + { + ASSERT(!ptype4 && !ptype5); + insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), VectorType(ptype2, 2), VectorType(ptype3, 2)); + insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), VectorType(ptype2, 3), VectorType(ptype3, 3)); + insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), VectorType(ptype2, 4), VectorType(ptype3, 4)); } + else + { + TFunction *function = new TFunction(NewPoolTString(name), *rvalue, op, ext); - TFunction *function = new TFunction(NewPoolTString(name), *rvalue); + TParameter param1 = {0, ptype1}; + function->addParameter(param1); - TType *types[] = {ptype1, ptype2, ptype3, ptype4, ptype5}; - for (size_t ii = 0; ii < sizeof(types) / sizeof(types[0]); ++ii) - { - if (types[ii]) + if (ptype2) { - TParameter param = {NULL, types[ii]}; - function->addParameter(param); + TParameter param2 = {0, ptype2}; + function->addParameter(param2); } - } - insert(level, function); + if (ptype3) + { + TParameter param3 = {0, ptype3}; + function->addParameter(param3); + } + + if (ptype4) + { + TParameter param4 = {0, ptype4}; + function->addParameter(param4); + } + + if (ptype5) + { + TParameter param5 = {0, ptype5}; + function->addParameter(param5); + } + + insert(level, function); + } } TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index 9cd74218dc..dfc65cb957 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _SYMBOL_TABLE_INCLUDED_ -#define _SYMBOL_TABLE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ +#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ // // Symbol table for parsing. Has these design characteristics: @@ -38,7 +38,7 @@ #include "compiler/translator/IntermNode.h" // Symbol base class. (Can build functions or variables out of these...) -class TSymbol +class TSymbol : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); @@ -86,8 +86,6 @@ class TSymbol } private: - DISALLOW_COPY_AND_ASSIGN(TSymbol); - int uniqueId; // For real comparing during code generation const TString *name; TString extension; @@ -158,8 +156,6 @@ class TVariable : public TSymbol } private: - DISALLOW_COPY_AND_ASSIGN(TVariable); - TType type; bool userType; // we are assuming that Pool Allocator will free the memory @@ -186,13 +182,14 @@ class TFunction : public TSymbol defined(false) { } - TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull) + TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull, const char *ext = "") : TSymbol(name), returnType(retType), mangledName(TFunction::mangleName(*name)), op(tOp), defined(false) { + relateToExtension(ext); } virtual ~TFunction(); virtual bool isFunction() const @@ -224,10 +221,6 @@ class TFunction : public TSymbol return returnType; } - void relateToOperator(TOperator o) - { - op = o; - } TOperator getBuiltInOp() const { return op; @@ -252,8 +245,6 @@ class TFunction : public TSymbol } private: - DISALLOW_COPY_AND_ASSIGN(TFunction); - typedef TVector<TParameter> TParamList; TParamList parameters; TType returnType; @@ -291,10 +282,10 @@ class TSymbolTableLevel bool insert(TSymbol *symbol); - TSymbol *find(const TString &name) const; + // Insert a function using its unmangled name as the key. + bool insertUnmangled(TFunction *function); - void relateToOperator(const char *name, TOperator op); - void relateToExtension(const char *name, const TString &ext); + TSymbol *find(const TString &name) const; protected: tLevel level; @@ -310,7 +301,7 @@ const int ESSL3_BUILTINS = 2; const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS; const int GLOBAL_LEVEL = 3; -class TSymbolTable +class TSymbolTable : angle::NonCopyable { public: TSymbolTable() @@ -363,6 +354,12 @@ class TSymbolTable return table[level]->insert(symbol); } + bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol) + { + symbol->relateToExtension(ext); + return table[level]->insert(symbol); + } + bool insertConstInt(ESymbolLevel level, const char *name, int value) { TVariable *constant = new TVariable( @@ -371,9 +368,26 @@ class TSymbolTable return insert(level, constant); } + void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0); + void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, - TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, - TType *ptype4 = 0, TType *ptype5 = 0); + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) + { + insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); + } + + void insertBuiltIn(ESymbolLevel level, const char *ext, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) + { + insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); + } + + void insertBuiltIn(ESymbolLevel level, TOperator op, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) + { + insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); + } TSymbol *find(const TString &name, int shaderVersion, bool *builtIn = NULL, bool *sameScope = NULL) const; @@ -385,14 +399,6 @@ class TSymbolTable return table[currentLevel() - 1]; } - void relateToOperator(ESymbolLevel level, const char *name, TOperator op) - { - table[level]->relateToOperator(name, op); - } - void relateToExtension(ESymbolLevel level, const char *name, const TString &ext) - { - table[level]->relateToExtension(name, ext); - } void dump(TInfoSink &infoSink) const; bool setDefaultPrecision(const TPublicType &type, TPrecision prec) @@ -413,7 +419,7 @@ class TSymbolTable // This records invariant varyings declared through // "invariant varying_name;". - void addInvariantVarying(const TString &originalName) + void addInvariantVarying(const std::string &originalName) { mInvariantVaryings.insert(originalName); } @@ -421,7 +427,7 @@ class TSymbolTable // 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 + bool isVaryingInvariant(const std::string &originalName) const { return (mGlobalInvariant || mInvariantVaryings.count(originalName) > 0); @@ -445,10 +451,10 @@ class TSymbolTable typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; std::vector< PrecisionStackLevel *> precisionStack; - std::set<TString> mInvariantVaryings; + std::set<std::string> mInvariantVaryings; bool mGlobalInvariant; static int uniqueIdCounter; }; -#endif // _SYMBOL_TABLE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp index dcbf3cea1d..238bc97576 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -6,40 +6,91 @@ #include "compiler/translator/TranslatorESSL.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/OutputESSL.h" #include "angle_gl.h" TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_ESSL_OUTPUT) { + : TCompiler(type, spec, SH_ESSL_OUTPUT) +{ } -void TranslatorESSL::translate(TIntermNode* root) { +void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) +{ + if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS) + InitBuiltInFunctionEmulatorForGLSL(emu, getShaderType()); +} + +void TranslatorESSL::translate(TIntermNode *root, int) { TInfoSinkBase& sink = getInfoSink().obj; + int shaderVersion = getShaderVersion(); + if (shaderVersion > 100) + { + sink << "#version " << shaderVersion << " es\n"; + } + writePragma(); // Write built-in extension behaviors. writeExtensionBehavior(); + bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; + + if (precisionEmulation) + { + EmulatePrecision emulatePrecision; + root->traverse(&emulatePrecision); + emulatePrecision.updateTree(); + emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT); + } + // Write emulated built-in functions if needed. - getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, getShaderType() == GL_FRAGMENT_SHADER); + if (!getBuiltInFunctionEmulator().IsOutputEmpty()) + { + sink << "// BEGIN: Generated code for built-in function emulation\n\n"; + if (getShaderType() == GL_FRAGMENT_SHADER) + { + sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" + << "#define webgl_emu_precision highp\n" + << "#else\n" + << "#define webgl_emu_precision mediump\n" + << "#endif\n\n"; + } + else + { + sink << "#define webgl_emu_precision highp\n"; + } + + getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink); + sink << "// END: Generated code for built-in function emulation\n\n"; + } // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); // Write translated shader. - TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion()); + TOutputESSL outputESSL(sink, + getArrayIndexClampingStrategy(), + getHashFunction(), + getNameMap(), + getSymbolTable(), + shaderVersion, + precisionEmulation); root->traverse(&outputESSL); } void TranslatorESSL::writeExtensionBehavior() { TInfoSinkBase& sink = getInfoSink().obj; - const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); - iter != extensionBehavior.end(); ++iter) { + const TExtensionBehavior& extBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); + iter != extBehavior.end(); ++iter) { if (iter->second != EBhUndefined) { - if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") { + if (getResources().NV_shader_framebuffer_fetch && iter->first == "GL_EXT_shader_framebuffer_fetch") { + sink << "#extension GL_NV_shader_framebuffer_fetch : " + << getBehaviorString(iter->second) << "\n"; + } else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") { sink << "#extension GL_NV_draw_buffers : " << getBehaviorString(iter->second) << "\n"; } else { diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h index 55766822d1..89a3e473e9 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h @@ -4,20 +4,23 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATORESSL_H_ -#define COMPILER_TRANSLATORESSL_H_ +#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_ #include "compiler/translator/Compiler.h" -class TranslatorESSL : public TCompiler { -public: +class TranslatorESSL : public TCompiler +{ + public: TranslatorESSL(sh::GLenum type, ShShaderSpec spec); -protected: - virtual void translate(TIntermNode* root); + protected: + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override; -private: + virtual void translate(TIntermNode *root, int compileOptions); + + private: void writeExtensionBehavior(); }; -#endif // COMPILER_TRANSLATORESSL_H_ +#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp index 6acbf7c5a8..aea3f77c4e 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -6,14 +6,69 @@ #include "compiler/translator/TranslatorGLSL.h" +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/OutputGLSL.h" #include "compiler/translator/VersionGLSL.h" -TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_GLSL_OUTPUT) { +namespace +{ + +// To search for what output variables are used in a fragment shader. +// We handle gl_FragColor and gl_FragData at the moment. +class TFragmentOutSearcher : public TIntermTraverser +{ + public: + TFragmentOutSearcher() + : mUsesGlFragColor(false), + mUsesGlFragData(false) + { + } + + bool usesGlFragColor() const + { + return mUsesGlFragColor; + } + + bool usesGlFragData() const + { + return mUsesGlFragData; + } + + protected: + virtual void visitSymbol(TIntermSymbol *node) override + { + if (node->getSymbol() == "gl_FragColor") + { + mUsesGlFragColor = true; + } + else if (node->getSymbol() == "gl_FragData") + { + mUsesGlFragData = true; + } + } + + private: + bool mUsesGlFragColor; + bool mUsesGlFragData; +}; + +} // namespace anonymous + +TranslatorGLSL::TranslatorGLSL(sh::GLenum type, + ShShaderSpec spec, + ShShaderOutput output) + : TCompiler(type, spec, output) { +} + +void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) +{ + if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS) + InitBuiltInFunctionEmulatorForGLSL(emu, getShaderType()); } -void TranslatorGLSL::translate(TIntermNode* root) { +void TranslatorGLSL::translate(TIntermNode *root, int) { TInfoSinkBase& sink = getInfoSink().obj; // Write GLSL version. @@ -24,21 +79,60 @@ void TranslatorGLSL::translate(TIntermNode* root) { // Write extension behaviour as needed writeExtensionBehavior(); + bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; + + if (precisionEmulation) + { + EmulatePrecision emulatePrecision; + root->traverse(&emulatePrecision); + emulatePrecision.updateTree(); + emulatePrecision.writeEmulationHelpers(sink, getOutputType()); + } + // Write emulated built-in functions if needed. - getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, false); + if (!getBuiltInFunctionEmulator().IsOutputEmpty()) + { + sink << "// BEGIN: Generated code for built-in function emulation\n\n"; + sink << "#define webgl_emu_precision\n\n"; + getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink); + sink << "// END: Generated code for built-in function emulation\n\n"; + } // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); + // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData + // if it's core profile shaders and they are used. + if (getShaderType() == GL_FRAGMENT_SHADER && + getOutputType() == SH_GLSL_CORE_OUTPUT) + { + TFragmentOutSearcher searcher; + root->traverse(&searcher); + ASSERT(!(searcher.usesGlFragData() && searcher.usesGlFragColor())); + if (searcher.usesGlFragColor()) + { + sink << "out vec4 webgl_FragColor;\n"; + } + if (searcher.usesGlFragData()) + { + sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; + } + } + // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion()); + TOutputGLSL outputGLSL(sink, + getArrayIndexClampingStrategy(), + getHashFunction(), + getNameMap(), + getSymbolTable(), + getShaderVersion(), + getOutputType()); root->traverse(&outputGLSL); } void TranslatorGLSL::writeVersion(TIntermNode *root) { - TVersionGLSL versionGLSL(getShaderType(), getPragma()); + TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); root->traverse(&versionGLSL); int version = versionGLSL.getVersion(); // We need to write version directive only if it is greater than 110. @@ -52,9 +146,9 @@ void TranslatorGLSL::writeVersion(TIntermNode *root) void TranslatorGLSL::writeExtensionBehavior() { TInfoSinkBase& sink = getInfoSink().obj; - const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); - iter != extensionBehavior.end(); ++iter) { + const TExtensionBehavior& extBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); + iter != extBehavior.end(); ++iter) { if (iter->second == EBhUndefined) continue; diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h index 766d8d910e..4a5a641096 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -4,22 +4,24 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATORGLSL_H_ -#define COMPILER_TRANSLATORGLSL_H_ +#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ #include "compiler/translator/Compiler.h" class TranslatorGLSL : public TCompiler { public: - TranslatorGLSL(sh::GLenum type, ShShaderSpec spec); + TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); protected: - virtual void translate(TIntermNode *root); + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override; + + virtual void translate(TIntermNode *root, int compileOptions); private: void writeVersion(TIntermNode *root); void writeExtensionBehavior(); }; -#endif // COMPILER_TRANSLATORGLSL_H_ +#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 22bf60e86e..f6275defa1 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -6,20 +6,26 @@ #include "compiler/translator/TranslatorHLSL.h" -#include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/SimplifyArrayAssignment.h" TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : TCompiler(type, spec, output) { } -void TranslatorHLSL::translate(TIntermNode *root) +void TranslatorHLSL::translate(TIntermNode *root, int compileOptions) { - TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, this); + const ShBuiltInResources &resources = getResources(); + int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - outputHLSL.output(); + SimplifyArrayAssignment simplify; + root->traverse(&simplify); + + sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(), + getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions); + + outputHLSL.output(root, getInfoSink().obj); mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap(); mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h index 11a042d83a..1920ed5755 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATORHLSL_H_ -#define COMPILER_TRANSLATORHLSL_H_ +#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ #include "compiler/translator/Compiler.h" @@ -22,10 +22,10 @@ class TranslatorHLSL : public TCompiler unsigned int getUniformRegister(const std::string &uniformName) const; protected: - virtual void translate(TIntermNode* root); + virtual void translate(TIntermNode *root, int compileOptions); std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap; }; -#endif // COMPILER_TRANSLATORHLSL_H_ +#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp index d36936fb23..b970bf5ac4 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp @@ -178,11 +178,12 @@ size_t TType::getObjectSize() const if (isArray()) { - size_t arraySize = getArraySize(); - if (arraySize > INT_MAX / totalSize) + // TODO: getArraySize() returns an int, not a size_t + size_t currentArraySize = getArraySize(); + if (currentArraySize > INT_MAX / totalSize) totalSize = INT_MAX; else - totalSize *= arraySize; + totalSize *= currentArraySize; } return totalSize; @@ -199,6 +200,17 @@ bool TStructure::containsArrays() const return false; } +bool TStructure::containsSamplers() const +{ + for (size_t i = 0; i < mFields->size(); ++i) + { + const TType *fieldType = (*mFields)[i]->type(); + if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) + return true; + } + return false; +} + TString TFieldListCollection::buildMangledName() const { TString mangledName(mangledNamePrefix()); diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h index 075196daa3..044f22c3c1 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _TYPES_INCLUDED -#define _TYPES_INCLUDED +#ifndef COMPILER_TRANSLATOR_TYPES_H_ +#define COMPILER_TRANSLATOR_TYPES_H_ #include "common/angleutils.h" @@ -17,7 +17,7 @@ struct TPublicType; class TType; class TSymbol; -class TField +class TField : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); @@ -49,7 +49,6 @@ class TField } private: - DISALLOW_COPY_AND_ASSIGN(TField); TType *mType; TString *mName; TSourceLoc mLine; @@ -62,7 +61,7 @@ inline TFieldList *NewPoolTFieldList() return new(memory) TFieldList; } -class TFieldListCollection +class TFieldListCollection : angle::NonCopyable { public: const TString &name() const @@ -113,7 +112,8 @@ class TStructure : public TFieldListCollection TStructure(const TString *name, TFieldList *fields) : TFieldListCollection(name, fields), mDeepestNesting(0), - mUniqueId(0) + mUniqueId(0), + mAtGlobalScope(false) { } @@ -124,6 +124,7 @@ class TStructure : public TFieldListCollection return mDeepestNesting; } bool containsArrays() const; + bool containsSamplers() const; bool equals(const TStructure &other) const; @@ -138,9 +139,17 @@ class TStructure : public TFieldListCollection return mUniqueId; } - private: - DISALLOW_COPY_AND_ASSIGN(TStructure); + void setAtGlobalScope(bool atGlobalScope) + { + mAtGlobalScope = atGlobalScope; + } + + bool atGlobalScope() const + { + return mAtGlobalScope; + } + private: // TODO(zmo): Find a way to get rid of the const_cast in function // setName(). At the moment keep this function private so only // friend class RegenerateStructNames may call it. @@ -159,6 +168,7 @@ class TStructure : public TFieldListCollection mutable int mDeepestNesting; int mUniqueId; + bool mAtGlobalScope; }; class TInterfaceBlock : public TFieldListCollection @@ -201,7 +211,6 @@ class TInterfaceBlock : public TFieldListCollection } private: - DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock); virtual TString mangledNamePrefix() const { return "iblock-"; @@ -325,6 +334,10 @@ class TType { return primarySize > 1 && secondarySize > 1; } + bool isNonSquareMatrix() const + { + return isMatrix() && primarySize != secondarySize; + } bool isArray() const { return array ? true : false; @@ -464,6 +477,11 @@ class TType return structure ? structure->containsArrays() : false; } + bool isStructureContainingSamplers() const + { + return structure ? structure->containsSamplers() : false; + } + protected: TString buildMangledName() const; size_t getStructSize() const; @@ -584,4 +602,4 @@ struct TPublicType } }; -#endif // _TYPES_INCLUDED_ +#endif // COMPILER_TRANSLATOR_TYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp index 65f50c4cc3..f79f9dd7fb 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp @@ -16,7 +16,7 @@ namespace sh { -UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL) +UnfoldShortCircuit::UnfoldShortCircuit(OutputHLSL *outputHLSL) : mOutputHLSL(outputHLSL) { mTemporaryIndex = 0; } @@ -30,7 +30,7 @@ void UnfoldShortCircuit::traverse(TIntermNode *node) bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) { - TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + TInfoSinkBase &out = mOutputHLSL->getInfoSink(); // If our right node doesn't have side effects, we know we don't need to unfold this // expression: there will be no short-circuiting side effects to avoid @@ -111,7 +111,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + TInfoSinkBase &out = mOutputHLSL->getInfoSink(); // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" if (node->usesTernaryOperator()) diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h index 6fd3b457bd..eaceb0a0b3 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -6,8 +6,8 @@ // UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements // -#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ -#define COMPILER_UNFOLDSHORTCIRCUIT_H_ +#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ +#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" @@ -19,7 +19,7 @@ class OutputHLSL; class UnfoldShortCircuit : public TIntermTraverser { public: - UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL); + UnfoldShortCircuit(OutputHLSL *outputHLSL); void traverse(TIntermNode *node); bool visitBinary(Visit visit, TIntermBinary*); @@ -29,11 +29,10 @@ class UnfoldShortCircuit : public TIntermTraverser int getNextTemporaryIndex(); protected: - TParseContext &mContext; OutputHLSL *const mOutputHLSL; int mTemporaryIndex; }; } -#endif // COMPILER_UNFOLDSHORTCIRCUIT_H_ +#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp index 29c4397d56..d548d421d2 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp @@ -50,32 +50,8 @@ bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) } if (replacement) { - replacements.push_back( - NodeUpdateEntry(getParentNode(), node, replacement)); + mReplacements.push_back( + NodeUpdateEntry(getParentNode(), node, replacement, false)); } return true; } - -void UnfoldShortCircuitAST::updateTree() -{ - for (size_t ii = 0; ii < replacements.size(); ++ii) - { - const NodeUpdateEntry& entry = replacements[ii]; - ASSERT(entry.parent); - bool replaced = entry.parent->replaceChildNode( - entry.original, entry.replacement); - ASSERT(replaced); - - // In AST traversing, a parent is visited before its children. - // After we replace a node, if an immediate child is to - // be replaced, we need to make sure we don't update the replaced - // node; instead, we update the replacement node. - for (size_t jj = ii + 1; jj < replacements.size(); ++jj) - { - NodeUpdateEntry& entry2 = replacements[jj]; - if (entry2.parent == entry.original) - entry2.parent = entry.replacement; - } - } -} - diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h index 3acaf7ee7c..7b698ccb63 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -7,8 +7,8 @@ // operations with ternary operations. // -#ifndef COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ -#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ +#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ +#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ #include "common/angleutils.h" #include "compiler/translator/IntermNode.h" @@ -23,29 +23,6 @@ class UnfoldShortCircuitAST : public TIntermTraverser UnfoldShortCircuitAST() { } virtual bool visitBinary(Visit visit, TIntermBinary *); - - void updateTree(); - - private: - struct NodeUpdateEntry - { - NodeUpdateEntry(TIntermNode *_parent, - TIntermNode *_original, - TIntermNode *_replacement) - : parent(_parent), - original(_original), - replacement(_replacement) {} - - TIntermNode *parent; - TIntermNode *original; - TIntermNode *replacement; - }; - - // During traversing, save all the replacements that need to happen; - // then replace them by calling updateNodes(). - std::vector<NodeUpdateEntry> replacements; - - DISALLOW_COPY_AND_ASSIGN(UnfoldShortCircuitAST); }; -#endif // COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ +#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp index 61b6ed7455..71659fe354 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp @@ -7,14 +7,13 @@ // Methods for GLSL to HLSL translation for uniforms and interface blocks. // -#include "OutputHLSL.h" -#include "common/blocklayout.h" -#include "common/utilities.h" #include "compiler/translator/UniformHLSL.h" + +#include "common/utilities.h" #include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/util.h" #include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/TranslatorHLSL.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "compiler/translator/util.h" namespace sh { @@ -61,13 +60,13 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) return DecoratePrivate(interfaceBlock.name()) + "_type"; } -UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator) +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms) : mUniformRegister(0), mInterfaceBlockRegister(0), mSamplerRegister(0), mStructureHLSL(structureHLSL), - mOutputType(translator->getOutputType()), - mUniforms(translator->getUniforms()) + mOutputType(outputType), + mUniforms(uniforms) {} void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) @@ -105,7 +104,7 @@ unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, con unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); - if (gl::IsSampler(uniform->type)) + if (gl::IsSamplerType(uniform->type)) { mSamplerRegister += registerCount; } diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h index 91fa51588b..4ab9ccdf53 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h @@ -7,19 +7,19 @@ // Methods for GLSL to HLSL translation for uniforms and interface blocks. // -#ifndef TRANSLATOR_UNIFORMHLSL_H_ -#define TRANSLATOR_UNIFORMHLSL_H_ +#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_ +#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_ -#include "compiler/translator/Types.h" +#include "compiler/translator/OutputHLSL.h" namespace sh { class StructureHLSL; -class UniformHLSL +class UniformHLSL : angle::NonCopyable { public: - UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator); + UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms); void reserveUniformRegisters(unsigned int registerCount); void reserveInterfaceBlockRegisters(unsigned int registerCount); @@ -60,4 +60,4 @@ class UniformHLSL } -#endif // TRANSLATOR_UNIFORMHLSL_H_ +#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp index de0c36ca65..94e19ac40d 100644 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp @@ -175,6 +175,13 @@ TString StructNameString(const TStructure &structure) return ""; } + // For structures at global scope we use a consistent + // translation so that we can link between shader stages. + if (structure.atGlobalScope()) + { + return Decorate(structure.name()); + } + return "ss" + str(structure.uniqueId()) + "_" + structure.name(); } diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h index aaa3ddf5d2..9800a3bbf3 100644 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h @@ -7,8 +7,8 @@ // Utility methods for GLSL to HLSL translation. // -#ifndef TRANSLATOR_UTILSHLSL_H_ -#define TRANSLATOR_UTILSHLSL_H_ +#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_ +#define COMPILER_TRANSLATOR_UTILSHLSL_H_ #include <vector> #include "compiler/translator/Types.h" @@ -34,4 +34,4 @@ TString QualifierString(TQualifier qualifier); } -#endif // TRANSLATOR_UTILSHLSL_H_ +#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp index 896e1cd7a0..12367066e8 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -47,93 +47,6 @@ class ValidateConstIndexExpr : public TIntermTraverser TLoopStack& mLoopStack; }; -const char *GetOperatorString(TOperator op) -{ - switch (op) - { - case EOpInitialize: return "="; - case EOpAssign: return "="; - case EOpAddAssign: return "+="; - case EOpSubAssign: return "-="; - case EOpDivAssign: return "/="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: return "*="; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: return "[]"; - - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: return "."; - case EOpVectorSwizzle: return "."; - case EOpAdd: return "+"; - case EOpSub: return "-"; - case EOpMul: return "*"; - case EOpDiv: return "/"; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: return "=="; - case EOpNotEqual: return "!="; - case EOpLessThan: return "<"; - case EOpGreaterThan: return ">"; - case EOpLessThanEqual: return "<="; - case EOpGreaterThanEqual: return ">="; - - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: return "*"; - - case EOpLogicalOr: return "||"; - case EOpLogicalXor: return "^^"; - case EOpLogicalAnd: return "&&"; - case EOpNegative: return "-"; - case EOpPositive: return "+"; - case EOpVectorLogicalNot: return "not"; - case EOpLogicalNot: return "!"; - case EOpPostIncrement: return "++"; - case EOpPostDecrement: return "--"; - case EOpPreIncrement: return "++"; - case EOpPreDecrement: return "--"; - - case EOpRadians: return "radians"; - case EOpDegrees: return "degrees"; - case EOpSin: return "sin"; - case EOpCos: return "cos"; - case EOpTan: return "tan"; - case EOpAsin: return "asin"; - case EOpAcos: return "acos"; - case EOpAtan: return "atan"; - case EOpExp: return "exp"; - case EOpLog: return "log"; - case EOpExp2: return "exp2"; - case EOpLog2: return "log2"; - case EOpSqrt: return "sqrt"; - case EOpInverseSqrt: return "inversesqrt"; - case EOpAbs: return "abs"; - case EOpSign: return "sign"; - case EOpFloor: return "floor"; - case EOpCeil: return "ceil"; - case EOpFract: return "fract"; - case EOpLength: return "length"; - case EOpNormalize: return "normalize"; - case EOpDFdx: return "dFdx"; - case EOpDFdy: return "dFdy"; - case EOpFwidth: return "fwidth"; - case EOpAny: return "any"; - case EOpAll: return "all"; - - default: break; - } - return ""; -} - } // namespace anonymous ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index e6e8a9619f..59cccb565f 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ +#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ + #include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" @@ -53,3 +56,4 @@ class ValidateLimitations : public TIntermTraverser TLoopStack mLoopStack; }; +#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h index 0f808dbb97..1538e0f157 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ +#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ + #include "compiler/translator/IntermNode.h" #include <set> @@ -31,3 +34,5 @@ class ValidateOutputs : public TIntermTraverser void error(TSourceLoc loc, const char *reason, const char* token); }; + +#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp new file mode 100644 index 0000000000..9a4ed33632 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp @@ -0,0 +1,200 @@ +// +// Copyright (c) 2002-2015 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 "compiler/translator/ValidateSwitch.h" + +#include "compiler/translator/ParseContext.h" + +bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc) +{ + ValidateSwitch validate(switchType, context); + ASSERT(statementList); + statementList->traverse(&validate); + return validate.validateInternal(loc); +} + +ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context) + : TIntermTraverser(true, false, true), + mSwitchType(switchType), + mContext(context), + mCaseTypeMismatch(false), + mFirstCaseFound(false), + mStatementBeforeCase(false), + mLastStatementWasCase(false), + mControlFlowDepth(0), + mCaseInsideControlFlow(false), + mDefaultCount(0), + mDuplicateCases(false) +{} + +void ValidateSwitch::visitSymbol(TIntermSymbol *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) +{ + // Conditions of case labels are not traversed, so this is some other constant + // Could be just a statement like "0;" + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + // Don't go into nested switch statements + return false; +} + +bool ValidateSwitch::visitCase(Visit, TIntermCase *node) +{ + const char *nodeStr = node->hasCondition() ? "case" : "default"; + if (mControlFlowDepth > 0) + { + mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr); + mCaseInsideControlFlow = true; + } + mFirstCaseFound = true; + mLastStatementWasCase = true; + if (!node->hasCondition()) + { + ++mDefaultCount; + if (mDefaultCount > 1) + { + mContext->error(node->getLine(), "duplicate default label", nodeStr); + } + } + else + { + TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); + if (condition == nullptr) + { + // This can happen in error cases. + return false; + } + TBasicType conditionType = condition->getBasicType(); + if (conditionType != mSwitchType) + { + mContext->error(condition->getLine(), + "case label type does not match switch init-expression type", nodeStr); + mCaseTypeMismatch = true; + } + + if (conditionType == EbtInt) + { + int iConst = condition->getIConst(0); + if (mCasesSigned.find(iConst) != mCasesSigned.end()) + { + mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesSigned.insert(iConst); + } + } + else if (conditionType == EbtUInt) + { + unsigned int uConst = condition->getUConst(0); + if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) + { + mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesUnsigned.insert(uConst); + } + } + // Other types are possible only in error cases, where the error has already been generated + // when parsing the case statement. + } + // Don't traverse the condition of the case statement + return false; +} + +bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) +{ + if (getParentNode() != nullptr) + { + // This is not the statementList node, but some other node. + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + } + return true; +} + +bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::validateInternal(const TSourceLoc &loc) +{ + if (mStatementBeforeCase) + { + mContext->error(loc, + "statement before the first label", "switch"); + } + if (mLastStatementWasCase) + { + mContext->error(loc, + "no statement between the last label and the end of the switch statement", "switch"); + } + return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && + !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h new file mode 100644 index 0000000000..88b68a500e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2002-2015 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 COMPILER_TRANSLATOR_VALIDATESWITCH_H_ +#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ + +#include "compiler/translator/IntermNode.h" + +struct TParseContext; + +class ValidateSwitch : public TIntermTraverser +{ + public: + // Check for errors and output messages any remaining errors on the context. + // Returns true if there are no errors. + static bool validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc); + + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitBinary(Visit, TIntermBinary *) override; + bool visitUnary(Visit, TIntermUnary *) override; + bool visitSelection(Visit visit, TIntermSelection *) override; + bool visitSwitch(Visit, TIntermSwitch *) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit, TIntermBranch *) override; + + private: + ValidateSwitch(TBasicType switchType, TParseContext *context); + + bool validateInternal(const TSourceLoc &loc); + + TBasicType mSwitchType; + TParseContext *mContext; + bool mCaseTypeMismatch; + bool mFirstCaseFound; + bool mStatementBeforeCase; + bool mLastStatementWasCase; + int mControlFlowDepth; + bool mCaseInsideControlFlow; + int mDefaultCount; + std::set<int> mCasesSigned; + std::set<unsigned int> mCasesUnsigned; + bool mDuplicateCases; +}; + +#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index d8e13788b7..cf229ec96a 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -142,8 +142,10 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs, mPointCoordAdded(false), mFrontFacingAdded(false), mFragCoordAdded(false), + mInstanceIDAdded(false), mPositionAdded(false), mPointSizeAdded(false), + mLastFragDataAdded(false), mHashFunction(hashFunction), mSymbolTable(symbolTable) { @@ -249,6 +251,22 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) mPointCoordAdded = true; } return; + case EvqInstanceID: + if (!mInstanceIDAdded) + { + Attribute info; + const char kName[] = "gl_InstanceID"; + info.name = kName; + info.mappedName = kName; + info.type = GL_INT; + info.arraySize = 0; + info.precision = GL_HIGH_INT; // Defined by spec. + info.staticUse = true; + info.location = -1; + mAttribs->push_back(info); + mInstanceIDAdded = true; + } + return; case EvqPosition: if (!mPositionAdded) { @@ -281,6 +299,22 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) mPointSizeAdded = true; } return; + case EvqLastFragData: + if (!mLastFragDataAdded) + { + Varying info; + const char kName[] = "gl_LastFragData"; + info.name = kName; + info.mappedName = kName; + info.type = GL_FLOAT_VEC4; + info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst(); + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. + info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); + mVaryings->push_back(info); + mLastFragDataAdded = true; + } + return; default: break; } @@ -301,8 +335,6 @@ class NameHashingTraverser : public GetVariableTraverser {} private: - DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser); - virtual void visitVariable(ShaderVariable *variable) { TString stringName = TString(variable->name.c_str()); diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 92d376d879..bb1328a507 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_VARIABLE_INFO_H_ -#define COMPILER_VARIABLE_INFO_H_ +#ifndef COMPILER_TRANSLATOR_VARIABLEINFO_H_ +#define COMPILER_TRANSLATOR_VARIABLEINFO_H_ #include <GLSLANG/ShaderLang.h> @@ -51,8 +51,10 @@ class CollectVariables : public TIntermTraverser bool mFrontFacingAdded; bool mFragCoordAdded; + bool mInstanceIDAdded; bool mPositionAdded; bool mPointSizeAdded; + bool mLastFragDataAdded; ShHashFunction64 mHashFunction; @@ -65,4 +67,4 @@ void ExpandUniforms(const std::vector<Uniform> &compact, } -#endif // COMPILER_VARIABLE_INFO_H_ +#endif // COMPILER_TRANSLATOR_VARIABLEINFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h index 1de5332d8a..9c80eea618 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _VARIABLEPACKER_INCLUDED_ -#define _VARIABLEPACKER_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_ +#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_ #include <vector> #include "compiler/translator/VariableInfo.h" @@ -38,4 +38,4 @@ class VariablePacker { std::vector<unsigned> rows_; }; -#endif // _VARIABLEPACKER_INCLUDED_ +#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 05b111a7a7..f6f568897d 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -8,6 +8,7 @@ static const int GLSL_VERSION_110 = 110; static const int GLSL_VERSION_120 = 120; +static const int GLSL_VERSION_150 = 150; // We need to scan for the following: // 1. "invariant" keyword: This can occur in both - vertex and fragment shaders @@ -26,12 +27,22 @@ 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." // -TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma) +TVersionGLSL::TVersionGLSL(sh::GLenum type, + const TPragma &pragma, + ShShaderOutput output) { - if (pragma.stdgl.invariantAll) - mVersion = GLSL_VERSION_120; + if (output == SH_GLSL_CORE_OUTPUT) + { + mVersion = GLSL_VERSION_150; + } else - mVersion = GLSL_VERSION_110; + { + ASSERT(output == SH_GLSL_COMPATIBILITY_OUTPUT); + 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 72368e39d6..2b63d5f25d 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -29,14 +29,16 @@ class TVersionGLSL : public TIntermTraverser { public: - TVersionGLSL(sh::GLenum type, const TPragma &pragma); - - // Returns 120 if the following is used the shader: - // - "invariant", - // - "gl_PointCoord", - // - matrix/matrix constructors - // - array "out" parameters - // Else 110 is returned. + TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output); + + // If output is core profile, returns 150. + // If output is legacy profile, + // Returns 120 if the following is used the shader: + // - "invariant", + // - "gl_PointCoord", + // - matrix/matrix constructors + // - array "out" parameters + // Else 110 is returned. int getVersion() { return mVersion; } virtual void visitSymbol(TIntermSymbol *); diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp new file mode 100644 index 0000000000..7c74105680 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp @@ -0,0 +1,123 @@ +// +// Copyright (c) 2013-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. +// +// blocklayout.cpp: +// Implementation for block layout classes and methods. +// + +#include "compiler/translator/blocklayout.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace sh +{ + +BlockLayoutEncoder::BlockLayoutEncoder() + : mCurrentOffset(0) +{ +} + +BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) +{ + int arrayStride; + int matrixStride; + + getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); + + const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); + + advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; +} + +// static +size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) +{ + return (info.offset / BytesPerComponent) / ComponentsPerRegister; +} + +// static +size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) +{ + return (info.offset / BytesPerComponent) % ComponentsPerRegister; +} + +void BlockLayoutEncoder::nextRegister() +{ + mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister); +} + +Std140BlockEncoder::Std140BlockEncoder() +{ +} + +void Std140BlockEncoder::enterAggregateType() +{ + nextRegister(); +} + +void Std140BlockEncoder::exitAggregateType() +{ + nextRegister(); +} + +void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) +{ + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); + + size_t baseAlignment = 0; + int matrixStride = 0; + int arrayStride = 0; + + if (gl::IsMatrixType(type)) + { + baseAlignment = ComponentsPerRegister; + matrixStride = ComponentsPerRegister; + + if (arraySize > 0) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = ComponentsPerRegister * numRegisters; + } + } + else if (arraySize > 0) + { + baseAlignment = ComponentsPerRegister; + arrayStride = ComponentsPerRegister; + } + else + { + const int numComponents = gl::VariableComponentCount(type); + baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents)); + } + + mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) +{ + if (arraySize > 0) + { + mCurrentOffset += arrayStride * arraySize; + } + else if (gl::IsMatrixType(type)) + { + ASSERT(matrixStride == ComponentsPerRegister); + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + mCurrentOffset += ComponentsPerRegister * numRegisters; + } + else + { + mCurrentOffset += gl::VariableComponentCount(type); + } +} + +} diff --git a/src/3rdparty/angle/src/common/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h index d46ac6e547..c11357fe66 100644 --- a/src/3rdparty/angle/src/common/blocklayout.h +++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.h @@ -24,7 +24,7 @@ struct Uniform; struct Varying; struct InterfaceBlock; -struct BlockMemberInfo +struct COMPILER_EXPORT BlockMemberInfo { BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) : offset(offset), @@ -44,7 +44,7 @@ struct BlockMemberInfo bool isRowMajorMatrix; }; -class BlockLayoutEncoder +class COMPILER_EXPORT BlockLayoutEncoder { public: BlockLayoutEncoder(); @@ -61,6 +61,9 @@ class BlockLayoutEncoder static const size_t BytesPerComponent = 4u; static const unsigned int ComponentsPerRegister = 4u; + static size_t getBlockRegister(const BlockMemberInfo &info); + static size_t getBlockRegisterElement(const BlockMemberInfo &info); + protected: size_t mCurrentOffset; @@ -73,7 +76,7 @@ class BlockLayoutEncoder // Block layout according to the std140 block layout // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification -class Std140BlockEncoder : public BlockLayoutEncoder +class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder { public: Std140BlockEncoder(); @@ -86,42 +89,6 @@ class Std140BlockEncoder : public BlockLayoutEncoder virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); }; -// Block layout packed according to the D3D9 or default D3D10+ register packing rules -// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx -// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED -// for everything else (D3D10+ constant blocks and all attributes/varyings). - -class HLSLBlockEncoder : public BlockLayoutEncoder -{ - public: - enum HLSLBlockEncoderStrategy - { - ENCODE_PACKED, - ENCODE_LOOSE - }; - - HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy); - - virtual void enterAggregateType(); - virtual void exitAggregateType(); - void skipRegisters(unsigned int numRegisters); - - bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } - - static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); - - protected: - virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); - virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); - - HLSLBlockEncoderStrategy mEncoderStrategy; -}; - -// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder -// class to count the number of used registers in a struct (which are individually packed according to the same rules). -unsigned int HLSLVariableRegisterCount(const Varying &variable); -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); - } #endif // COMMON_BLOCKLAYOUT_H_ diff --git a/src/3rdparty/angle/src/common/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp index e3b2d43566..f32cf2cf89 100644 --- a/src/3rdparty/angle/src/common/blocklayout.cpp +++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp @@ -7,108 +7,17 @@ // Implementation for block layout classes and methods. // -#include "common/blocklayout.h" +#include "compiler/translator/blocklayoutHLSL.h" + #include "common/mathutil.h" #include "common/utilities.h" namespace sh { -BlockLayoutEncoder::BlockLayoutEncoder() - : mCurrentOffset(0) -{ -} - -BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) -{ - int arrayStride; - int matrixStride; - - getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); - - advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); - - return memberInfo; -} - -void BlockLayoutEncoder::nextRegister() -{ - mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister); -} - -Std140BlockEncoder::Std140BlockEncoder() -{ -} - -void Std140BlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::exitAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) -{ - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - size_t baseAlignment = 0; - int matrixStride = 0; - int arrayStride = 0; - - if (gl::IsMatrixType(type)) - { - baseAlignment = ComponentsPerRegister; - matrixStride = ComponentsPerRegister; - - if (arraySize > 0) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (arraySize > 0) - { - baseAlignment = ComponentsPerRegister; - arrayStride = ComponentsPerRegister; - } - else - { - const int numComponents = gl::VariableComponentCount(type); - baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents)); - } - - mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) -{ - if (arraySize > 0) - { - mCurrentOffset += arrayStride * arraySize; - } - else if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * numRegisters; - } - else - { - mCurrentOffset += gl::VariableComponentCount(type); - } -} - HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy) - : mEncoderStrategy(strategy) + : mEncoderStrategy(strategy), + mTransposeMatrices(false) { } @@ -121,8 +30,10 @@ void HLSLBlockEncoder::exitAggregateType() { } -void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) +void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) { + GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); @@ -166,8 +77,10 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b *arrayStrideOut = arrayStride; } -void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) +void HLSLBlockEncoder::advanceOffset(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) { + GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); + if (arraySize > 0) { mCurrentOffset += arrayStride * (arraySize - 1); @@ -230,9 +143,10 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * } } -unsigned int HLSLVariableRegisterCount(const Varying &variable) +unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices) { HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED); + encoder.setTransposeMatrices(transposeMatrices); HLSLVariableRegisterCount(variable, &encoder); const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h new file mode 100644 index 0000000000..c61cb1ae57 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h @@ -0,0 +1,62 @@ +// +// Copyright (c) 2013-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. +// +// blocklayout.h: +// Methods and classes related to uniform layout and packing in GLSL and HLSL. +// + +#ifndef COMMON_BLOCKLAYOUTHLSL_H_ +#define COMMON_BLOCKLAYOUTHLSL_H_ + +#include <cstddef> +#include <vector> + +#include "angle_gl.h" +#include "blocklayout.h" +#include <GLSLANG/ShaderLang.h> + +namespace sh +{ +// Block layout packed according to the D3D9 or default D3D10+ register packing rules +// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx +// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED +// for everything else (D3D10+ constant blocks and all attributes/varyings). + +class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder +{ + public: + enum HLSLBlockEncoderStrategy + { + ENCODE_PACKED, + ENCODE_LOOSE + }; + + HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy); + + virtual void enterAggregateType(); + virtual void exitAggregateType(); + void skipRegisters(unsigned int numRegisters); + + bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } + void setTransposeMatrices(bool enabled) { mTransposeMatrices = enabled; } + + static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); + + protected: + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); + + HLSLBlockEncoderStrategy mEncoderStrategy; + bool mTransposeMatrices; +}; + +// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder +// class to count the number of used registers in a struct (which are individually packed according to the same rules). +COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices); +COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); + +} + +#endif // COMMON_BLOCKLAYOUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h index 7a371516af..84a12ad2f8 100644 --- a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h +++ b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h @@ -6,8 +6,8 @@ // debug.h: Debugging utilities. -#ifndef COMPILER_DEBUG_H_ -#define COMPILER_DEBUG_H_ +#ifndef COMPILER_TRANSLATOR_COMPILERDEBUG_H_ +#define COMPILER_TRANSLATOR_COMPILERDEBUG_H_ #include <assert.h> @@ -49,5 +49,5 @@ void Trace(const char* format, ...); assert(false); \ } while(0) -#endif // COMPILER_DEBUG_H_ +#endif // COMPILER_TRANSLATOR_COMPILERDEBUG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h index bc25fe7cbc..22db633678 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ #include "compiler/translator/IntermNode.h" @@ -186,7 +186,7 @@ private: // // When using this, just fill in the methods for nodes you want visited. // -class TDependencyGraphTraverser { +class TDependencyGraphTraverser : angle::NonCopyable { public: TDependencyGraphTraverser() : mDepth(0) {} @@ -209,4 +209,4 @@ private: TGraphNodeSet mVisited; }; -#endif +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h index b76f075e68..f7b3bd4b43 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H -#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ #include "compiler/translator/depgraph/DependencyGraph.h" @@ -104,7 +104,7 @@ class TDependencyGraphBuilder : public TIntermTraverser // An instance of this class pushes a new node set when instantiated. // When the instance goes out of scope, it and pops the node set. // - class TNodeSetMaintainer + class TNodeSetMaintainer : angle::NonCopyable { public: TNodeSetMaintainer(TDependencyGraphBuilder *factory) @@ -122,7 +122,7 @@ class TDependencyGraphBuilder : public TIntermTraverser // When the instance goes out of scope, it and pops the top node set and adds // its contents to the new top node set. // - class TNodeSetPropagatingMaintainer + class TNodeSetPropagatingMaintainer : angle::NonCopyable { public: TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory) @@ -147,7 +147,7 @@ class TDependencyGraphBuilder : public TIntermTraverser // kRightSubtree will never be replaced by a real symbol because we are tracking // the leftmost symbol. // - class TLeftmostSymbolMaintainer + class TLeftmostSymbolMaintainer : angle::NonCopyable { public: TLeftmostSymbolMaintainer( @@ -196,4 +196,4 @@ class TDependencyGraphBuilder : public TIntermTraverser TSymbolStack mLeftmostSymbols; }; -#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h index c3a4112278..b201e0a671 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h @@ -4,27 +4,28 @@ // found in the LICENSE file. // -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ #include "compiler/translator/depgraph/DependencyGraph.h" #include "compiler/translator/InfoSink.h" -class TDependencyGraphOutput : public TDependencyGraphTraverser { -public: +class TDependencyGraphOutput : public TDependencyGraphTraverser +{ + public: TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {} - virtual void visitSymbol(TGraphSymbol* symbol); - virtual void visitArgument(TGraphArgument* parameter); - virtual void visitFunctionCall(TGraphFunctionCall* functionCall); - virtual void visitSelection(TGraphSelection* selection); - virtual void visitLoop(TGraphLoop* loop); - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); + void visitSymbol(TGraphSymbol* symbol) override; + void visitArgument(TGraphArgument* parameter) override; + void visitFunctionCall(TGraphFunctionCall* functionCall) override; + void visitSelection(TGraphSelection* selection) override; + void visitLoop(TGraphLoop* loop) override; + void visitLogicalOp(TGraphLogicalOp* logicalOp) override; void outputAllSpanningTrees(TDependencyGraph& graph); -private: + private: void outputIndentation(); TInfoSinkBase& mSink; }; -#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h index f221199093..db31e6946c 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.h +++ b/src/3rdparty/angle/src/compiler/translator/glslang.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_GLSLANG_H_ +#define COMPILER_TRANSLATOR_GLSLANG_H_ + struct TParseContext; extern int glslang_initialize(TParseContext* context); extern int glslang_finalize(TParseContext* context); @@ -14,3 +17,4 @@ extern int glslang_scan(size_t count, TParseContext* context); extern int glslang_parse(TParseContext* context); +#endif // COMPILER_TRANSLATOR_GLSLANG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l index 518b78df11..ee4d28b6d6 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.l +++ b/src/3rdparty/angle/src/compiler/translator/glslang.l @@ -32,6 +32,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #pragma warning(disable: 4189) #pragma warning(disable: 4505) #pragma warning(disable: 4701) +#pragma warning(disable: 4702) #endif } @@ -70,6 +71,7 @@ static int floatsuffix_check(TParseContext* context); %option noyywrap nounput never-interactive %option yylineno reentrant bison-bridge bison-locations %option extra-type="TParseContext*" +%x FIELDS D [0-9] L [a-zA-Z_] @@ -358,7 +360,7 @@ O [0-7] ")" { return RIGHT_PAREN; } ("["|"<:") { return LEFT_BRACKET; } ("]"|":>") { return RIGHT_BRACKET; } -"." { return DOT; } +"." { BEGIN(FIELDS); return DOT; } "!" { return BANG; } "-" { return DASH; } "~" { return TILDE; } @@ -373,9 +375,16 @@ O [0-7] "&" { return AMPERSAND; } "?" { return QUESTION; } +<FIELDS>{L}({L}|{D})* { + BEGIN(INITIAL); + yylval->lex.string = NewPoolTString(yytext); + return FIELD_SELECTION; +} +<FIELDS>[ \t\v\f\r] {} + [ \t\v\n\f\r] { } -<<EOF>> { yyterminate(); } -. { assert(false); return 0; } +<*><<EOF>> { yyterminate(); } +<*>. { assert(false); return 0; } %% @@ -492,8 +501,8 @@ int floatsuffix_check(TParseContext* context) return(FLOATCONSTANT); } -void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { - context->error(*lloc, reason, yyget_text(context->scanner)); +void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) { + context->error(*lloc, reason, yyget_text(scanner)); context->recover(); } diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index e271de978c..6024898cb0 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -32,6 +32,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #pragma warning(disable: 4189) #pragma warning(disable: 4505) #pragma warning(disable: 4701) +#pragma warning(disable: 4702) #endif #include "angle_gl.h" @@ -41,12 +42,11 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #define YYENABLE_NLS 0 -#define YYLEX_PARAM context->scanner - %} %expect 1 /* One shift reduce conflict because of if | else */ -%pure-parser %parse-param {TParseContext* context} +%param {void *scanner} +%define api.pure full %locations %code requires { @@ -72,6 +72,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TIntermNodePair nodePair; TIntermTyped* intermTypedNode; TIntermAggregate* intermAggregate; + TIntermSwitch* intermSwitch; + TIntermCase* intermCase; }; union { TPublicType type; @@ -88,11 +90,11 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %{ extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); -extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); +extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason); #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ - if (YYID(N)) { \ + if (N) { \ (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ @@ -179,6 +181,8 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) %type <interm.intermNode> declaration external_declaration %type <interm.intermNode> for_init_statement compound_statement_no_new_scope %type <interm.nodePair> selection_rest_statement for_rest_statement +%type <interm.intermSwitch> switch_statement +%type <interm.intermCase> case_label %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope %type <interm> single_declaration init_declarator_list @@ -269,28 +273,14 @@ postfix_expression | function_call { $$ = $1; } - | postfix_expression DOT identifier { + | postfix_expression DOT FIELD_SELECTION { $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3); } | postfix_expression INC_OP { - if (context->lValueErrorCheck(@2, "++", $1)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2); - if ($$ == 0) { - context->unaryOpError(@2, "++", $1->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2); } | postfix_expression DEC_OP { - if (context->lValueErrorCheck(@2, "--", $1)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2); - if ($$ == 0) { - context->unaryOpError(@2, "--", $1->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2); } ; @@ -304,118 +294,12 @@ integer_expression function_call : function_call_or_method { - TFunction* fnCall = $1.function; - TOperator op = fnCall->getBuiltInOp(); - - if (op != EOpNull) + bool fatalError = false; + $$ = context->addFunctionCallOrMethod($1.function, $1.intermNode, @1, &fatalError); + if (fatalError) { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { - $$ = 0; - } else { - // - // It's a constructor, of type 'type'. - // - $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); - } - - if ($$ == 0) { - context->recover(); - $$ = context->intermediate.setAggregateOperator(0, op, @1); - } - $$->setType(type); - } else { - // - // Not a constructor. Find it in the symbol table. - // - const TFunction* fnCandidate; - bool builtIn; - fnCandidate = context->findFunction(@1, fnCall, context->shaderVersion, &builtIn); - if (fnCandidate) { - // - // A declared function. - // - if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck(@1, fnCandidate->getExtension())) { - context->recover(); - } - op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) { - // - // A function call mapped to a built-in operation. - // - if (fnCandidate->getParamCount() == 1) { - // - // 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(); - std::string extraInfo = extraInfoStream.str(); - context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str()); - YYERROR; - } - } else { - TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); - aggregate->setType(fnCandidate->getReturnType()); - aggregate->setPrecisionFromChildren(); - $$ = aggregate; - } - } else { - // This is a real function call - - 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) - 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) { - qual = fnCandidate->getParam(i).type->getQualifier(); - if (qual == EvqOut || qual == EvqInOut) { - if (context->lValueErrorCheck($$->getLine(), "assign", (*($$->getAsAggregate()->getSequence()))[i]->getAsTyped())) { - context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); - context->recover(); - } - } - } - } - } else { - // error message was put out by PaFindFunction() - // Put on a dummy node for error recovery - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); - context->recover(); - } + YYERROR; } - delete fnCall; } ; @@ -484,6 +368,13 @@ function_identifier TFunction *function = new TFunction($1.string, type); $$ = function; } + | FIELD_SELECTION { + if (context->reservedErrorCheck(@1, *$1.string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } ; unary_expression @@ -491,40 +382,14 @@ unary_expression $$ = $1; } | INC_OP unary_expression { - if (context->lValueErrorCheck(@1, "++", $2)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1); - if ($$ == 0) { - context->unaryOpError(@1, "++", $2->getCompleteString()); - context->recover(); - $$ = $2; - } + $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1); } | DEC_OP unary_expression { - if (context->lValueErrorCheck(@1, "--", $2)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1); - if ($$ == 0) { - context->unaryOpError(@1, "--", $2->getCompleteString()); - context->recover(); - $$ = $2; - } + $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1); } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, @1); - if ($$ == 0) { - const char* errorOp = ""; - switch($1.op) { - case EOpNegative: errorOp = "-"; break; - case EOpPositive: errorOp = "+"; break; - case EOpLogicalNot: errorOp = "!"; break; - default: break; - } - context->unaryOpError(@1, errorOp, $2->getCompleteString()); - context->recover(); - $$ = $2; - } + $$ = context->addUnaryMath($1.op, $2, @1); } else $$ = $2; } @@ -535,172 +400,117 @@ unary_operator : PLUS { $$.op = EOpPositive; } | DASH { $$.op = EOpNegative; } | BANG { $$.op = EOpLogicalNot; } + | TILDE { + ES3_ONLY("~", @$, "bit-wise operator"); + $$.op = EOpBitwiseNot; + } ; // Grammar Note: No '*' or '&' unary ops. Pointers are not supported. multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpMul, $1, $3, @2); } | multiplicative_expression SLASH unary_expression { - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpDiv, $1, $3, @2); + } + | multiplicative_expression PERCENT unary_expression { + ES3_ONLY("%", @2, "integer modulus operator"); + $$ = context->addBinaryMath(EOpIMod, $1, $3, @2); } ; additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpAdd, $1, $3, @2); } | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpSub, $1, $3, @2); } ; shift_expression : additive_expression { $$ = $1; } + | shift_expression LEFT_OP additive_expression { + ES3_ONLY("<<", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2); + } + | shift_expression RIGHT_OP additive_expression { + ES3_ONLY(">>", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2); + } ; relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2); } | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2); } | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2); } | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2); } ; equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2); } | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2); } ; and_expression : equality_expression { $$ = $1; } + | and_expression AMPERSAND equality_expression { + ES3_ONLY("&", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2); + } ; exclusive_or_expression : and_expression { $$ = $1; } + | exclusive_or_expression CARET and_expression { + ES3_ONLY("^", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2); + } ; inclusive_or_expression : exclusive_or_expression { $$ = $1; } + | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { + ES3_ONLY("|", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2); + } ; logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2); } ; logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2); } ; logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2); } ; @@ -727,12 +537,7 @@ assignment_expression | unary_expression assignment_operator assignment_expression { if (context->lValueErrorCheck(@2, "assign", $1)) context->recover(); - $$ = context->intermediate.addAssign($2.op, $1, $3, @2); - if ($$ == 0) { - context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addAssign($2.op, $1, $3, @2); } ; @@ -740,8 +545,32 @@ assignment_operator : EQUAL { $$.op = EOpAssign; } | MUL_ASSIGN { $$.op = EOpMulAssign; } | DIV_ASSIGN { $$.op = EOpDivAssign; } + | MOD_ASSIGN { + ES3_ONLY("%=", @$, "integer modulus operator"); + $$.op = EOpIModAssign; + } | ADD_ASSIGN { $$.op = EOpAddAssign; } | SUB_ASSIGN { $$.op = EOpSubAssign; } + | LEFT_ASSIGN { + ES3_ONLY("<<=", @$, "bit-wise operator"); + $$.op = EOpBitShiftLeftAssign; + } + | RIGHT_ASSIGN { + ES3_ONLY(">>=", @$, "bit-wise operator"); + $$.op = EOpBitShiftRightAssign; + } + | AND_ASSIGN { + ES3_ONLY("&=", @$, "bit-wise operator"); + $$.op = EOpBitwiseAndAssign; + } + | XOR_ASSIGN { + ES3_ONLY("^=", @$, "bit-wise operator"); + $$.op = EOpBitwiseXorAssign; + } + | OR_ASSIGN { + ES3_ONLY("|=", @$, "bit-wise operator"); + $$.op = EOpBitwiseOrAssign; + } ; expression @@ -877,7 +706,7 @@ function_prototype { // Insert the unmangled name to detect potential future redefinition as a variable. TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), $1->getReturnType()); - context->symbolTable.getOuterLevel()->insert(function); + context->symbolTable.getOuterLevel()->insertUnmangled(function); } // @@ -1599,12 +1428,14 @@ statement | simple_statement { $$ = $1; } ; -// Grammar Note: No labeled statements; 'goto' is not supported. +// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported. simple_statement : declaration_statement { $$ = $1; } | expression_statement { $$ = $1; } | selection_statement { $$ = $1; } + | switch_statement { $$ = $1; } + | case_label { $$ = $1; } | iteration_statement { $$ = $1; } | jump_statement { $$ = $1; } ; @@ -1677,7 +1508,21 @@ selection_rest_statement } ; -// Grammar Note: No 'switch'. Switch statements not supported. +switch_statement + : SWITCH LEFT_PAREN expression RIGHT_PAREN { ++context->mSwitchNestingLevel; } compound_statement { + $$ = context->addSwitch($3, $6, @1); + --context->mSwitchNestingLevel; + } + ; + +case_label + : CASE constant_expression COLON { + $$ = context->addCase($2, @1); + } + | DEFAULT COLON { + $$ = context->addDefault(@1); + } + ; condition // In 1996 c++ draft, conditions can include single declarations @@ -1703,22 +1548,22 @@ condition ; iteration_statement - : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { + : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->mLoopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); - --context->loopNestingLevel; + --context->mLoopNestingLevel; } - | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { + | DO { ++context->mLoopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { if (context->boolErrorCheck(@8, $6)) context->recover(); $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); - --context->loopNestingLevel; + --context->mLoopNestingLevel; } - | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { + | FOR LEFT_PAREN { context->symbolTable.push(); ++context->mLoopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1); - --context->loopNestingLevel; + --context->mLoopNestingLevel; } ; @@ -1753,40 +1598,20 @@ for_rest_statement jump_statement : CONTINUE SEMICOLON { - if (context->loopNestingLevel <= 0) { - context->error(@1, "continue statement only allowed in loops", ""); - context->recover(); - } - $$ = context->intermediate.addBranch(EOpContinue, @1); + $$ = context->addBranch(EOpContinue, @1); } | BREAK SEMICOLON { - if (context->loopNestingLevel <= 0) { - context->error(@1, "break statement only allowed in loops", ""); - context->recover(); - } - $$ = context->intermediate.addBranch(EOpBreak, @1); + $$ = context->addBranch(EOpBreak, @1); } | RETURN SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, @1); - if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error(@1, "non-void function must return a value", "return"); - context->recover(); - } + $$ = context->addBranch(EOpReturn, @1); } | RETURN expression SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $2, @1); - context->functionReturnsValue = true; - if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error(@1, "void function cannot return a value", "return"); - context->recover(); - } else if (*(context->currentFunctionType) != $2->getType()) { - context->error(@1, "function return is not matching type:", "return"); - context->recover(); - } + $$ = context->addBranch(EOpReturn, $2, @1); } | DISCARD SEMICOLON { FRAG_ONLY("discard", @1); - $$ = context->intermediate.addBranch(EOpKill, @1); + $$ = context->addBranch(EOpKill, @1); } ; @@ -1857,7 +1682,7 @@ function_definition // Remember the return type for later checking for RETURN statements. // context->currentFunctionType = &(prevDec->getReturnType()); - context->functionReturnsValue = false; + context->mFunctionReturnsValue = false; // // Insert parameters into the symbol table. @@ -1896,12 +1721,12 @@ function_definition } context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); $1.intermAggregate = paramNodes; - context->loopNestingLevel = 0; + context->mLoopNestingLevel = 0; } compound_statement_no_new_scope { //?? Check that all paths return a value if return type != void ? // May be best done as post process phase on intermediate code - if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { + if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->mFunctionReturnsValue) { context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); context->recover(); } @@ -1923,5 +1748,5 @@ function_definition %% int glslang_parse(TParseContext* context) { - return yyparse(context); + return yyparse(context, context->scanner); } diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index 00780f0454..07c50f0ce5 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -131,6 +131,25 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) case EOpDivAssign: out << "divide second child into first child"; break; + case EOpIModAssign: + out << "modulo second child into first child"; + break; + case EOpBitShiftLeftAssign: + out << "bit-wise shift first child left by second child"; + break; + case EOpBitShiftRightAssign: + out << "bit-wise shift first child right by second child"; + break; + case EOpBitwiseAndAssign: + out << "bit-wise and second child into first child"; + break; + case EOpBitwiseXorAssign: + out << "bit-wise xor second child into first child"; + break; + case EOpBitwiseOrAssign: + out << "bit-wise or second child into first child"; + break; + case EOpIndexDirect: out << "direct index"; break; @@ -159,6 +178,25 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) case EOpDiv: out << "divide"; break; + case EOpIMod: + out << "modulo"; + break; + case EOpBitShiftLeft: + out << "bit-wise shift left"; + break; + case EOpBitShiftRight: + out << "bit-wise shift right"; + break; + case EOpBitwiseAnd: + out << "bit-wise and"; + break; + case EOpBitwiseXor: + out << "bit-wise xor"; + break; + case EOpBitwiseOr: + out << "bit-wise or"; + break; + case EOpEqual: out << "Compare Equal"; break; @@ -211,6 +249,36 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) out << "\n"; + // Special handling for direct indexes. Because constant + // unions are not aware they are struct indexes, treat them + // here where we have that contextual knowledge. + if (node->getOp() == EOpIndexDirectStruct || + node->getOp() == EOpIndexDirectInterfaceBlock) + { + mDepth++; + node->getLeft()->traverse(this); + mDepth--; + + TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion(); + ASSERT(intermConstantUnion); + + OutputTreeText(out, intermConstantUnion, mDepth + 1); + + // The following code finds the field name from the constant union + const ConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer(); + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); + ASSERT(structure || interfaceBlock); + + const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields(); + + const TField *field = fields[constantUnion->getIConst()]; + + out << constantUnion->getIConst() << " (field '" << field->name() << "')"; + + return false; + } + return true; } @@ -226,6 +294,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) case EOpPositive: out << "Positive sign"; break; case EOpVectorLogicalNot: case EOpLogicalNot: out << "Negate conditional"; break; + case EOpBitwiseNot: out << "bit-wise not"; break; case EOpPostIncrement: out << "Post-Increment"; break; case EOpPostDecrement: out << "Post-Decrement"; break; @@ -241,6 +310,13 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) case EOpAcos: out << "arc cosine"; break; case EOpAtan: out << "arc tangent"; break; + case EOpSinh: out << "hyperbolic sine"; break; + case EOpCosh: out << "hyperbolic cosine"; break; + case EOpTanh: out << "hyperbolic tangent"; break; + case EOpAsinh: out << "arc hyperbolic sine"; break; + case EOpAcosh: out << "arc hyperbolic cosine"; break; + case EOpAtanh: out << "arc hyperbolic tangent"; break; + case EOpExp: out << "exp"; break; case EOpLog: out << "log"; break; case EOpExp2: out << "exp2"; break; @@ -251,8 +327,26 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) case EOpAbs: out << "Absolute value"; break; case EOpSign: out << "Sign"; break; case EOpFloor: out << "Floor"; break; + case EOpTrunc: out << "Truncate"; break; + case EOpRound: out << "Round"; break; + case EOpRoundEven: out << "Round half even"; break; case EOpCeil: out << "Ceiling"; break; case EOpFract: out << "Fraction"; break; + case EOpIsNan: out << "Is not a number"; break; + case EOpIsInf: out << "Is infinity"; break; + + case EOpFloatBitsToInt: out << "float bits to int"; break; + case EOpFloatBitsToUint: out << "float bits to uint"; break; + case EOpIntBitsToFloat: out << "int bits to float"; break; + case EOpUintBitsToFloat: out << "uint bits to float"; break; + + case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break; + case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break; + case EOpPackHalf2x16: out << "pack half 2x16"; break; + + case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break; + case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break; + case EOpUnpackHalf2x16: out << "unpack half 2x16"; break; case EOpLength: out << "length"; break; case EOpNormalize: out << "normalize"; break; @@ -260,6 +354,10 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) // case EOpDPdy: out << "dPdy"; break; // case EOpFwidth: out << "fwidth"; break; + case EOpDeterminant: out << "determinant"; break; + case EOpTranspose: out << "transpose"; break; + case EOpInverse: out << "inverse"; break; + case EOpAny: out << "any"; break; case EOpAll: out << "all"; break; @@ -326,6 +424,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorNotEqual: out << "NotEqual"; break; case EOpMod: out << "mod"; break; + case EOpModf: out << "modf"; break; case EOpPow: out << "pow"; break; case EOpAtan: out << "arc tangent"; break; @@ -345,6 +444,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpRefract: out << "refract"; break; case EOpMul: out << "component-wise multiply"; break; + case EOpOuterProduct: out << "outer product"; break; + case EOpDeclaration: out << "Declaration: "; break; case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; @@ -518,14 +619,13 @@ bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) // // This function is the one to call externally to start the traversal. // Individual functions can be initialized to 0 to skip processing of that -// type of node. It's children will still be processed. +// type of node. Its children will still be processed. // -void TIntermediate::outputTree(TIntermNode *root) +void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink) { - if (root == NULL) - return; + TOutputTraverser it(infoSink); - TOutputTraverser it(mInfoSink.info); + ASSERT(root); root->traverse(&it); } diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h index df70ee5d84..88634381fa 100644 --- a/src/3rdparty/angle/src/compiler/translator/length_limits.h +++ b/src/3rdparty/angle/src/compiler/translator/length_limits.h @@ -8,8 +8,8 @@ // length_limits.h // -#if !defined(__LENGTH_LIMITS_H) -#define __LENGTH_LIMITS_H 1 +#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_ +#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_ #include "GLSLANG/ShaderLang.h" @@ -18,4 +18,4 @@ size_t GetGlobalMaxTokenSize(ShShaderSpec spec); -#endif // !(defined(__LENGTH_LIMITS_H) +#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index 80d5f7fa7f..b8c7e82956 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -4,35 +4,36 @@ // found in the LICENSE file. // -#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ +#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ +#define COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; -class RestrictFragmentShaderTiming : TDependencyGraphTraverser { -public: - RestrictFragmentShaderTiming(TInfoSinkBase& sink); - void enforceRestrictions(const TDependencyGraph& graph); +class RestrictFragmentShaderTiming : TDependencyGraphTraverser +{ + public: + RestrictFragmentShaderTiming(TInfoSinkBase &sink); + void enforceRestrictions(const TDependencyGraph &graph); int numErrors() const { return mNumErrors; } - virtual void visitArgument(TGraphArgument* parameter); - virtual void visitSelection(TGraphSelection* selection); - virtual void visitLoop(TGraphLoop* loop); - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); + void visitArgument(TGraphArgument *parameter) override; + void visitSelection(TGraphSelection *selection) override; + void visitLoop(TGraphLoop *loop) override; + void visitLogicalOp(TGraphLogicalOp *logicalOp) override; -private: - void beginError(const TIntermNode* node); - void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph); - bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const; + private: + void beginError(const TIntermNode *node); + void validateUserDefinedFunctionCallUsage(const TDependencyGraph &graph); + bool isSamplingOp(const TIntermAggregate *intermFunctionCall) const; - TInfoSinkBase& mSink; + TInfoSinkBase &mSink; int mNumErrors; typedef std::set<TString> StringSet; StringSet mSamplingOps; }; -#endif // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ +#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index a6263567b4..74bfd0b5c2 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ +#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ +#define COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/InfoSink.h" @@ -28,4 +28,4 @@ private: int mNumErrors; }; -#endif // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ +#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index 8cc06a658a..42a995ee6f 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -307,7 +307,7 @@ void GetVariableTraverser::setTypeSpecificInfo( break; case EvqVaryingIn: case EvqVaryingOut: - if (mSymbolTable.isVaryingInvariant(name)) + if (mSymbolTable.isVaryingInvariant(std::string(name.c_str()))) { variable->isInvariant = true; } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index fb5308759e..68bae66168 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_UTIL_H -#define COMPILER_UTIL_H +#ifndef COMPILER_TRANSLATOR_UTIL_H_ +#define COMPILER_TRANSLATOR_UTIL_H_ #include <stack> @@ -37,7 +37,7 @@ bool IsVarying(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier); TString ArrayString(const TType &type); -class GetVariableTraverser +class GetVariableTraverser : angle::NonCopyable { public: GetVariableTraverser(const TSymbolTable &symbolTable); @@ -57,10 +57,8 @@ class GetVariableTraverser const TType &type, const TString &name, VarT *variable) {} const TSymbolTable &mSymbolTable; - - DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; } -#endif // COMPILER_UTIL_H +#endif // COMPILER_TRANSLATOR_UTIL_H_ diff --git a/src/3rdparty/angle/src/id/commit.h b/src/3rdparty/angle/src/id/commit.h new file mode 100644 index 0000000000..fd9a011d0c --- /dev/null +++ b/src/3rdparty/angle/src/id/commit.h @@ -0,0 +1,3 @@ +#define ANGLE_COMMIT_HASH "99f075dade7c" +#define ANGLE_COMMIT_HASH_SIZE 12 +#define ANGLE_COMMIT_DATE "2015-04-02 17:07:24 +0000" diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp index 28dd3d842e..651a012037 100644 --- a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp +++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "libEGL/AttributeMap.h" +#include "libANGLE/AttributeMap.h" namespace egl { @@ -15,9 +15,12 @@ AttributeMap::AttributeMap() AttributeMap::AttributeMap(const EGLint *attributes) { - for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2) + if (attributes) { - insert(curAttrib[0], curAttrib[1]); + for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + insert(curAttrib[0], curAttrib[1]); + } } } @@ -37,4 +40,14 @@ EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue; } +AttributeMap::const_iterator AttributeMap::begin() const +{ + return mAttributes.begin(); +} + +AttributeMap::const_iterator AttributeMap::end() const +{ + return mAttributes.end(); +} + } diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.h b/src/3rdparty/angle/src/libANGLE/AttributeMap.h index f2f082fe21..72b6edc3c7 100644 --- a/src/3rdparty/angle/src/libEGL/AttributeMap.h +++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.h @@ -4,8 +4,9 @@ // found in the LICENSE file. // -#ifndef LIBEGL_ATTRIBUTEMAP_H_ -#define LIBEGL_ATTRIBUTEMAP_H_ +#ifndef LIBANGLE_ATTRIBUTEMAP_H_ +#define LIBANGLE_ATTRIBUTEMAP_H_ + #include <EGL/egl.h> @@ -24,10 +25,15 @@ class AttributeMap virtual bool contains(EGLint key) const; virtual EGLint get(EGLint key, EGLint defaultValue) const; + typedef std::map<EGLint, EGLint>::const_iterator const_iterator; + + const_iterator begin() const; + const_iterator end() const; + private: std::map<EGLint, EGLint> mAttributes; }; } -#endif // LIBEGL_ATTRIBUTEMAP_H_ +#endif // LIBANGLE_ATTRIBUTEMAP_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libANGLE/BinaryStream.h index 4f7f5f2c85..50392e1d3f 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libANGLE/BinaryStream.h @@ -6,8 +6,8 @@ // BinaryStream.h: Provides binary serialization of simple types. -#ifndef LIBGLESV2_BINARYSTREAM_H_ -#define LIBGLESV2_BINARYSTREAM_H_ +#ifndef LIBANGLE_BINARYSTREAM_H_ +#define LIBANGLE_BINARYSTREAM_H_ #include "common/angleutils.h" #include "common/mathutil.h" @@ -17,10 +17,22 @@ #include <vector> #include <stdint.h> +template <typename T> +void StaticAssertIsFundamental() +{ + // c++11 STL is not available on OSX or Android +#if !defined(ANGLE_PLATFORM_APPLE) && !defined(ANGLE_PLATFORM_ANDROID) + static_assert(std::is_fundamental<T>::value, "T must be a fundamental type."); +#else + union { T dummy; } dummy; + static_cast<void>(dummy); +#endif +} + namespace gl { -class BinaryInputStream +class BinaryInputStream : angle::NonCopyable { public: BinaryInputStream(const void *data, size_t length) @@ -122,7 +134,6 @@ class BinaryInputStream } private: - DISALLOW_COPY_AND_ASSIGN(BinaryInputStream); bool mError; size_t mOffset; const uint8_t *mData; @@ -131,7 +142,7 @@ class BinaryInputStream template <typename T> void read(T *v, size_t num) { - META_ASSERT(std::is_fundamental<T>::value); + StaticAssertIsFundamental<T>(); size_t length = num * sizeof(T); @@ -153,7 +164,7 @@ class BinaryInputStream }; -class BinaryOutputStream +class BinaryOutputStream : angle::NonCopyable { public: BinaryOutputStream() @@ -191,13 +202,12 @@ class BinaryOutputStream } private: - DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream); std::vector<char> mData; template <typename T> void write(const T *v, size_t num) { - META_ASSERT(std::is_fundamental<T>::value); + StaticAssertIsFundamental<T>(); const char *asBytes = reinterpret_cast<const char*>(v); mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T)); } @@ -205,4 +215,4 @@ class BinaryOutputStream }; } -#endif // LIBGLESV2_BINARYSTREAM_H_ +#endif // LIBANGLE_BINARYSTREAM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libANGLE/Buffer.cpp index 3b2a1a912a..f394a6b1d1 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/Buffer.cpp @@ -8,9 +8,9 @@ // index data. Implements GL buffer objects and related functionality. // [OpenGL ES 2.0.24] section 2.9 page 21. -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/BufferImpl.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/renderer/Renderer.h" namespace gl { @@ -118,11 +118,4 @@ Error Buffer::unmap() return error; } -void Buffer::markTransformFeedbackUsage() -{ - // TODO: Only used by the DX11 backend. Refactor to a more appropriate place. - mBuffer->markTransformFeedbackUsage(); - mIndexRangeCache.clear(); -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libANGLE/Buffer.h index daa862ca0d..6793028e3b 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libANGLE/Buffer.h @@ -8,14 +8,14 @@ // index data. Implements GL buffer objects and related functionality. // [OpenGL ES 2.0.24] section 2.9 page 21. -#ifndef LIBGLESV2_BUFFER_H_ -#define LIBGLESV2_BUFFER_H_ +#ifndef LIBANGLE_BUFFER_H_ +#define LIBANGLE_BUFFER_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/renderer/IndexRangeCache.h" #include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/renderer/IndexRangeCache.h" namespace rx { @@ -48,14 +48,10 @@ class Buffer : public RefCountObject rx::BufferImpl *getImplementation() const { return mBuffer; } - void markTransformFeedbackUsage(); - rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; } private: - DISALLOW_COPY_AND_ASSIGN(Buffer); - rx::BufferImpl *mBuffer; GLenum mUsage; @@ -71,4 +67,4 @@ class Buffer : public RefCountObject } -#endif // LIBGLESV2_BUFFER_H_ +#endif // LIBANGLE_BUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libANGLE/Caps.cpp index 983800c0e6..086d0a02a2 100644 --- a/src/3rdparty/angle/src/libGLESv2/Caps.cpp +++ b/src/3rdparty/angle/src/libANGLE/Caps.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "libGLESv2/Caps.h" +#include "libANGLE/Caps.h" #include "common/debug.h" #include "common/angleutils.h" @@ -13,6 +13,14 @@ #include <algorithm> #include <sstream> +static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector) +{ + if (supported) + { + extensionVector->push_back(extension); + } +} + namespace gl { @@ -119,6 +127,9 @@ Extensions::Extensions() packReverseRowOrder(false), standardDerivatives(false), shaderTextureLOD(false), + shaderFramebufferFetch(false), + ARMshaderFramebufferFetch(false), + NVshaderFramebufferFetch(false), fragDepth(false), textureUsage(false), translatedShaderSource(false), @@ -126,14 +137,6 @@ Extensions::Extensions() { } -static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector) -{ - if (supported) - { - extensionVector->push_back(extension); - } -} - std::vector<std::string> Extensions::getStrings() const { std::vector<std::string> extensionStrings; @@ -173,6 +176,9 @@ std::vector<std::string> Extensions::getStrings() const InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); + InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings); + InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch,&extensionStrings); + InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings); InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); @@ -371,6 +377,41 @@ void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps); } +TypePrecision::TypePrecision() +{ + range[0] = 0; + range[1] = 0; + precision = 0; +} + +void TypePrecision::setIEEEFloat() +{ + range[0] = 127; + range[1] = 127; + precision = 23; +} + +void TypePrecision::setTwosComplementInt(unsigned int bits) +{ + range[0] = GLint(bits) - 1; + range[1] = GLint(bits) - 2; + precision = 0; +} + +void TypePrecision::setSimulatedInt(unsigned int r) +{ + range[0] = GLint(r); + range[1] = GLint(r); + precision = 0; +} + +void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const +{ + returnRange[0] = range[0]; + returnRange[1] = range[1]; + *returnPrecision = precision; +} + Caps::Caps() : maxElementIndex(0), max3DTextureSize(0), @@ -423,3 +464,64 @@ Caps::Caps() } } + +namespace egl +{ + +Caps::Caps() + : textureNPOT(false) +{ +} + +DisplayExtensions::DisplayExtensions() + : createContextRobustness(false), + d3dShareHandleClientBuffer(false), + surfaceD3DTexture2DShareHandle(false), + querySurfacePointer(false), + windowFixedSize(false), + postSubBuffer(false), + createContext(false) +{ +} + +std::vector<std::string> DisplayExtensions::getStrings() const +{ + std::vector<std::string> extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings); + InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings); + InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings); + InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings); + InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings); + InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings); + InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings); + + return extensionStrings; +} + + +ClientExtensions::ClientExtensions() + : clientExtensions(false), + platformBase(false), + platformANGLE(false), + platformANGLED3D(false), + platformANGLEOpenGL(false) +{ +} + +std::vector<std::string> ClientExtensions::getStrings() const +{ + std::vector<std::string> extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings); + InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings); + + return extensionStrings; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.h b/src/3rdparty/angle/src/libANGLE/Caps.h index a00e554176..37a634226a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Caps.h +++ b/src/3rdparty/angle/src/libANGLE/Caps.h @@ -1,18 +1,19 @@ -#ifndef LIBGLESV2_CAPS_H -#define LIBGLESV2_CAPS_H - // // 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 LIBANGLE_CAPS_H_ +#define LIBANGLE_CAPS_H_ + #include "angle_gl.h" +#include "libANGLE/angletypes.h" +#include <map> #include <set> -#include <unordered_map> -#include <vector> #include <string> +#include <vector> namespace gl { @@ -45,7 +46,7 @@ struct TextureCaps class TextureCapsMap { public: - typedef std::unordered_map<GLenum, TextureCaps>::const_iterator const_iterator; + typedef std::map<GLenum, TextureCaps>::const_iterator const_iterator; void insert(GLenum internalFormat, const TextureCaps &caps); void remove(GLenum internalFormat); @@ -58,7 +59,7 @@ class TextureCapsMap size_t size() const; private: - typedef std::unordered_map<GLenum, TextureCaps> InternalFormatToCapsMap; + typedef std::map<GLenum, TextureCaps> InternalFormatToCapsMap; InternalFormatToCapsMap mCapsMap; }; @@ -190,6 +191,15 @@ struct Extensions // GL_EXT_shader_texture_lod bool shaderTextureLOD; + // GL_EXT_shader_framebuffer_fetch + bool shaderFramebufferFetch; + + // GL_ARM_shader_framebuffer_fetch + bool ARMshaderFramebufferFetch; + + // GL_NV_shader_framebuffer_fetch + bool NVshaderFramebufferFetch; + // GL_EXT_frag_depth bool fragDepth; @@ -205,6 +215,20 @@ struct Extensions bool colorBufferFloat; }; +struct TypePrecision +{ + TypePrecision(); + + void setIEEEFloat(); + void setTwosComplementInt(unsigned int bits); + void setSimulatedInt(unsigned int range); + + void get(GLint *returnRange, GLint *returnPrecision) const; + + GLint range[2]; + GLint precision; +}; + struct Caps { Caps(); @@ -232,6 +256,18 @@ struct Caps std::vector<GLenum> compressedTextureFormats; std::vector<GLenum> programBinaryFormats; std::vector<GLenum> shaderBinaryFormats; + TypePrecision vertexHighpFloat; + TypePrecision vertexMediumpFloat; + TypePrecision vertexLowpFloat; + TypePrecision vertexHighpInt; + TypePrecision vertexMediumpInt; + TypePrecision vertexLowpInt; + TypePrecision fragmentHighpFloat; + TypePrecision fragmentMediumpFloat; + TypePrecision fragmentLowpFloat; + TypePrecision fragmentHighpInt; + TypePrecision fragmentMediumpInt; + TypePrecision fragmentLowpInt; GLuint64 maxServerWaitTimeout; // Table 6.31, implementation dependent vertex shader limits @@ -270,4 +306,69 @@ struct Caps } -#endif // LIBGLESV2_CAPS_H +namespace egl +{ + +struct Caps +{ + Caps(); + + // Support for NPOT surfaces + bool textureNPOT; +}; + +struct DisplayExtensions +{ + DisplayExtensions(); + + // Generate a vector of supported extension strings + std::vector<std::string> getStrings() const; + + // EGL_EXT_create_context_robustness + bool createContextRobustness; + + // EGL_ANGLE_d3d_share_handle_client_buffer + bool d3dShareHandleClientBuffer; + + // EGL_ANGLE_surface_d3d_texture_2d_share_handle + bool surfaceD3DTexture2DShareHandle; + + // EGL_ANGLE_query_surface_pointer + bool querySurfacePointer; + + // EGL_ANGLE_window_fixed_size + bool windowFixedSize; + + // EGL_NV_post_sub_buffer + bool postSubBuffer; + + // EGL_KHR_create_context + bool createContext; +}; + +struct ClientExtensions +{ + ClientExtensions(); + + // Generate a vector of supported extension strings + std::vector<std::string> getStrings() const; + + // EGL_EXT_client_extensions + bool clientExtensions; + + // EGL_EXT_platform_base + bool platformBase; + + // EGL_ANGLE_platform_angle + bool platformANGLE; + + // EGL_ANGLE_platform_angle_d3d + bool platformANGLED3D; + + // EGL_ANGLE_platform_angle_opengl + bool platformANGLEOpenGL; +}; + +} + +#endif // LIBANGLE_CAPS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.cpp b/src/3rdparty/angle/src/libANGLE/Compiler.cpp new file mode 100644 index 0000000000..7d0efea220 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Compiler.cpp @@ -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. +// + +// Compiler.cpp: implements the gl::Compiler class. + +#include "libANGLE/Compiler.h" +#include "libANGLE/renderer/CompilerImpl.h" + +#include "common/debug.h" + +namespace gl +{ + +Compiler::Compiler(rx::CompilerImpl *impl) + : mCompiler(impl) +{ + ASSERT(mCompiler); +} + +Compiler::~Compiler() +{ + SafeDelete(mCompiler); +} + +Error Compiler::release() +{ + return mCompiler->release(); +} + +rx::CompilerImpl *Compiler::getImplementation() +{ + return mCompiler; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.h b/src/3rdparty/angle/src/libANGLE/Compiler.h new file mode 100644 index 0000000000..05de15ec97 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Compiler.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. +// + +// Compiler.h: Defines the gl::Compiler class, abstracting the ESSL compiler +// that a GL context holds. + +#ifndef LIBANGLE_COMPILER_H_ +#define LIBANGLE_COMPILER_H_ + +#include "libANGLE/Error.h" + +namespace rx +{ +class CompilerImpl; +} + +namespace gl +{ + +class Compiler final +{ + public: + explicit Compiler(rx::CompilerImpl *impl); + ~Compiler(); + + Error release(); + + rx::CompilerImpl *getImplementation(); + + private: + rx::CompilerImpl *mCompiler; +}; + +} + +#endif // LIBANGLE_COMPILER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Config.cpp b/src/3rdparty/angle/src/libANGLE/Config.cpp new file mode 100644 index 0000000000..1b1fc50cb3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Config.cpp @@ -0,0 +1,275 @@ +// +// Copyright (c) 2002-2010 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. +// + +// Config.cpp: Implements the egl::Config class, describing the format, type +// and size for an egl::Surface. Implements EGLConfig and related functionality. +// [EGL 1.5] section 3.4 page 19. + +#include "libANGLE/Config.h" +#include "libANGLE/AttributeMap.h" + +#include <algorithm> +#include <vector> + +#include "angle_gl.h" +#include <EGL/eglext.h> + +#include "common/debug.h" + +namespace egl +{ + +Config::Config() + : renderTargetFormat(GL_NONE), + depthStencilFormat(GL_NONE), + bufferSize(0), + redSize(0), + greenSize(0), + blueSize(0), + luminanceSize(0), + alphaSize(0), + alphaMaskSize(0), + bindToTextureRGB(EGL_FALSE), + bindToTextureRGBA(EGL_FALSE), + colorBufferType(EGL_NONE), + configCaveat(EGL_NONE), + configID(0), + conformant(0), + depthSize(0), + level(0), + matchNativePixmap(EGL_FALSE), + maxPBufferWidth(0), + maxPBufferHeight(0), + maxPBufferPixels(0), + maxSwapInterval(0), + minSwapInterval(0), + nativeRenderable(EGL_FALSE), + nativeVisualID(0), + nativeVisualType(0), + renderableType(0), + sampleBuffers(0), + samples(0), + stencilSize(0), + surfaceType(0), + transparentType(EGL_NONE), + transparentRedValue(0), + transparentGreenValue(0), + transparentBlueValue(0) +{ +} + +EGLint ConfigSet::add(const Config &config) +{ + // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4) + EGLint id = mConfigs.size() + 1; + + Config copyConfig(config); + copyConfig.configID = id; + mConfigs.insert(std::make_pair(id, copyConfig)); + + return id; +} + +const Config &ConfigSet::get(EGLint id) const +{ + ASSERT(mConfigs.find(id) != mConfigs.end()); + return mConfigs.find(id)->second; +} + +void ConfigSet::clear() +{ + mConfigs.clear(); +} + +size_t ConfigSet::size() const +{ + return mConfigs.size(); +} + +bool ConfigSet::contains(const Config *config) const +{ + for (auto i = mConfigs.begin(); i != mConfigs.end(); i++) + { + const Config &item = i->second; + if (config == &item) + { + return true; + } + } + + return false; +} + +// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28. +class ConfigSorter +{ + public: + explicit ConfigSorter(const AttributeMap &attributeMap) + : mWantRed(false), + mWantGreen(false), + mWantBlue(false), + mWantAlpha(false), + mWantLuminance(false) + { + scanForWantedComponents(attributeMap); + } + + bool operator()(const Config *x, const Config *y) const + { + return (*this)(*x, *y); + } + + bool operator()(const Config &x, const Config &y) const + { + #define SORT(attribute) \ + if (x.attribute != y.attribute) \ + { \ + return x.attribute < y.attribute; \ + } + + static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value."); + SORT(configCaveat); + + static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value."); + SORT(colorBufferType); + + // By larger total number of color bits, only considering those that are requested to be > 0. + EGLint xComponentsSize = wantedComponentsSize(x); + EGLint yComponentsSize = wantedComponentsSize(y); + if (xComponentsSize != yComponentsSize) + { + return xComponentsSize > yComponentsSize; + } + + SORT(bufferSize); + SORT(sampleBuffers); + SORT(samples); + SORT(depthSize); + SORT(stencilSize); + SORT(alphaMaskSize); + SORT(nativeVisualType); + SORT(configID); + + #undef SORT + + return false; + } + + private: + void scanForWantedComponents(const AttributeMap &attributeMap) + { + // [EGL 1.5] section 3.4.1.2 page 30 + // Sorting rule #3: by larger total number of color bits, not considering + // components that are 0 or don't-care. + for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++) + { + EGLint attributeKey = attribIter->first; + EGLint attributeValue = attribIter->second; + if (attributeKey != 0 && attributeValue != EGL_DONT_CARE) + { + switch (attributeKey) + { + case EGL_RED_SIZE: mWantRed = true; break; + case EGL_GREEN_SIZE: mWantGreen = true; break; + case EGL_BLUE_SIZE: mWantBlue = true; break; + case EGL_ALPHA_SIZE: mWantAlpha = true; break; + case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; + } + } + } + } + + EGLint wantedComponentsSize(const Config &config) const + { + EGLint total = 0; + + if (mWantRed) total += config.redSize; + if (mWantGreen) total += config.greenSize; + if (mWantBlue) total += config.blueSize; + if (mWantAlpha) total += config.alphaSize; + if (mWantLuminance) total += config.luminanceSize; + + return total; + } + + bool mWantRed; + bool mWantGreen; + bool mWantBlue; + bool mWantAlpha; + bool mWantLuminance; +}; + +std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const +{ + std::vector<const Config*> result; + result.reserve(mConfigs.size()); + + for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++) + { + const Config &config = configIter->second; + bool match = true; + + for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++) + { + EGLint attributeKey = attribIter->first; + EGLint attributeValue = attribIter->second; + + switch (attributeKey) + { + case EGL_BUFFER_SIZE: match = config.bufferSize >= attributeValue; break; + case EGL_ALPHA_SIZE: match = config.alphaSize >= attributeValue; break; + case EGL_BLUE_SIZE: match = config.blueSize >= attributeValue; break; + case EGL_GREEN_SIZE: match = config.greenSize >= attributeValue; break; + case EGL_RED_SIZE: match = config.redSize >= attributeValue; break; + case EGL_DEPTH_SIZE: match = config.depthSize >= attributeValue; break; + case EGL_STENCIL_SIZE: match = config.stencilSize >= attributeValue; break; + case EGL_CONFIG_CAVEAT: match = config.configCaveat == (EGLenum)attributeValue; break; + case EGL_CONFIG_ID: match = config.configID == attributeValue; break; + case EGL_LEVEL: match = config.level >= attributeValue; break; + case EGL_NATIVE_RENDERABLE: match = config.nativeRenderable == (EGLBoolean)attributeValue; break; + case EGL_NATIVE_VISUAL_TYPE: match = config.nativeVisualType == attributeValue; break; + case EGL_SAMPLES: match = config.samples >= attributeValue; break; + case EGL_SAMPLE_BUFFERS: match = config.sampleBuffers >= attributeValue; break; + case EGL_SURFACE_TYPE: match = (config.surfaceType & attributeValue) == attributeValue; break; + case EGL_TRANSPARENT_TYPE: match = config.transparentType == (EGLenum)attributeValue; break; + case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break; + case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break; + case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break; + case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break; + case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)attributeValue; break; + case EGL_MIN_SWAP_INTERVAL: match = config.minSwapInterval == attributeValue; break; + case EGL_MAX_SWAP_INTERVAL: match = config.maxSwapInterval == attributeValue; break; + case EGL_LUMINANCE_SIZE: match = config.luminanceSize >= attributeValue; break; + case EGL_ALPHA_MASK_SIZE: match = config.alphaMaskSize >= attributeValue; break; + case EGL_COLOR_BUFFER_TYPE: match = config.colorBufferType == (EGLenum)attributeValue; break; + case EGL_RENDERABLE_TYPE: match = (config.renderableType & attributeValue) == attributeValue; break; + case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; + case EGL_CONFORMANT: match = (config.conformant & attributeValue) == attributeValue; break; + case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break; + case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break; + case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break; + default: UNREACHABLE(); + } + + if (!match) + { + break; + } + } + + if (match) + { + result.push_back(&config); + } + } + + // Sort the result + std::sort(result.begin(), result.end(), ConfigSorter(attributeMap)); + + return result; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Config.h b/src/3rdparty/angle/src/libANGLE/Config.h new file mode 100644 index 0000000000..aed8aedb1d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Config.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2002-2010 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. +// + +// Config.h: Defines the egl::Config class, describing the format, type +// and size for an egl::Surface. Implements EGLConfig and related functionality. +// [EGL 1.5] section 3.4 page 19. + +#ifndef INCLUDE_CONFIG_H_ +#define INCLUDE_CONFIG_H_ + +#include "libANGLE/AttributeMap.h" + +#include "common/angleutils.h" + +#include <EGL/egl.h> +#include <GLES2/gl2.h> + +#include <map> +#include <vector> + +namespace egl +{ + +struct Config +{ + Config(); + + GLenum renderTargetFormat; // TODO(geofflang): remove this + GLenum depthStencilFormat; // TODO(geofflang): remove this + + EGLint bufferSize; // Depth of the color buffer + EGLint redSize; // Bits of Red in the color buffer + EGLint greenSize; // Bits of Green in the color buffer + EGLint blueSize; // Bits of Blue in the color buffer + EGLint luminanceSize; // Bits of Luminance in the color buffer + EGLint alphaSize; // Bits of Alpha in the color buffer + EGLint alphaMaskSize; // Bits of Alpha Mask in the mask buffer + EGLBoolean bindToTextureRGB; // True if bindable to RGB textures. + EGLBoolean bindToTextureRGBA; // True if bindable to RGBA textures. + EGLenum colorBufferType; // Color buffer type + EGLenum configCaveat; // Any caveats for the configuration + EGLint configID; // Unique EGLConfig identifier + EGLint conformant; // Whether contexts created with this config are conformant + EGLint depthSize; // Bits of Z in the depth buffer + EGLint level; // Frame buffer level + EGLBoolean matchNativePixmap; // Match the native pixmap format + EGLint maxPBufferWidth; // Maximum width of pbuffer + EGLint maxPBufferHeight; // Maximum height of pbuffer + EGLint maxPBufferPixels; // Maximum size of pbuffer + EGLint maxSwapInterval; // Maximum swap interval + EGLint minSwapInterval; // Minimum swap interval + EGLBoolean nativeRenderable; // EGL_TRUE if native rendering APIs can render to surface + EGLint nativeVisualID; // Handle of corresponding native visual + EGLint nativeVisualType; // Native visual type of the associated visual + EGLint renderableType; // Which client rendering APIs are supported. + EGLint sampleBuffers; // Number of multisample buffers + EGLint samples; // Number of samples per pixel + EGLint stencilSize; // Bits of Stencil in the stencil buffer + EGLint surfaceType; // Which types of EGL surfaces are supported. + EGLenum transparentType; // Type of transparency supported + EGLint transparentRedValue; // Transparent red value + EGLint transparentGreenValue; // Transparent green value + EGLint transparentBlueValue; // Transparent blue value +}; + +class ConfigSet +{ + public: + EGLint add(const Config &config); + const Config &get(EGLint id) const; + + void clear(); + + size_t size() const; + + bool contains(const Config *config) const; + + // Filter configurations based on the table in [EGL 1.5] section 3.4.1.2 page 29 + std::vector<const Config*> filter(const AttributeMap &attributeMap) const; + + private: + typedef std::map<EGLint, const Config> ConfigMap; + ConfigMap mConfigs; +}; + +} + +#endif // INCLUDE_CONFIG_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libANGLE/Constants.h index 69c4823fb2..dc8f9555b8 100644 --- a/src/3rdparty/angle/src/libGLESv2/constants.h +++ b/src/3rdparty/angle/src/libANGLE/Constants.h @@ -6,8 +6,8 @@ // Contants.h: Defines some implementation specific and gl constants -#ifndef LIBGLESV2_CONSTANTS_H_ -#define LIBGLESV2_CONSTANTS_H_ +#ifndef LIBANGLE_CONSTANTS_H_ +#define LIBANGLE_CONSTANTS_H_ namespace gl { @@ -41,4 +41,4 @@ enum } -#endif // LIBGLESV2_CONSTANTS_H_ +#endif // LIBANGLE_CONSTANTS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp index 3772da6f42..1da5fdae95 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libANGLE/Context.cpp @@ -7,37 +7,36 @@ // Context.cpp: Implements the gl::Context class, managing all GL state and performing // rendering operations. It is the GLES2 specific implementation of EGLContext. -#include "libGLESv2/Context.h" +#include "libANGLE/Context.h" -#include "common/utilities.h" -#include "common/platform.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Fence.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/ResourceManager.h" -#include "libGLESv2/Sampler.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" - -#include <sstream> #include <iterator> +#include <sstream> + +#include "common/platform.h" +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Display.h" +#include "libANGLE/Fence.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/Query.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/validationES.h" +#include "libANGLE/renderer/Renderer.h" namespace gl { -Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) +Context::Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented @@ -47,6 +46,10 @@ Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *r mClientVersion = clientVersion; + mConfigID = config->configID; + mClientType = EGL_OPENGL_ES_API; + mRenderBuffer = EGL_NONE; + mFenceNVHandleAllocator.setBaseHandle(0); if (shareContext != NULL) @@ -65,19 +68,19 @@ Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *r // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - Texture2D *zeroTexture2D = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0); + Texture *zeroTexture2D = new Texture(mRenderer->createTexture(GL_TEXTURE_2D), 0, GL_TEXTURE_2D); mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D); - TextureCubeMap *zeroTextureCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0); + Texture *zeroTextureCube = new Texture(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0, GL_TEXTURE_CUBE_MAP); mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube); if (mClientVersion >= 3) { // TODO: These could also be enabled via extension - Texture3D *zeroTexture3D = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0); + Texture *zeroTexture3D = new Texture(mRenderer->createTexture(GL_TEXTURE_3D), 0, GL_TEXTURE_3D); mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D); - Texture2DArray *zeroTexture2DArray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0); + Texture *zeroTexture2DArray = new Texture(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0, GL_TEXTURE_2D_ARRAY); mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray); } @@ -120,25 +123,18 @@ Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *r mResetStatus = GL_NO_ERROR; mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; + + mCompiler = new Compiler(mRenderer->createCompiler(getData())); } Context::~Context() { - GLuint currentProgram = mState.getCurrentProgramId(); - if (currentProgram != 0) - { - Program *programObject = mResourceManager->getProgram(currentProgram); - if (programObject) - { - programObject->release(); - } - currentProgram = 0; - } - mState.setCurrentProgram(0, NULL); + mState.reset(); while (!mFramebufferMap.empty()) { - deleteFramebuffer(mFramebufferMap.begin()->first); + // Delete the framebuffer in reverse order to destroy the framebuffer zero last. + deleteFramebuffer(mFramebufferMap.rbegin()->first); } while (!mFenceNVMap.empty()) @@ -162,9 +158,9 @@ Context::~Context() deleteTransformFeedback(mTransformFeedbackMap.begin()->first); } - for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) + for (auto it = mZeroTextures.begin(); it != mZeroTextures.end(); ++it) { - i->second.set(NULL); + it->second.set(NULL); } mZeroTextures.clear(); @@ -172,6 +168,8 @@ Context::~Context() { mResourceManager->release(); } + + SafeDelete(mCompiler); } void Context::makeCurrent(egl::Surface *surface) @@ -187,14 +185,12 @@ void Context::makeCurrent(egl::Surface *surface) mHasBeenCurrent = true; } - // Wrap the existing swapchain resources into GL objects and assign them to the '0' names - rx::SwapChain *swapchain = surface->getSwapChain(); - - rx::RenderbufferImpl *colorbufferZero = mRenderer->createRenderbuffer(swapchain, false); - rx::RenderbufferImpl *depthStencilbufferZero = mRenderer->createRenderbuffer(swapchain, true); - Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); + // TODO(jmadill): do not allocate new pointers here + Framebuffer *framebufferZero = new DefaultFramebuffer(mCaps, mRenderer, surface); setFramebufferZero(framebufferZero); + + mRenderBuffer = surface->getRenderBuffer(); } // NOTE: this function should not assume that this context is current! @@ -239,7 +235,7 @@ GLsync Context::createFenceSync() { GLuint handle = mResourceManager->createFenceSync(); - return reinterpret_cast<GLsync>(handle); + return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle)); } GLuint Context::createVertexArray() @@ -348,7 +344,7 @@ void Context::deleteFenceSync(GLsync fenceSync) void Context::deleteVertexArray(GLuint vertexArray) { - VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray); + auto vertexArrayObject = mVertexArrayMap.find(vertexArray); if (vertexArrayObject != mVertexArrayMap.end()) { @@ -372,7 +368,7 @@ void Context::deleteSampler(GLuint sampler) void Context::deleteTransformFeedback(GLuint transformFeedback) { - TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(transformFeedback); + auto iter = mTransformFeedbackMap.find(transformFeedback); if (iter != mTransformFeedbackMap.end()) { detachTransformFeedback(transformFeedback); @@ -454,7 +450,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const VertexArray *Context::getVertexArray(GLuint handle) const { - VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle); + auto vertexArray = mVertexArrayMap.find(handle); if (vertexArray == mVertexArrayMap.end()) { @@ -526,7 +522,7 @@ void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); + mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer); } mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); @@ -536,7 +532,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); + mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer); } mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); @@ -626,58 +622,7 @@ void Context::bindPixelUnpackBuffer(GLuint buffer) void Context::useProgram(GLuint program) { - GLuint priorProgramId = mState.getCurrentProgramId(); - Program *priorProgram = mResourceManager->getProgram(priorProgramId); - - if (priorProgramId != program) - { - mState.setCurrentProgram(program, mResourceManager->getProgram(program)); - - if (priorProgram) - { - priorProgram->release(); - } - } -} - -Error Context::linkProgram(GLuint program) -{ - Program *programObject = mResourceManager->getProgram(program); - - 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 (programObject->isLinked() && program == mState.getCurrentProgramId()) - { - mState.setCurrentProgramBinary(programObject->getProgramBinary()); - } - - return Error(GL_NO_ERROR); -} - -Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) -{ - Program *programObject = mResourceManager->getProgram(program); - - 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 (programObject->isLinked() && program == mState.getCurrentProgramId()) - { - mState.setCurrentProgramBinary(programObject->getProgramBinary()); - } - - return Error(GL_NO_ERROR); + mState.setProgram(getProgram(program)); } void Context::bindTransformFeedback(GLuint transformFeedback) @@ -784,44 +729,19 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) Texture *Context::getTargetTexture(GLenum target) const { - if (!ValidTextureTarget(this, target)) - { - return NULL; - } - - switch (target) - { - case GL_TEXTURE_2D: return getTexture2D(); - case GL_TEXTURE_CUBE_MAP: return getTextureCubeMap(); - case GL_TEXTURE_3D: return getTexture3D(); - case GL_TEXTURE_2D_ARRAY: return getTexture2DArray(); - default: return NULL; - } -} - -Texture2D *Context::getTexture2D() const -{ - return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D)); -} + ASSERT(ValidTextureTarget(this, target)); -TextureCubeMap *Context::getTextureCubeMap() const -{ - return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP)); + return getSamplerTexture(mState.getActiveSampler(), target); } -Texture3D *Context::getTexture3D() const +Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const { - return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D)); + return mState.getSamplerTexture(sampler, type); } -Texture2DArray *Context::getTexture2DArray() const +Compiler *Context::getCompiler() const { - return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY)); -} - -Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const -{ - return mState.getSamplerTexture(sampler, type); + return mCompiler; } void Context::getBooleanv(GLenum pname, GLboolean *params) @@ -900,17 +820,6 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break; case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break; case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; - case GL_IMPLEMENTATION_COLOR_READ_TYPE: - case GL_IMPLEMENTATION_COLOR_READ_FORMAT: - { - GLenum internalFormat, format, type; - getCurrentReadFormatType(&internalFormat, &format, &type); - if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT) - *params = format; - else - *params = type; - } - break; case GL_MAX_VIEWPORT_DIMS: { params[0] = mCaps.maxViewportWidth; @@ -1025,6 +934,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *numParams = mCaps.shaderBinaryFormats.size(); } return true; + case GL_MAX_VERTEX_ATTRIBS: case GL_MAX_VERTEX_UNIFORM_VECTORS: case GL_MAX_VARYING_VECTORS: @@ -1286,62 +1196,6 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned return false; } -Error Context::clear(GLbitfield mask) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clear(getData(), mask); -} - -Error Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferfv(getData(), buffer, drawbuffer, values); -} - -Error Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferuiv(getData(), buffer, drawbuffer, values); -} - -Error Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferiv(getData(), buffer, drawbuffer, values); -} - -Error Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - 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) -{ - return mRenderer->readPixels(getData(), x, y, width, height, format, type, bufSize, pixels); -} - Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { return mRenderer->drawArrays(getData(), mode, first, count, instances); @@ -1354,10 +1208,14 @@ Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange); } -// Implements glFlush when block is false, glFinish when block is true -Error Context::sync(bool block) +Error Context::flush() { - return mRenderer->sync(block); + return mRenderer->flush(); +} + +Error Context::finish() +{ + return mRenderer->finish(); } void Context::recordError(const Error &error) @@ -1391,7 +1249,10 @@ GLenum Context::getResetStatus() { // mResetStatus will be set by the markContextLost callback // in the case a notification is sent - mRenderer->testDeviceLost(true); + if (mRenderer->testDeviceLost()) + { + mRenderer->notifyDeviceLost(); + } } GLenum status = mResetStatus; @@ -1419,6 +1280,21 @@ int Context::getClientVersion() const return mClientVersion; } +EGLint Context::getConfigID() const +{ + return mConfigID; +} + +EGLenum Context::getClientType() const +{ + return mClientType; +} + +EGLenum Context::getRenderBuffer() const +{ + return mRenderBuffer; +} + const Caps &Context::getCaps() const { return mCaps; @@ -1434,22 +1310,6 @@ const Extensions &Context::getExtensions() const return mExtensions; } -void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) -{ - Framebuffer *framebuffer = mState.getReadFramebuffer(); - ASSERT(framebuffer && framebuffer->completeness(getData()) == GL_FRAMEBUFFER_COMPLETE); - - FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); - ASSERT(attachment); - - GLenum actualFormat = attachment->getActualFormat(); - const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat); - - *internalFormat = actualFormat; - *format = actualFormatInfo.format; - *type = actualFormatInfo.type; -} - void Context::detachTexture(GLuint texture) { // Simple pass-through to State's detachTexture method, as textures do not require @@ -1487,12 +1347,12 @@ void Context::detachFramebuffer(GLuint framebuffer) // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. - if (mState.removeReadFramebufferBinding(framebuffer)) + if (mState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0) { bindReadFramebuffer(0); } - if (mState.removeDrawFramebufferBinding(framebuffer)) + if (mState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0) { bindDrawFramebuffer(0); } @@ -1660,19 +1520,6 @@ size_t Context::getExtensionStringCount() const return mExtensionStrings.size(); } -Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - return mRenderer->blitFramebuffer(getData(), srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); -} - -void Context::releaseShaderCompiler() -{ - mRenderer->releaseShaderCompiler(); -} - void Context::initCaps(GLuint clientVersion) { mCaps = mRenderer->getRendererCaps(); @@ -1738,32 +1585,3 @@ Data Context::getData() const } } - -extern "C" -{ -gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) -{ - return new gl::Context(clientVersion, shareContext, renderer, notifyResets, robustAccess); -} - -void glDestroyContext(gl::Context *context) -{ - delete context; - - if (context == gl::getContext()) - { - gl::makeCurrent(NULL, NULL, NULL); - } -} - -void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface) -{ - gl::makeCurrent(context, display, surface); -} - -gl::Context *glGetCurrentContext() -{ - return gl::getContext(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libANGLE/Context.h index 0699592d91..eeada43355 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libANGLE/Context.h @@ -7,26 +7,24 @@ // Context.h: Defines the gl::Context class, managing all GL state and performing // rendering operations. It is the GLES2 specific implementation of EGLContext. -#ifndef LIBGLESV2_CONTEXT_H_ -#define LIBGLESV2_CONTEXT_H_ +#ifndef LIBANGLE_CONTEXT_H_ +#define LIBANGLE_CONTEXT_H_ #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/VertexAttribute.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Data.h" +#include "libANGLE/Error.h" +#include "libANGLE/HandleAllocator.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/angletypes.h" #include "angle_gl.h" #include <string> #include <set> #include <map> -#include <unordered_map> -#include <array> namespace rx { @@ -36,18 +34,15 @@ class Renderer; namespace egl { class Surface; +struct Config; } namespace gl { +class Compiler; class Shader; class Program; -class ProgramBinary; class Texture; -class Texture2D; -class TextureCubeMap; -class Texture3D; -class Texture2DArray; class Framebuffer; class Renderbuffer; class FenceNV; @@ -60,10 +55,10 @@ class VertexArray; class Sampler; class TransformFeedback; -class Context +class Context final : angle::NonCopyable { public: - Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); + Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); virtual ~Context(); @@ -125,8 +120,6 @@ class Context void bindPixelPackBuffer(GLuint buffer); void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); - 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); @@ -155,13 +148,10 @@ class Context TransformFeedback *getTransformFeedback(GLuint handle) const; Texture *getTargetTexture(GLenum target) const; - Texture2D *getTexture2D() const; - TextureCubeMap *getTextureCubeMap() const; - Texture3D *getTexture3D() const; - Texture2DArray *getTexture2DArray() const; - Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; + Compiler *getCompiler() const; + bool isSampler(GLuint samplerName) const; void getBooleanv(GLenum pname, GLboolean *params); @@ -175,18 +165,12 @@ class Context bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); - Error clear(GLbitfield mask); - 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); - Error sync(bool block); // flush/finish + Error flush(); + Error finish(); void recordError(const Error &error); @@ -196,6 +180,10 @@ class Context virtual int getClientVersion() const; + EGLint getConfigID() const; + EGLenum getClientType() const; + EGLenum getRenderBuffer() const; + const Caps &getCaps() const; const TextureCapsMap &getTextureCaps() const; const Extensions &getExtensions() const; @@ -206,11 +194,6 @@ class Context const std::string &getExtensionString(size_t idx) const; size_t getExtensionStringCount() const; - void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type); - - 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; } @@ -218,11 +201,7 @@ class Context Data getData() const; - void releaseShaderCompiler(); - private: - DISALLOW_COPY_AND_ASSIGN(Context); - void detachBuffer(GLuint buffer); void detachTexture(GLuint texture); void detachFramebuffer(GLuint framebuffer); @@ -241,31 +220,38 @@ class Context TextureCapsMap mTextureCaps; Extensions mExtensions; + // Shader compiler + Compiler *mCompiler; + rx::Renderer *const mRenderer; State mState; int mClientVersion; + EGLint mConfigID; + EGLenum mClientType; + EGLenum mRenderBuffer; + TextureMap mZeroTextures; - typedef std::unordered_map<GLuint, Framebuffer*> FramebufferMap; + typedef std::map<GLuint, Framebuffer*> FramebufferMap; FramebufferMap mFramebufferMap; HandleAllocator mFramebufferHandleAllocator; - typedef std::unordered_map<GLuint, FenceNV*> FenceNVMap; + typedef std::map<GLuint, FenceNV*> FenceNVMap; FenceNVMap mFenceNVMap; HandleAllocator mFenceNVHandleAllocator; - typedef std::unordered_map<GLuint, Query*> QueryMap; + typedef std::map<GLuint, Query*> QueryMap; QueryMap mQueryMap; HandleAllocator mQueryHandleAllocator; - typedef std::unordered_map<GLuint, VertexArray*> VertexArrayMap; + typedef std::map<GLuint, VertexArray*> VertexArrayMap; VertexArrayMap mVertexArrayMap; HandleAllocator mVertexArrayHandleAllocator; BindingPointer<TransformFeedback> mTransformFeedbackZero; - typedef std::unordered_map<GLuint, TransformFeedback*> TransformFeedbackMap; + typedef std::map<GLuint, TransformFeedback*> TransformFeedbackMap; TransformFeedbackMap mTransformFeedbackMap; HandleAllocator mTransformFeedbackAllocator; @@ -288,4 +274,4 @@ class Context }; } -#endif // INCLUDE_CONTEXT_H_ +#endif // LIBANGLE_CONTEXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Data.cpp b/src/3rdparty/angle/src/libANGLE/Data.cpp index 3ddf591d77..7832e21b23 100644 --- a/src/3rdparty/angle/src/libGLESv2/Data.cpp +++ b/src/3rdparty/angle/src/libANGLE/Data.cpp @@ -6,8 +6,8 @@ // Data.cpp: Container class for all GL relevant state, caps and objects -#include "libGLESv2/Data.h" -#include "libGLESv2/ResourceManager.h" +#include "libANGLE/Data.h" +#include "libANGLE/ResourceManager.h" namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libANGLE/Data.h index 9234403e13..7eb6827dfc 100644 --- a/src/3rdparty/angle/src/libGLESv2/Data.h +++ b/src/3rdparty/angle/src/libANGLE/Data.h @@ -6,15 +6,15 @@ // Data.h: Container class for all GL relevant state, caps and objects -#ifndef LIBGLESV2_DATA_H_ -#define LIBGLESV2_DATA_H_ +#ifndef LIBANGLE_DATA_H_ +#define LIBANGLE_DATA_H_ -#include "libGLESv2/State.h" +#include "libANGLE/State.h" namespace gl { -struct Data +struct Data final { public: Data(GLint clientVersion, const State &state, const Caps &caps, @@ -35,4 +35,4 @@ struct Data } -#endif // LIBGLESV2_DATA_H_ +#endif // LIBANGLE_DATA_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp new file mode 100644 index 0000000000..1f54f82dea --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Display.cpp @@ -0,0 +1,675 @@ +// +// Copyright (c) 2002-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. +// + +// Display.cpp: Implements the egl::Display class, representing the abstract +// display on which graphics are drawn. Implements EGLDisplay. +// [EGL 1.4] section 2.1.2 page 3. + +#include "libANGLE/Display.h" + +#include <algorithm> +#include <iterator> +#include <map> +#include <sstream> +#include <vector> + +#include <platform/Platform.h> +#include <EGL/eglext.h> + +#include "common/debug.h" +#include "common/mathutil.h" +#include "common/platform.h" +#include "libANGLE/Context.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/DisplayImpl.h" + +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/DisplayD3D.h" +#endif + +#if defined(ANGLE_ENABLE_OPENGL) +# if defined(ANGLE_PLATFORM_WINDOWS) +# include "libANGLE/renderer/gl/wgl/DisplayWGL.h" +# else +# error Unsupported OpenGL platform. +# endif +#endif + +namespace egl +{ + +namespace +{ + +class DefaultPlatform : public angle::Platform +{ +public: + DefaultPlatform() {} + ~DefaultPlatform() override {} +}; + +DefaultPlatform *defaultPlatform = nullptr; + +void InitDefaultPlatformImpl() +{ + if (ANGLEPlatformCurrent() == nullptr) + { + if (defaultPlatform == nullptr) + { + defaultPlatform = new DefaultPlatform(); + } + + ANGLEPlatformInitialize(defaultPlatform); + } +} + +void DeinitDefaultPlatformImpl() +{ + if (defaultPlatform != nullptr) + { + if (ANGLEPlatformCurrent() == defaultPlatform) + { + ANGLEPlatformShutdown(); + } + + SafeDelete(defaultPlatform); + } +} + +typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap; +// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface +// associated with it. +static WindowSurfaceMap *GetWindowSurfaces() +{ + static WindowSurfaceMap windowSurfaces; + return &windowSurfaces; +} + +typedef std::map<EGLNativeDisplayType, Display*> DisplayMap; +static DisplayMap *GetDisplayMap() +{ + static DisplayMap displays; + return &displays; +} + +rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap) +{ + rx::DisplayImpl *impl = nullptr; + EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + switch (displayType) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + // Default to D3D displays + impl = new rx::DisplayD3D(); +#else + // No display available + UNREACHABLE(); +#endif + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + impl = new rx::DisplayD3D(); +#else + // A D3D display was requested on a platform that doesn't support it + UNREACHABLE(); +#endif + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: +#if defined(ANGLE_ENABLE_OPENGL) +#if defined(ANGLE_PLATFORM_WINDOWS) + impl = new rx::DisplayWGL(); +#else +#error Unsupported OpenGL platform. +#endif +#else + UNREACHABLE(); +#endif + break; + + default: + UNREACHABLE(); + break; + } + + ASSERT(impl != nullptr); + return impl; +} + +} + +Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap) +{ + // Initialize the global platform if not already + InitDefaultPlatformImpl(); + + Display *display = NULL; + + DisplayMap *displays = GetDisplayMap(); + DisplayMap::const_iterator iter = displays->find(displayId); + if (iter != displays->end()) + { + display = iter->second; + } + + if (display == nullptr) + { + // Validate the native display + if (!Display::isValidNativeDisplay(displayId)) + { + return NULL; + } + + display = new Display(displayId); + displays->insert(std::make_pair(displayId, display)); + } + + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + rx::DisplayImpl* impl = CreateDisplayImpl(attribMap); + display->setAttributes(impl, attribMap); + } + + return display; +} + +Display::Display(EGLNativeDisplayType displayId) + : mImplementation(nullptr), + mDisplayId(displayId), + mAttributeMap(), + mConfigSet(), + mContextSet(), + mInitialized(false), + mCaps(), + mDisplayExtensions(), + mDisplayExtensionString(), + mVendorString() +{ +} + +Display::~Display() +{ + terminate(); + + DisplayMap *displays = GetDisplayMap(); + DisplayMap::iterator iter = displays->find(mDisplayId); + if (iter != displays->end()) + { + displays->erase(iter); + } + + SafeDelete(mImplementation); +} + +void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap) +{ + ASSERT(!mInitialized); + + ASSERT(impl != nullptr); + SafeDelete(mImplementation); + mImplementation = impl; + + mAttributeMap = attribMap; +} + +Error Display::initialize() +{ + ASSERT(mImplementation != nullptr); + + if (isInitialized()) + { + return Error(EGL_SUCCESS); + } + + Error error = mImplementation->initialize(this); + if (error.isError()) + { + return error; + } + + mCaps = mImplementation->getCaps(); + + mConfigSet = mImplementation->generateConfigs(); + if (mConfigSet.size() == 0) + { + mImplementation->terminate(); + return Error(EGL_NOT_INITIALIZED); + } + + initDisplayExtensions(); + initVendorString(); + + mInitialized = true; + return Error(EGL_SUCCESS); +} + +void Display::terminate() +{ + makeCurrent(nullptr, nullptr, nullptr); + + while (!mContextSet.empty()) + { + destroyContext(*mContextSet.begin()); + } + + mConfigSet.clear(); + + mImplementation->terminate(); + mInitialized = false; + + // De-init default platform + DeinitDefaultPlatformImpl(); +} + +std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const +{ + return mConfigSet.filter(attribs); +} + +bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value) +{ + switch (attribute) + { + case EGL_BUFFER_SIZE: *value = configuration->bufferSize; break; + case EGL_ALPHA_SIZE: *value = configuration->alphaSize; break; + case EGL_BLUE_SIZE: *value = configuration->blueSize; break; + case EGL_GREEN_SIZE: *value = configuration->greenSize; break; + case EGL_RED_SIZE: *value = configuration->redSize; break; + case EGL_DEPTH_SIZE: *value = configuration->depthSize; break; + case EGL_STENCIL_SIZE: *value = configuration->stencilSize; break; + case EGL_CONFIG_CAVEAT: *value = configuration->configCaveat; break; + case EGL_CONFIG_ID: *value = configuration->configID; break; + case EGL_LEVEL: *value = configuration->level; break; + case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break; + case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break; + case EGL_SAMPLES: *value = configuration->samples; break; + case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break; + case EGL_SURFACE_TYPE: *value = configuration->surfaceType; break; + case EGL_TRANSPARENT_TYPE: *value = configuration->transparentType; break; + case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->transparentBlueValue; break; + case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->transparentGreenValue; break; + case EGL_TRANSPARENT_RED_VALUE: *value = configuration->transparentRedValue; break; + case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->bindToTextureRGB; break; + case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->bindToTextureRGBA; break; + case EGL_MIN_SWAP_INTERVAL: *value = configuration->minSwapInterval; break; + case EGL_MAX_SWAP_INTERVAL: *value = configuration->maxSwapInterval; break; + case EGL_LUMINANCE_SIZE: *value = configuration->luminanceSize; break; + case EGL_ALPHA_MASK_SIZE: *value = configuration->alphaMaskSize; break; + case EGL_COLOR_BUFFER_TYPE: *value = configuration->colorBufferType; break; + case EGL_RENDERABLE_TYPE: *value = configuration->renderableType; break; + case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break; + case EGL_CONFORMANT: *value = configuration->conformant; break; + case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break; + case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break; + case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break; + default: + return false; + } + + return true; +} + +Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs, + Surface **outSurface) +{ + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createWindowSurface(configuration, window, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_WINDOW_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end()); + windowSurfaces->insert(std::make_pair(window, surface)); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createPbufferSurface(configuration, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, + const AttributeMap &attribs, Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs, + Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createPixmapSurface(configuration, nativePixmap, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_PIXMAP_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, + gl::Context **outContext) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + gl::Context *context = nullptr; + Error error = mImplementation->createContext(configuration, shareContext, attribs, &context); + if (error.isError()) + { + return error; + } + + ASSERT(context != nullptr); + mContextSet.insert(context); + + ASSERT(outContext != nullptr); + *outContext = context; + return Error(EGL_SUCCESS); +} + +Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + Error error = mImplementation->makeCurrent(drawSurface, readSurface, context); + if (error.isError()) + { + return error; + } + + if (context && drawSurface) + { + context->makeCurrent(drawSurface); + } + + return egl::Error(EGL_SUCCESS); +} + +Error Display::restoreLostDevice() +{ + for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) + { + if ((*ctx)->isResetNotificationEnabled()) + { + // If reset notifications have been requested, application must delete all contexts first + return Error(EGL_CONTEXT_LOST); + } + } + + return mImplementation->restoreLostDevice(); +} + +void Display::destroySurface(Surface *surface) +{ + if (surface->getType() == EGL_WINDOW_BIT) + { + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces); + + bool surfaceRemoved = false; + for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++) + { + if (iter->second == surface) + { + windowSurfaces->erase(iter); + surfaceRemoved = true; + break; + } + } + + ASSERT(surfaceRemoved); + } + + mImplementation->destroySurface(surface); +} + +void Display::destroyContext(gl::Context *context) +{ + mContextSet.erase(context); + SafeDelete(context); +} + +bool Display::isDeviceLost() const +{ + ASSERT(isInitialized()); + return mImplementation->isDeviceLost(); +} + +bool Display::testDeviceLost() +{ + ASSERT(isInitialized()); + return mImplementation->testDeviceLost(); +} + +void Display::notifyDeviceLost() +{ + for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) + { + (*context)->markContextLost(); + } +} + +const Caps &Display::getCaps() const +{ + return mCaps; +} + +bool Display::isInitialized() const +{ + return mInitialized; +} + +bool Display::isValidConfig(const Config *config) const +{ + return mConfigSet.contains(config); +} + +bool Display::isValidContext(gl::Context *context) const +{ + return mContextSet.find(context) != mContextSet.end(); +} + +bool Display::isValidSurface(Surface *surface) const +{ + return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end(); +} + +bool Display::hasExistingWindowSurface(EGLNativeWindowType window) +{ + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces); + + return windowSurfaces->find(window) != windowSurfaces->end(); +} + +static ClientExtensions GenerateClientExtensions() +{ + ClientExtensions extensions; + + extensions.clientExtensions = true; + extensions.platformBase = true; + extensions.platformANGLE = true; + +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + extensions.platformANGLED3D = true; +#endif + +#if defined(ANGLE_ENABLE_OPENGL) + extensions.platformANGLEOpenGL = true; +#endif + + return extensions; +} + +template <typename T> +static std::string GenerateExtensionsString(const T &extensions) +{ + std::vector<std::string> extensionsVector = extensions.getStrings(); + + std::ostringstream stream; + std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " ")); + return stream.str(); +} + +const ClientExtensions &Display::getClientExtensions() +{ + static const ClientExtensions clientExtensions = GenerateClientExtensions(); + return clientExtensions; +} + +const std::string &Display::getClientExtensionString() +{ + static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions()); + return clientExtensionsString; +} + +void Display::initDisplayExtensions() +{ + mDisplayExtensions = mImplementation->getExtensions(); + mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions); +} + +bool Display::isValidNativeWindow(EGLNativeWindowType window) const +{ + return mImplementation->isValidNativeWindow(window); +} + +bool Display::isValidNativeDisplay(EGLNativeDisplayType display) +{ + // TODO(jmadill): handle this properly + if (display == EGL_DEFAULT_DISPLAY) + { + return true; + } + +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (display == EGL_SOFTWARE_DISPLAY_ANGLE || + display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + display == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + return true; + } + return (WindowFromDC(display) != NULL); +#else + return true; +#endif +} + +void Display::initVendorString() +{ + mVendorString = mImplementation->getVendorString(); +} + +const DisplayExtensions &Display::getExtensions() const +{ + return mDisplayExtensions; +} + +const std::string &Display::getExtensionString() const +{ + return mDisplayExtensionString; +} + +const std::string &Display::getVendorString() const +{ + return mVendorString; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h new file mode 100644 index 0000000000..5ab3f9c0e9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Display.h @@ -0,0 +1,124 @@ +// +// Copyright (c) 2002-2013 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. +// + +// Display.h: Defines the egl::Display class, representing the abstract +// display on which graphics are drawn. Implements EGLDisplay. +// [EGL 1.4] section 2.1.2 page 3. + +#ifndef LIBANGLE_DISPLAY_H_ +#define LIBANGLE_DISPLAY_H_ + +#include <set> +#include <vector> + +#include "libANGLE/Error.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Config.h" +#include "libANGLE/AttributeMap.h" + +namespace gl +{ +class Context; +} + +namespace rx +{ +class DisplayImpl; +} + +namespace egl +{ +class Surface; + +class Display final : angle::NonCopyable +{ + public: + ~Display(); + + Error initialize(); + void terminate(); + + static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); + + static const ClientExtensions &getClientExtensions(); + static const std::string &getClientExtensionString(); + + std::vector<const Config*> getConfigs(const egl::AttributeMap &attribs) const; + bool getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value); + + Error createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs, + Surface **outSurface); + Error createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface); + Error createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, const AttributeMap &attribs, + Surface **outSurface); + Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs, + Surface **outSurface); + + Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, + gl::Context **outContext); + + Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context); + + void destroySurface(egl::Surface *surface); + void destroyContext(gl::Context *context); + + bool isInitialized() const; + bool isValidConfig(const Config *config) const; + bool isValidContext(gl::Context *context) const; + bool isValidSurface(egl::Surface *surface) const; + bool isValidNativeWindow(EGLNativeWindowType window) const; + + static bool isValidNativeDisplay(EGLNativeDisplayType display); + static bool hasExistingWindowSurface(EGLNativeWindowType window); + + bool isDeviceLost() const; + bool testDeviceLost(); + void notifyDeviceLost(); + + const Caps &getCaps() const; + + const DisplayExtensions &getExtensions() const; + const std::string &getExtensionString() const; + const std::string &getVendorString() const; + + const AttributeMap &getAttributeMap() const { return mAttributeMap; } + EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; } + + rx::DisplayImpl *getImplementation() { return mImplementation; } + + private: + Display(EGLNativeDisplayType displayId); + + void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap); + + Error restoreLostDevice(); + + void initDisplayExtensions(); + void initVendorString(); + + rx::DisplayImpl *mImplementation; + + EGLNativeDisplayType mDisplayId; + AttributeMap mAttributeMap; + + ConfigSet mConfigSet; + + typedef std::set<gl::Context*> ContextSet; + ContextSet mContextSet; + + bool mInitialized; + + Caps mCaps; + + DisplayExtensions mDisplayExtensions; + std::string mDisplayExtensionString; + + std::string mVendorString; +}; + +} + +#endif // LIBANGLE_DISPLAY_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Error.cpp b/src/3rdparty/angle/src/libANGLE/Error.cpp new file mode 100644 index 0000000000..e17f26bec4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Error.cpp @@ -0,0 +1,86 @@ +// +// 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 and gl::Error classes which encapsulate API errors +// and optional error messages. + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include <cstdarg> + +namespace gl +{ + +Error::Error(GLenum errorCode, const char *msg, ...) + : mCode(errorCode), + mMessage(nullptr) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +void Error::createMessageString() const +{ + if (mMessage == nullptr) + { + mMessage = new std::string(); + } +} + +const std::string &Error::getMessage() const +{ + createMessageString(); + return *mMessage; +} + +} + +namespace egl +{ + +Error::Error(EGLint errorCode, const char *msg, ...) + : mCode(errorCode), + mID(0), + mMessage(nullptr) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) + : mCode(errorCode), + mID(id), + mMessage(nullptr) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} +void Error::createMessageString() const +{ + if (mMessage == nullptr) + { + mMessage = new std::string(); + } +} + +const std::string &Error::getMessage() const +{ + createMessageString(); + return *mMessage; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h new file mode 100644 index 0000000000..896b777567 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Error.h @@ -0,0 +1,83 @@ +// +// 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 and gl::Error classes which encapsulate API errors +// and optional error messages. + +#ifndef LIBANGLE_ERROR_H_ +#define LIBANGLE_ERROR_H_ + +#include "angle_gl.h" +#include "common/platform.h" +#include <EGL/egl.h> + +#include <string> + +namespace gl +{ + +class Error final +{ + public: + explicit inline Error(GLenum errorCode); + Error(GLenum errorCode, const char *msg, ...); + inline Error(const Error &other); + inline Error(Error &&other); + + inline ~Error(); + + inline Error &operator=(const Error &other); + inline Error &operator=(Error &&other); + + inline GLenum getCode() const; + inline bool isError() const; + + const std::string &getMessage() const; + + private: + void createMessageString() const; + + GLenum mCode; + mutable std::string *mMessage; +}; + +} + +namespace egl +{ + +class Error final +{ + public: + explicit inline Error(EGLint errorCode); + Error(EGLint errorCode, const char *msg, ...); + Error(EGLint errorCode, EGLint id, const char *msg, ...); + inline Error(const Error &other); + inline Error(Error &&other); + + inline ~Error(); + + inline Error &operator=(const Error &other); + inline Error &operator=(Error &&other); + + inline EGLint getCode() const; + inline EGLint getID() const; + inline bool isError() const; + + const std::string &getMessage() const; + + private: + void createMessageString() const; + + EGLint mCode; + EGLint mID; + mutable std::string *mMessage; +}; + +} + +#include "Error.inl" + +#endif // LIBANGLE_ERROR_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Error.inl b/src/3rdparty/angle/src/libANGLE/Error.inl new file mode 100644 index 0000000000..32e8f05828 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Error.inl @@ -0,0 +1,163 @@ +// +// 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.inl: Inline definitions of egl::Error and gl::Error classes which encapsulate API errors +// and optional error messages. + +#include "common/angleutils.h" + +#include <cstdarg> + +namespace gl +{ + +Error::Error(GLenum errorCode) + : mCode(errorCode), + mMessage(nullptr) +{ +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mMessage(nullptr) +{ + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } +} + +Error::Error(Error &&other) + : mCode(other.mCode), + mMessage(other.mMessage) +{ + other.mMessage = nullptr; +} + +Error::~Error() +{ + SafeDelete(mMessage); +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } + else + { + SafeDelete(mMessage); + } + + return *this; +} + +Error &Error::operator=(Error &&other) +{ + mCode = other.mCode; + mMessage = other.mMessage; + + other.mMessage = nullptr; + + return *this; +} + +GLenum Error::getCode() const +{ + return mCode; +} + +bool Error::isError() const +{ + return (mCode != GL_NO_ERROR); +} + +} + +namespace egl +{ + +Error::Error(EGLint errorCode) + : mCode(errorCode), + mID(0), + mMessage(nullptr) +{ +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mID(other.mID), + mMessage(nullptr) +{ + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } +} + +Error::Error(Error &&other) + : mCode(other.mCode), + mID(other.mID), + mMessage(other.mMessage) +{ + other.mMessage = nullptr; +} + +Error::~Error() +{ + SafeDelete(mMessage); +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + mID = other.mID; + + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } + else + { + SafeDelete(mMessage); + } + + return *this; +} + +Error &Error::operator=(Error &&other) +{ + mCode = other.mCode; + mID = other.mID; + mMessage = other.mMessage; + + other.mMessage = nullptr; + + return *this; +} + +EGLint Error::getCode() const +{ + return mCode; +} + +EGLint Error::getID() const +{ + return mID; +} + +bool Error::isError() const +{ + return (mCode != EGL_SUCCESS); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libANGLE/Fence.cpp index 966a327de5..8ab4cc9daa 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libANGLE/Fence.cpp @@ -7,10 +7,11 @@ // 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 "libANGLE/Fence.h" + +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" +#include "libANGLE/renderer/Renderer.h" #include "common/utilities.h" #include "angle_gl.h" diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libANGLE/Fence.h index fd565e96a6..bcd66b6831 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.h +++ b/src/3rdparty/angle/src/libANGLE/Fence.h @@ -7,13 +7,13 @@ // 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_ +#ifndef LIBANGLE_FENCE_H_ +#define LIBANGLE_FENCE_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" #include "common/angleutils.h" -#include "common/RefCountObject.h" namespace rx { @@ -24,7 +24,7 @@ class FenceSyncImpl; namespace gl { -class FenceNV +class FenceNV final : angle::NonCopyable { public: explicit FenceNV(rx::FenceNVImpl *impl); @@ -36,11 +36,9 @@ class FenceNV Error finishFence(); GLboolean getStatus() const { return mStatus; } - GLuint getCondition() const { return mCondition; } + GLenum getCondition() const { return mCondition; } private: - DISALLOW_COPY_AND_ASSIGN(FenceNV); - rx::FenceNVImpl *mFence; bool mIsSet; @@ -49,7 +47,7 @@ class FenceNV GLenum mCondition; }; -class FenceSync : public RefCountObject +class FenceSync final : public RefCountObject { public: explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id); @@ -60,11 +58,9 @@ class FenceSync : public RefCountObject Error serverWait(GLbitfield flags, GLuint64 timeout); Error getStatus(GLint *outResult) const; - GLuint getCondition() const { return mCondition; } + GLenum getCondition() const { return mCondition; } private: - DISALLOW_COPY_AND_ASSIGN(FenceSync); - rx::FenceSyncImpl *mFence; GLenum mCondition; @@ -72,4 +68,4 @@ class FenceSync : public RefCountObject } -#endif // LIBGLESV2_FENCE_H_ +#endif // LIBANGLE_FENCE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp index 5bf7b3fce8..5bf7b3fce8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp +++ b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp new file mode 100644 index 0000000000..b1dd4a1b0f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp @@ -0,0 +1,658 @@ +// +// Copyright (c) 2002-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. +// + +// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. + +#include "libANGLE/Framebuffer.h" + +#include "common/utilities.h" +#include "libANGLE/Config.h" +#include "libANGLE/Context.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/FramebufferImpl.h" +#include "libANGLE/renderer/ImplFactory.h" +#include "libANGLE/renderer/RenderbufferImpl.h" +#include "libANGLE/renderer/Workarounds.h" + +namespace gl +{ + +namespace +{ +void DeleteMatchingAttachment(FramebufferAttachment *&attachment, GLenum matchType, GLuint matchId) +{ + if (attachment && attachment->type() == matchType && attachment->id() == matchId) + { + SafeDelete(attachment); + } +} +} + +Framebuffer::Data::Data(const Caps &caps) + : mColorAttachments(caps.maxColorAttachments, nullptr), + mDepthAttachment(nullptr), + mStencilAttachment(nullptr), + mDrawBufferStates(caps.maxDrawBuffers, GL_NONE), + mReadBufferState(GL_COLOR_ATTACHMENT0_EXT) +{ + mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; +} + +Framebuffer::Data::~Data() +{ + for (auto it = mColorAttachments.begin(); it != mColorAttachments.end(); ++it) + { + SafeDelete(*it); + } + SafeDelete(mDepthAttachment); + SafeDelete(mStencilAttachment); +} + +FramebufferAttachment *Framebuffer::Data::getReadAttachment() const +{ + ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15)); + size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0)); + ASSERT(readIndex < mColorAttachments.size()); + return mColorAttachments[readIndex]; +} + +FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const +{ + for (auto it = mColorAttachments.cbegin(); it != mColorAttachments.cend(); ++it) + { + if (*it != nullptr) + { + return *it; + } + } + + return nullptr; +} + +FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const +{ + return (mDepthAttachment != nullptr ? mDepthAttachment : mStencilAttachment); +} + +Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id) + : mData(caps), + mImpl(nullptr), + mId(id) +{ + if (mId == 0) + { + mImpl = factory->createDefaultFramebuffer(mData); + } + else + { + mImpl = factory->createFramebuffer(mData); + } + ASSERT(mImpl != nullptr); +} + +Framebuffer::~Framebuffer() +{ + SafeDelete(mImpl); +} + +void Framebuffer::detachTexture(GLuint textureId) +{ + detachResourceById(GL_TEXTURE, textureId); +} + +void Framebuffer::detachRenderbuffer(GLuint renderbufferId) +{ + detachResourceById(GL_RENDERBUFFER, renderbufferId); +} + +void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId) +{ + for (auto it = mData.mColorAttachments.begin(); it != mData.mColorAttachments.end(); ++it) + { + DeleteMatchingAttachment(*it, resourceType, resourceId); + } + + DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId); + DeleteMatchingAttachment(mData.mStencilAttachment, resourceType, resourceId); +} + +FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const +{ + ASSERT(colorAttachment < mData.mColorAttachments.size()); + return mData.mColorAttachments[colorAttachment]; +} + +FramebufferAttachment *Framebuffer::getDepthbuffer() const +{ + return mData.mDepthAttachment; +} + +FramebufferAttachment *Framebuffer::getStencilbuffer() const +{ + return mData.mStencilAttachment; +} + +FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const +{ + return (hasValidDepthStencil() ? mData.mDepthAttachment : NULL); +} + +FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const +{ + return mData.getDepthOrStencilAttachment(); +} + +FramebufferAttachment *Framebuffer::getReadColorbuffer() const +{ + return mData.getReadAttachment(); +} + +GLenum Framebuffer::getReadColorbufferType() const +{ + FramebufferAttachment *readAttachment = mData.getReadAttachment(); + return (readAttachment ? readAttachment->type() : GL_NONE); +} + +FramebufferAttachment *Framebuffer::getFirstColorbuffer() const +{ + return mData.getFirstColorAttachment(); +} + +FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const +{ + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) + { + return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); + } + else + { + switch (attachment) + { + case GL_COLOR: + case GL_BACK: + return getColorbuffer(0); + case GL_DEPTH: + case GL_DEPTH_ATTACHMENT: + return getDepthbuffer(); + case GL_STENCIL: + case GL_STENCIL_ATTACHMENT: + return getStencilbuffer(); + case GL_DEPTH_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + return getDepthStencilBuffer(); + default: + UNREACHABLE(); + return NULL; + } + } +} + +GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const +{ + ASSERT(colorAttachment < mData.mDrawBufferStates.size()); + return mData.mDrawBufferStates[colorAttachment]; +} + +void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers) +{ + auto &drawStates = mData.mDrawBufferStates; + + ASSERT(count <= drawStates.size()); + std::copy(buffers, buffers + count, drawStates.begin()); + std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE); + mImpl->setDrawBuffers(count, buffers); +} + +GLenum Framebuffer::getReadBufferState() const +{ + return mData.mReadBufferState; +} + +void Framebuffer::setReadBuffer(GLenum buffer) +{ + ASSERT(buffer == GL_BACK || buffer == GL_NONE || + (buffer >= GL_COLOR_ATTACHMENT0 && + (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size())); + mData.mReadBufferState = buffer; + mImpl->setReadBuffer(buffer); +} + +bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const +{ + ASSERT(colorAttachment < mData.mColorAttachments.size()); + return (mData.mColorAttachments[colorAttachment] && + mData.mDrawBufferStates[colorAttachment] != GL_NONE); +} + +bool Framebuffer::hasEnabledColorAttachment() const +{ + for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +bool Framebuffer::hasStencil() const +{ + return (mData.mStencilAttachment && mData.mStencilAttachment->getStencilSize() > 0); +} + +bool Framebuffer::usingExtendedDrawBuffers() const +{ + for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +GLenum Framebuffer::checkStatus(const gl::Data &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. + if (mId == 0) + { + return GL_FRAMEBUFFER_COMPLETE; + } + + int width = 0; + int height = 0; + unsigned int colorbufferSize = 0; + int samples = -1; + bool missingAttachment = true; + + for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { + const auto &colorAttachment = *it; + if (colorAttachment != nullptr) + { + if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + GLenum internalformat = colorAttachment->getInternalFormat(); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (colorAttachment->type() == GL_TEXTURE) + { + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (colorAttachment->type() == GL_RENDERBUFFER) + { + if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + + if (!missingAttachment) + { + // all color attachments must have the same width and height + if (colorAttachment->getWidth() != width || colorAttachment->getHeight() != height) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + + // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that + // all color attachments have the same number of samples for the FBO to be complete. + if (colorAttachment->getSamples() != samples) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; + } + + // 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 (data.clientVersion < 3) + { + if (formatInfo.pixelBytes != colorbufferSize) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + } + else + { + width = colorAttachment->getWidth(); + height = colorAttachment->getHeight(); + samples = colorAttachment->getSamples(); + colorbufferSize = formatInfo.pixelBytes; + missingAttachment = false; + } + } + } + + const FramebufferAttachment *depthAttachment = mData.mDepthAttachment; + if (depthAttachment != nullptr) + { + if (depthAttachment->getWidth() == 0 || depthAttachment->getHeight() == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + GLenum internalformat = depthAttachment->getInternalFormat(); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (depthAttachment->type() == GL_TEXTURE) + { + // depth texture attachments require OES/ANGLE_depth_texture + if (!data.extensions->depthTextures) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.depthBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (depthAttachment->type() == GL_RENDERBUFFER) + { + if (!formatCaps.renderable || formatInfo.depthBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + + if (missingAttachment) + { + width = depthAttachment->getWidth(); + height = depthAttachment->getHeight(); + samples = depthAttachment->getSamples(); + missingAttachment = false; + } + else if (width != depthAttachment->getWidth() || height != depthAttachment->getHeight()) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + else if (samples != depthAttachment->getSamples()) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; + } + } + + const FramebufferAttachment *stencilAttachment = mData.mStencilAttachment; + if (stencilAttachment) + { + if (stencilAttachment->getWidth() == 0 || stencilAttachment->getHeight() == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + GLenum internalformat = stencilAttachment->getInternalFormat(); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (stencilAttachment->type() == GL_TEXTURE) + { + // texture stencil attachments come along as part + // of OES_packed_depth_stencil + OES/ANGLE_depth_texture + if (!data.extensions->depthTextures) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.stencilBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (stencilAttachment->type() == GL_RENDERBUFFER) + { + if (!formatCaps.renderable || formatInfo.stencilBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + + if (missingAttachment) + { + width = stencilAttachment->getWidth(); + height = stencilAttachment->getHeight(); + samples = stencilAttachment->getSamples(); + missingAttachment = false; + } + else if (width != stencilAttachment->getWidth() || height != stencilAttachment->getHeight()) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + else if (samples != stencilAttachment->getSamples()) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; + } + } + + // if we have both a depth and stencil buffer, they must refer to the same object + // since we only support packed_depth_stencil and not separate depth and stencil + if (depthAttachment && stencilAttachment && !hasValidDepthStencil()) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + // we need to have at least one attachment to be complete + if (missingAttachment) + { + return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; + } + + return mImpl->checkStatus(); +} + +Error Framebuffer::invalidate(size_t count, const GLenum *attachments) +{ + return mImpl->invalidate(count, attachments); +} + +Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) +{ + return mImpl->invalidateSub(count, attachments, area); +} + +Error Framebuffer::clear(const gl::Data &data, GLbitfield mask) +{ + return mImpl->clear(data, mask); +} + +Error Framebuffer::clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +{ + return mImpl->clearBufferfv(state, buffer, drawbuffer, values); +} + +Error Framebuffer::clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +{ + return mImpl->clearBufferuiv(state, buffer, drawbuffer, values); +} + +Error Framebuffer::clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +{ + return mImpl->clearBufferiv(state, buffer, drawbuffer, values); +} + +Error Framebuffer::clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + return mImpl->clearBufferfi(state, buffer, drawbuffer, depth, stencil); +} + +GLenum Framebuffer::getImplementationColorReadFormat() const +{ + return mImpl->getImplementationColorReadFormat(); +} + +GLenum Framebuffer::getImplementationColorReadType() const +{ + return mImpl->getImplementationColorReadType(); +} + +Error Framebuffer::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +{ + return mImpl->readPixels(state, area, format, type, pixels); +} + +Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) +{ + return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer); +} + +int Framebuffer::getSamples(const gl::Data &data) const +{ + if (checkStatus(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 + for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { + if (*it != nullptr) + { + return (*it)->getSamples(); + } + } + } + + return 0; +} + +bool Framebuffer::hasValidDepthStencil() const +{ + // A valid depth-stencil attachment has the same resource bound to both the + // depth and stencil attachment points. + return (mData.mDepthAttachment && mData.mStencilAttachment && + mData.mDepthAttachment->type() == mData.mStencilAttachment->type() && + mData.mDepthAttachment->id() == mData.mStencilAttachment->id()); +} + +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 + mData.mColorAttachments.size())) + { + size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0; + SafeDelete(mData.mColorAttachments[colorAttachment]); + mData.mColorAttachments[colorAttachment] = attachmentObj; + mImpl->setColorAttachment(colorAttachment, attachmentObj); + } + else if (attachment == GL_BACK) + { + SafeDelete(mData.mColorAttachments[0]); + mData.mColorAttachments[0] = attachmentObj; + mImpl->setColorAttachment(0, attachmentObj); + } + else if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH) + { + SafeDelete(mData.mDepthAttachment); + mData.mDepthAttachment = attachmentObj; + mImpl->setDepthAttachment(attachmentObj); + } + else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_STENCIL) + { + SafeDelete(mData.mStencilAttachment); + mData.mStencilAttachment = attachmentObj; + mImpl->setStencilAttachment(attachmentObj); + } + else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL) + { + SafeDelete(mData.mDepthAttachment); + SafeDelete(mData.mStencilAttachment); + + // ensure this is a legitimate depth+stencil format + if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0) + { + mData.mDepthAttachment = attachmentObj; + mImpl->setDepthAttachment(attachmentObj); + + // Make a new attachment object to ensure we do not double-delete + // See angle issue 686 + if (attachmentObj->type() == GL_TEXTURE) + { + mData.mStencilAttachment = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(), + *attachmentObj->getTextureImageIndex()); + mImpl->setStencilAttachment(mData.mStencilAttachment); + } + else if (attachmentObj->type() == GL_RENDERBUFFER) + { + mData.mStencilAttachment = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer()); + mImpl->setStencilAttachment(mData.mStencilAttachment); + } + else + { + UNREACHABLE(); + } + } + } + else + { + UNREACHABLE(); + } +} + +DefaultFramebuffer::DefaultFramebuffer(const Caps &caps, rx::ImplFactory *factory, egl::Surface *surface) + : Framebuffer(caps, factory, 0) +{ + const egl::Config *config = surface->getConfig(); + + setAttachment(GL_BACK, new DefaultAttachment(GL_BACK, surface)); + + if (config->depthSize > 0) + { + setAttachment(GL_DEPTH, new DefaultAttachment(GL_DEPTH, surface)); + } + if (config->stencilSize > 0) + { + setAttachment(GL_STENCIL, new DefaultAttachment(GL_STENCIL, surface)); + } + + GLenum drawBufferState = GL_BACK; + setDrawBuffers(1, &drawBufferState); + + setReadBuffer(GL_BACK); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.h b/src/3rdparty/angle/src/libANGLE/Framebuffer.h new file mode 100644 index 0000000000..8b24cf984e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.h @@ -0,0 +1,144 @@ +// +// Copyright (c) 2002-2013 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. +// + +// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. + +#ifndef LIBANGLE_FRAMEBUFFER_H_ +#define LIBANGLE_FRAMEBUFFER_H_ + +#include <vector> + +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +namespace rx +{ +class ImplFactory; +class FramebufferImpl; +class RenderbufferImpl; +struct Workarounds; +} + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class FramebufferAttachment; +class Renderbuffer; +class State; +class Texture; +class TextureCapsMap; +struct Caps; +struct Data; +struct Extensions; +struct ImageIndex; +struct Rectangle; + +typedef std::vector<FramebufferAttachment *> AttachmentList; + +class Framebuffer +{ + public: + + class Data final : angle::NonCopyable + { + public: + explicit Data(const Caps &caps); + ~Data(); + + FramebufferAttachment *getReadAttachment() const; + FramebufferAttachment *getFirstColorAttachment() const; + FramebufferAttachment *getDepthOrStencilAttachment() const; + + AttachmentList mColorAttachments; + FramebufferAttachment *mDepthAttachment; + FramebufferAttachment *mStencilAttachment; + + std::vector<GLenum> mDrawBufferStates; + GLenum mReadBufferState; + }; + + Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id); + virtual ~Framebuffer(); + + const rx::FramebufferImpl *getImplementation() const { return mImpl; } + rx::FramebufferImpl *getImplementation() { return mImpl; } + + GLuint id() const { return mId; } + + 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); + + FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; + FramebufferAttachment *getDepthbuffer() const; + FramebufferAttachment *getStencilbuffer() const; + FramebufferAttachment *getDepthStencilBuffer() const; + FramebufferAttachment *getDepthOrStencilbuffer() const; + FramebufferAttachment *getReadColorbuffer() const; + GLenum getReadColorbufferType() const; + FramebufferAttachment *getFirstColorbuffer() const; + + FramebufferAttachment *getAttachment(GLenum attachment) const; + + GLenum getDrawBufferState(unsigned int colorAttachment) const; + void setDrawBuffers(size_t count, const GLenum *buffers); + + GLenum getReadBufferState() const; + void setReadBuffer(GLenum buffer); + + bool isEnabledColorAttachment(unsigned int colorAttachment) const; + bool hasEnabledColorAttachment() const; + bool hasStencil() const; + int getSamples(const gl::Data &data) const; + bool usingExtendedDrawBuffers() const; + + GLenum checkStatus(const gl::Data &data) const; + bool hasValidDepthStencil() const; + + Error invalidate(size_t count, const GLenum *attachments); + Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area); + + Error clear(const gl::Data &data, GLbitfield mask); + Error clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values); + Error clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values); + Error clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values); + Error clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + + GLenum getImplementationColorReadFormat() const; + GLenum getImplementationColorReadType() const; + Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const; + + Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer); + + protected: + void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); + void detachResourceById(GLenum resourceType, GLuint resourceId); + + Data mData; + rx::FramebufferImpl *mImpl; + GLuint mId; +}; + +class DefaultFramebuffer : public Framebuffer +{ + public: + DefaultFramebuffer(const gl::Caps &caps, rx::ImplFactory *factory, egl::Surface *surface); +}; + +} + +#endif // LIBANGLE_FRAMEBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp index 894884a6d8..e56fc750ad 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp +++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp @@ -7,15 +7,15 @@ // FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libANGLE/FramebufferAttachment.h" #include "common/utilities.h" +#include "libANGLE/Config.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/FramebufferImpl.h" namespace gl { @@ -33,47 +33,42 @@ FramebufferAttachment::~FramebufferAttachment() GLuint FramebufferAttachment::getRedSize() const { - return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0; + return GetInternalFormatInfo(getInternalFormat()).redBits; } GLuint FramebufferAttachment::getGreenSize() const { - return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0; + return GetInternalFormatInfo(getInternalFormat()).greenBits; } GLuint FramebufferAttachment::getBlueSize() const { - return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0; + return GetInternalFormatInfo(getInternalFormat()).blueBits; } GLuint FramebufferAttachment::getAlphaSize() const { - return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0; + return GetInternalFormatInfo(getInternalFormat()).alphaBits; } GLuint FramebufferAttachment::getDepthSize() const { - return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0; + return GetInternalFormatInfo(getInternalFormat()).depthBits; } GLuint FramebufferAttachment::getStencilSize() const { - return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0; + return GetInternalFormatInfo(getInternalFormat()).stencilBits; } GLenum FramebufferAttachment::getComponentType() const { - return GetInternalFormatInfo(getActualFormat()).componentType; + return GetInternalFormatInfo(getInternalFormat()).componentType; } GLenum FramebufferAttachment::getColorEncoding() const { - return GetInternalFormatInfo(getActualFormat()).colorEncoding; -} - -bool FramebufferAttachment::isTexture() const -{ - return (type() != GL_RENDERBUFFER); + return GetInternalFormatInfo(getInternalFormat()).colorEncoding; } ///// TextureAttachment Implementation //////// @@ -102,27 +97,22 @@ GLuint TextureAttachment::id() const GLsizei TextureAttachment::getWidth() const { - return mTexture->getWidth(mIndex); + return mTexture->getWidth(mIndex.type, mIndex.mipIndex); } GLsizei TextureAttachment::getHeight() const { - return mTexture->getHeight(mIndex); + return mTexture->getHeight(mIndex.type, mIndex.mipIndex); } GLenum TextureAttachment::getInternalFormat() const { - return mTexture->getInternalFormat(mIndex); -} - -GLenum TextureAttachment::getActualFormat() const -{ - return mTexture->getActualFormat(mIndex); + return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex); } GLenum TextureAttachment::type() const { - return mIndex.type; + return GL_TEXTURE; } GLint TextureAttachment::mipLevel() const @@ -130,12 +120,17 @@ GLint TextureAttachment::mipLevel() const return mIndex.mipIndex; } +GLenum TextureAttachment::cubeMapFace() const +{ + return IsCubeMapTextureTarget(mIndex.type) ? mIndex.type : GL_NONE; +} + GLint TextureAttachment::layer() const { return mIndex.layerIndex; } -Texture *TextureAttachment::getTexture() +Texture *TextureAttachment::getTexture() const { return mTexture.get(); } @@ -145,7 +140,7 @@ const ImageIndex *TextureAttachment::getTextureImageIndex() const return &mIndex; } -Renderbuffer *TextureAttachment::getRenderbuffer() +Renderbuffer *TextureAttachment::getRenderbuffer() const { UNREACHABLE(); return NULL; @@ -180,11 +175,6 @@ GLenum RenderbufferAttachment::getInternalFormat() const return mRenderbuffer->getInternalFormat(); } -GLenum RenderbufferAttachment::getActualFormat() const -{ - return mRenderbuffer->getActualFormat(); -} - GLsizei RenderbufferAttachment::getSamples() const { return mRenderbuffer->getSamples(); @@ -205,12 +195,17 @@ GLint RenderbufferAttachment::mipLevel() const return 0; } +GLenum RenderbufferAttachment::cubeMapFace() const +{ + return GL_NONE; +} + GLint RenderbufferAttachment::layer() const { return 0; } -Texture *RenderbufferAttachment::getTexture() +Texture *RenderbufferAttachment::getTexture() const { UNREACHABLE(); return NULL; @@ -222,9 +217,86 @@ const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const return NULL; } -Renderbuffer *RenderbufferAttachment::getRenderbuffer() +Renderbuffer *RenderbufferAttachment::getRenderbuffer() const { return mRenderbuffer.get(); } + +DefaultAttachment::DefaultAttachment(GLenum binding, egl::Surface *surface) + : FramebufferAttachment(binding) +{ + mSurface.set(surface); +} + +DefaultAttachment::~DefaultAttachment() +{ + mSurface.set(nullptr); +} + +GLsizei DefaultAttachment::getWidth() const +{ + return mSurface->getWidth(); +} + +GLsizei DefaultAttachment::getHeight() const +{ + return mSurface->getHeight(); +} + +GLenum DefaultAttachment::getInternalFormat() const +{ + const egl::Config *config = mSurface->getConfig(); + return (getBinding() == GL_BACK ? config->renderTargetFormat : config->depthStencilFormat); +} + +GLsizei DefaultAttachment::getSamples() const +{ + const egl::Config *config = mSurface->getConfig(); + return config->samples; +} + +GLuint DefaultAttachment::id() const +{ + return 0; +} + +GLenum DefaultAttachment::type() const +{ + return GL_FRAMEBUFFER_DEFAULT; +} + +GLint DefaultAttachment::mipLevel() const +{ + return 0; +} + +GLenum DefaultAttachment::cubeMapFace() const +{ + return GL_NONE; +} + +GLint DefaultAttachment::layer() const +{ + return 0; +} + +Texture *DefaultAttachment::getTexture() const +{ + UNREACHABLE(); + return NULL; +} + +const ImageIndex *DefaultAttachment::getTextureImageIndex() const +{ + UNREACHABLE(); + return NULL; +} + +Renderbuffer *DefaultAttachment::getRenderbuffer() const +{ + UNREACHABLE(); + return NULL; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h index 8d2dafa7ee..0662130931 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h +++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h @@ -7,12 +7,13 @@ // FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. -#ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ -#define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ +#ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_ +#define LIBANGLE_FRAMEBUFFERATTACHMENT_H_ + +#include "libANGLE/Texture.h" +#include "libANGLE/RefCountObject.h" #include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "Texture.h" #include "angle_gl.h" @@ -26,7 +27,7 @@ class Renderbuffer; // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for // framebuffer attachments, which confused their usage. -class FramebufferAttachment +class FramebufferAttachment : angle::NonCopyable { public: explicit FramebufferAttachment(GLenum binding); @@ -41,10 +42,9 @@ class FramebufferAttachment GLuint getStencilSize() const; GLenum getComponentType() const; GLenum getColorEncoding() const; - bool isTexture() const; - bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; } - bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; } + bool isTextureWithId(GLuint textureId) const { return type() == GL_TEXTURE && id() == textureId; } + bool isRenderbufferWithId(GLuint renderbufferId) const { return type() == GL_RENDERBUFFER && id() == renderbufferId; } GLenum getBinding() const { return mBinding; } @@ -52,21 +52,19 @@ class FramebufferAttachment virtual GLsizei getWidth() const = 0; virtual GLsizei getHeight() const = 0; virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; virtual GLsizei getSamples() const = 0; virtual GLuint id() const = 0; virtual GLenum type() const = 0; virtual GLint mipLevel() const = 0; + virtual GLenum cubeMapFace() const = 0; virtual GLint layer() const = 0; - virtual Texture *getTexture() = 0; + virtual Texture *getTexture() const = 0; virtual const ImageIndex *getTextureImageIndex() const = 0; - virtual Renderbuffer *getRenderbuffer() = 0; + virtual Renderbuffer *getRenderbuffer() const = 0; private: - DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); - GLenum mBinding; }; @@ -82,19 +80,17 @@ class TextureAttachment : public FramebufferAttachment virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; virtual GLenum type() const; virtual GLint mipLevel() const; + virtual GLenum cubeMapFace() const; virtual GLint layer() const; - virtual Texture *getTexture(); + virtual Texture *getTexture() const; virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer(); + virtual Renderbuffer *getRenderbuffer() const; private: - DISALLOW_COPY_AND_ASSIGN(TextureAttachment); - BindingPointer<Texture> mTexture; ImageIndex mIndex; }; @@ -109,24 +105,50 @@ class RenderbufferAttachment : public FramebufferAttachment virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual GLuint id() const; virtual GLenum type() const; virtual GLint mipLevel() const; + virtual GLenum cubeMapFace() const; virtual GLint layer() const; - virtual Texture *getTexture(); + virtual Texture *getTexture() const; virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer(); + virtual Renderbuffer *getRenderbuffer() const; private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); - BindingPointer<Renderbuffer> mRenderbuffer; }; +class DefaultAttachment : public FramebufferAttachment +{ + public: + DefaultAttachment(GLenum binding, egl::Surface *surface); + + virtual ~DefaultAttachment(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLsizei getSamples() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLenum cubeMapFace() const; + virtual GLint layer() const; + + virtual Texture *getTexture() const; + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer() const; + + const egl::Surface *getSurface() const { return mSurface.get(); } + + private: + BindingPointer<egl::Surface> mSurface; +}; + } -#endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ +#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_ diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp new file mode 100644 index 0000000000..59d3966758 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp @@ -0,0 +1,133 @@ +// +// Copyright (c) 2002-2011 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. +// + +// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used +// to allocate GL handles. + +#include "libANGLE/HandleAllocator.h" + +#include <algorithm> + +#include "common/debug.h" + +namespace gl +{ + +struct HandleAllocator::HandleRangeComparator +{ + bool operator()(const HandleRange &range, GLuint handle) const + { + return (handle < range.begin); + } +}; + +HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1) +{ + mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max() - 1)); +} + +HandleAllocator::HandleAllocator(GLuint maximumHandleValue) : mBaseValue(1), mNextValue(1) +{ + mUnallocatedList.push_back(HandleRange(1, maximumHandleValue)); +} + +HandleAllocator::~HandleAllocator() +{ +} + +void HandleAllocator::setBaseHandle(GLuint value) +{ + ASSERT(mBaseValue == mNextValue); + mBaseValue = value; + mNextValue = value; +} + +GLuint HandleAllocator::allocate() +{ + ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty()); + + // Allocate from released list, constant time. + if (!mReleasedList.empty()) + { + GLuint reusedHandle = mReleasedList.back(); + mReleasedList.pop_back(); + return reusedHandle; + } + + // Allocate from unallocated list, constant time. + auto listIt = mUnallocatedList.begin(); + + GLuint freeListHandle = listIt->begin; + ASSERT(freeListHandle > 0); + + listIt->begin++; + if (listIt->begin == listIt->end) + { + mUnallocatedList.erase(listIt); + } + + return freeListHandle; +} + +void HandleAllocator::release(GLuint handle) +{ + // Add to released list, constant time. + mReleasedList.push_back(handle); +} + +void HandleAllocator::reserve(GLuint handle) +{ + // Clear from released list -- might be a slow operation. + if (!mReleasedList.empty()) + { + auto releasedIt = std::find(mReleasedList.begin(), mReleasedList.end(), handle); + if (releasedIt != mReleasedList.end()) + { + mReleasedList.erase(releasedIt); + return; + } + } + + // Not in released list, reserve in the unallocated list. + auto boundIt = std::lower_bound(mUnallocatedList.begin(), mUnallocatedList.end(), handle, HandleRangeComparator()); + + ASSERT(boundIt != mUnallocatedList.end()); + + GLuint begin = boundIt->begin; + GLuint end = boundIt->end; + + if (handle == begin || handle == end) + { + if (begin + 1 == end) + { + mUnallocatedList.erase(boundIt); + } + else if (handle == begin) + { + boundIt->begin++; + } + else + { + ASSERT(handle == end); + boundIt->end--; + } + return; + } + + // need to split the range + auto placementIt = mUnallocatedList.erase(boundIt); + + if (begin != handle) + { + placementIt = mUnallocatedList.insert(placementIt, HandleRange(begin, handle)); + } + if (handle + 1 != end) + { + mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end)); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h new file mode 100644 index 0000000000..c22f2ba61a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h @@ -0,0 +1,63 @@ +// +// Copyright (c) 2002-2011 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. +// + +// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to +// allocate GL handles. + +#ifndef LIBANGLE_HANDLEALLOCATOR_H_ +#define LIBANGLE_HANDLEALLOCATOR_H_ + +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include <stack> + +namespace gl +{ + +class HandleAllocator final : angle::NonCopyable +{ + public: + // Maximum handle = MAX_UINT-1 + HandleAllocator(); + // Specify maximum handle value + HandleAllocator(GLuint maximumHandleValue); + + ~HandleAllocator(); + + void setBaseHandle(GLuint value); + + GLuint allocate(); + void release(GLuint handle); + void reserve(GLuint handle); + + private: + GLuint mBaseValue; + GLuint mNextValue; + typedef std::vector<GLuint> HandleList; + HandleList mFreeValues; + + struct HandleRange + { + HandleRange(GLuint beginIn, GLuint endIn) : begin(beginIn), end(endIn) {} + + GLuint begin; + GLuint end; + }; + + struct HandleRangeComparator; + + // The freelist consists of never-allocated handles, stored + // as ranges, and handles that were previously allocated and + // released, stored in a stack. + std::vector<HandleRange> mUnallocatedList; + std::vector<GLuint> mReleasedList; +}; + +} + +#endif // LIBANGLE_HANDLEALLOCATOR_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp index b45cd9c169..ac7302d121 100644 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp +++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp @@ -6,8 +6,8 @@ // ImageIndex.cpp: Implementation for ImageIndex methods. -#include "libGLESv2/ImageIndex.h" -#include "libGLESv2/Texture.h" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/Constants.h" #include "common/utilities.h" namespace gl @@ -34,8 +34,8 @@ ImageIndex ImageIndex::Make2D(GLint mipIndex) ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex) { - ASSERT(gl::IsCubemapTextureTarget(target)); - return ImageIndex(target, mipIndex, TextureCubeMap::targetToLayerIndex(target)); + ASSERT(gl::IsCubeMapTextureTarget(target)); + return ImageIndex(target, mipIndex, CubeMapTextureTargetToLayerIndex(target)); } ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex) @@ -48,11 +48,33 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex); } +ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex) +{ + GLint layerIndex = IsCubeMapTextureTarget(target) ? CubeMapTextureTargetToLayerIndex(target) : ENTIRE_LEVEL; + return ImageIndex(target, mipIndex, layerIndex); +} + ImageIndex ImageIndex::MakeInvalid() { return ImageIndex(GL_NONE, -1, -1); } +bool ImageIndex::operator<(const ImageIndex &other) const +{ + if (type != other.type) + { + return type < other.type; + } + else if (mipIndex != other.mipIndex) + { + return mipIndex < other.mipIndex; + } + else + { + return layerIndex < other.layerIndex; + } +} + ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) : type(typeIn), mipIndex(mipIndexIn), @@ -134,7 +156,7 @@ ImageIndex ImageIndexIterator::current() const if (mType == GL_TEXTURE_CUBE_MAP) { - value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer); + value.type = LayerIndexToCubeMapTextureTarget(mCurrentLayer); } return value; diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libANGLE/ImageIndex.h index 8bb14fd555..820c650f20 100644 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h +++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.h @@ -6,22 +6,24 @@ // ImageIndex.h: A helper struct for indexing into an Image array -#ifndef LIBGLESV2_IMAGE_INDEX_H_ -#define LIBGLESV2_IMAGE_INDEX_H_ +#ifndef LIBANGLE_IMAGE_INDEX_H_ +#define LIBANGLE_IMAGE_INDEX_H_ -#include "angle_gl.h" #include "common/mathutil.h" +#include "angle_gl.h" + namespace gl { +class ImageIndexIterator; + struct ImageIndex { GLenum type; GLint mipIndex; GLint layerIndex; - ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); ImageIndex(const ImageIndex &other); ImageIndex &operator=(const ImageIndex &other); @@ -31,9 +33,18 @@ 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 MakeGeneric(GLenum target, GLint mipIndex); + static ImageIndex MakeInvalid(); static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1); + + bool operator<(const ImageIndex &other) const; + + private: + friend class ImageIndexIterator; + + ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); }; class ImageIndexIterator @@ -65,4 +76,4 @@ class ImageIndexIterator } -#endif // LIBGLESV2_IMAGE_INDEX_H_ +#endif // LIBANGLE_IMAGE_INDEX_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Platform.cpp b/src/3rdparty/angle/src/libANGLE/Platform.cpp new file mode 100644 index 0000000000..ab75bbba5a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Platform.cpp @@ -0,0 +1,35 @@ +// +// Copyright 2015 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. +// + +// Platform.cpp: Implementation methods for angle::Platform. + +#include <platform/Platform.h> + +#include "common/debug.h" + +namespace +{ +angle::Platform *currentPlatform = nullptr; +} + +// static +ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent() +{ + return currentPlatform; +} + +// static +ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform *platformImpl) +{ + ASSERT(platformImpl != nullptr); + currentPlatform = platformImpl; +} + +// static +ANGLE_EXPORT void ANGLEPlatformShutdown() +{ + currentPlatform = nullptr; +} diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libANGLE/Program.cpp index 6d64b38b56..daf0a403f0 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libANGLE/Program.cpp @@ -7,30 +7,24 @@ // Program.cpp: Implements the gl::Program class. Implements GL program objects // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. -#include "libGLESv2/BinaryStream.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/ShaderExecutable.h" +#include "libANGLE/Program.h" + +#include <algorithm> #include "common/debug.h" -#include "common/version.h" -#include "common/utilities.h" #include "common/platform.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/renderer/ProgramImpl.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Buffer.h" -#include "common/blocklayout.h" -#include "common/features.h" +#include "common/utilities.h" +#include "common/version.h" +#include "compiler/translator/blocklayout.h" +#include "libANGLE/Data.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/ProgramImpl.h" namespace gl { +const char * const g_fakepath = "C:\\fakepath"; namespace { @@ -53,353 +47,403 @@ unsigned int ParseAndStripArrayIndex(std::string* name) } -VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) - : name(name), element(element), index(index) +AttributeBindings::AttributeBindings() { } -LinkedVarying::LinkedVarying() +AttributeBindings::~AttributeBindings() { } -LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, - unsigned int semanticIndex, unsigned int semanticIndexCount) - : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount) +InfoLog::InfoLog() : mInfoLog(NULL) { } -LinkResult::LinkResult(bool linkSuccess, const Error &error) - : linkSuccess(linkSuccess), - error(error) +InfoLog::~InfoLog() { + delete[] mInfoLog; } -unsigned int ProgramBinary::mCurrentSerial = 1; -ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) - : RefCountObject(0), - mProgram(impl), - mValidated(false), - mSerial(issueSerial()) +int InfoLog::getLength() const { - ASSERT(impl); - - for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) + if (!mInfoLog) { - mSemanticIndex[index] = -1; + return 0; + } + else + { + return strlen(mInfoLog) + 1; } } -ProgramBinary::~ProgramBinary() +void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) { - reset(); - SafeDelete(mProgram); -} + int index = 0; -unsigned int ProgramBinary::getSerial() const -{ - return mSerial; -} + if (bufSize > 0) + { + if (mInfoLog) + { + index = std::min(bufSize - 1, (int)strlen(mInfoLog)); + memcpy(infoLog, mInfoLog, index); + } -unsigned int ProgramBinary::issueSerial() -{ - return mCurrentSerial++; + infoLog[index] = '\0'; + } + + if (length) + { + *length = index; + } } -GLuint ProgramBinary::getAttributeLocation(const char *name) +// append a santized message to the program info log. +// The D3D compiler includes a fake file path in some of the warning or error +// messages, so lets remove all occurrences of this fake file path from the log. +void InfoLog::appendSanitized(const char *message) { - if (name) + std::string msg(message); + + size_t found; + do { - for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) + found = msg.find(g_fakepath); + if (found != std::string::npos) { - if (mLinkedAttribute[index].name == std::string(name)) - { - return index; - } + msg.erase(found, strlen(g_fakepath)); } } + while (found != std::string::npos); - return -1; + append("%s", msg.c_str()); } -int ProgramBinary::getSemanticIndex(int attributeIndex) +void InfoLog::append(const char *format, ...) { - ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); + if (!format) + { + return; + } - return mSemanticIndex[attributeIndex]; -} + va_list vararg; + va_start(vararg, format); + size_t infoLength = vsnprintf(NULL, 0, format, vararg); + va_end(vararg); -// Returns one more than the highest sampler index used. -GLint ProgramBinary::getUsedSamplerRange(SamplerType type) -{ - return mProgram->getUsedSamplerRange(type); -} + char *logPointer = NULL; -bool ProgramBinary::usesPointSize() const -{ - return mProgram->usesPointSize(); + if (!mInfoLog) + { + mInfoLog = new char[infoLength + 2]; + logPointer = mInfoLog; + } + else + { + size_t currentlogLength = strlen(mInfoLog); + char *newLog = new char[currentlogLength + infoLength + 2]; + strcpy(newLog, mInfoLog); + + delete[] mInfoLog; + mInfoLog = newLog; + + logPointer = mInfoLog + currentlogLength; + } + + va_start(vararg, format); + vsnprintf(logPointer, infoLength, format, vararg); + va_end(vararg); + + logPointer[infoLength] = 0; + strcpy(logPointer + infoLength, "\n"); } -GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) +void InfoLog::reset() { - return mProgram->getSamplerMapping(type, samplerIndex, caps); + if (mInfoLog) + { + delete [] mInfoLog; + mInfoLog = NULL; + } } -GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +VariableLocation::VariableLocation() + : name(), element(0), index(0) { - return mProgram->getSamplerTextureType(type, samplerIndex); } -GLint ProgramBinary::getUniformLocation(std::string name) +VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) + : name(name), element(element), index(index) { - return mProgram->getUniformLocation(name); } -GLuint ProgramBinary::getUniformIndex(std::string name) +LinkedVarying::LinkedVarying() { - return mProgram->getUniformIndex(name); } -GLuint ProgramBinary::getUniformBlockIndex(std::string name) +LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, + unsigned int semanticIndex, unsigned int semanticIndexCount) + : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount) { - return mProgram->getUniformBlockIndex(name); } -UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex) +Program::Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle) + : mProgram(impl), + mValidated(false), + mTransformFeedbackVaryings(), + mTransformFeedbackBufferMode(GL_NONE), + mFragmentShader(NULL), + mVertexShader(NULL), + mLinked(false), + mDeleteStatus(false), + mRefCount(0), + mResourceManager(manager), + mHandle(handle) { - return mProgram->getUniformBlockByIndex(blockIndex); + ASSERT(mProgram); + + resetUniformBlockBindings(); + unlink(); } -GLint ProgramBinary::getFragDataLocation(const char *name) const +Program::~Program() { - std::string baseName(name); - unsigned int arrayIndex; - arrayIndex = ParseAndStripArrayIndex(&baseName); + unlink(true); - for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++) + if (mVertexShader != NULL) { - const VariableLocation &outputVariable = locationIt->second; - - if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element)) - { - return static_cast<GLint>(locationIt->first); - } + mVertexShader->release(); } - return -1; -} - -size_t ProgramBinary::getTransformFeedbackVaryingCount() const -{ - return mProgram->getTransformFeedbackLinkedVaryings().size(); -} + if (mFragmentShader != NULL) + { + mFragmentShader->release(); + } -const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const -{ - return mProgram->getTransformFeedbackLinkedVaryings()[idx]; + SafeDelete(mProgram); } -GLenum ProgramBinary::getTransformFeedbackBufferMode() const +bool Program::attachShader(Shader *shader) { - return mProgram->getTransformFeedbackBufferMode(); -} - -void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform1fv(location, count, v); -} - -void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform2fv(location, count, v); -} - -void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform3fv(location, count, v); -} + if (shader->getType() == GL_VERTEX_SHADER) + { + if (mVertexShader) + { + return false; + } -void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform4fv(location, count, v); -} + mVertexShader = shader; + mVertexShader->addRef(); + } + else if (shader->getType() == GL_FRAGMENT_SHADER) + { + if (mFragmentShader) + { + return false; + } -void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform1iv(location, count, v); -} + mFragmentShader = shader; + mFragmentShader->addRef(); + } + else UNREACHABLE(); -void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform2iv(location, count, v); + return true; } -void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform3iv(location, count, v); -} +bool Program::detachShader(Shader *shader) +{ + if (shader->getType() == GL_VERTEX_SHADER) + { + if (mVertexShader != shader) + { + return false; + } -void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform4iv(location, count, v); -} + mVertexShader->release(); + mVertexShader = NULL; + } + else if (shader->getType() == GL_FRAGMENT_SHADER) + { + if (mFragmentShader != shader) + { + return false; + } -void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform1uiv(location, count, v); -} + mFragmentShader->release(); + mFragmentShader = NULL; + } + else UNREACHABLE(); -void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform2uiv(location, count, v); + return true; } -void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform3uiv(location, count, v); +int Program::getAttachedShadersCount() const +{ + return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0); } -void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform4uiv(location, count, v); -} +void AttributeBindings::bindAttributeLocation(GLuint index, const char *name) +{ + if (index < MAX_VERTEX_ATTRIBS) + { + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mAttributeBinding[i].erase(name); + } -void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix2fv(location, count, transpose, v); + mAttributeBinding[index].insert(name); + } } -void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix3fv(location, count, transpose, v); +void Program::bindAttributeLocation(GLuint index, const char *name) +{ + mAttributeBindings.bindAttributeLocation(index, name); } -void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix4fv(location, count, transpose, v); -} +// 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 +Error Program::link(const Data &data) +{ + unlink(false); -void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix2x3fv(location, count, transpose, v); -} + mInfoLog.reset(); + resetUniformBlockBindings(); -void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix2x4fv(location, count, transpose, v); -} + if (!mFragmentShader || !mFragmentShader->isCompiled()) + { + return Error(GL_NO_ERROR); + } + ASSERT(mFragmentShader->getType() == GL_FRAGMENT_SHADER); -void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix3x2fv(location, count, transpose, v); -} + if (!mVertexShader || !mVertexShader->isCompiled()) + { + return Error(GL_NO_ERROR); + } + ASSERT(mVertexShader->getType() == GL_VERTEX_SHADER); -void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix3x4fv(location, count, transpose, v); -} + if (!linkAttributes(mInfoLog, mAttributeBindings, mVertexShader)) + { + return Error(GL_NO_ERROR); + } -void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix4x2fv(location, count, transpose, v); -} + int registers; + std::vector<LinkedVarying> linkedVaryings; + rx::LinkResult result = mProgram->link(data, mInfoLog, mFragmentShader, mVertexShader, mTransformFeedbackVaryings, mTransformFeedbackBufferMode, + ®isters, &linkedVaryings, &mOutputVariables); + if (result.error.isError() || !result.linkSuccess) + { + return result.error; + } -void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix4x3fv(location, count, transpose, v); -} + if (!mProgram->linkUniforms(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps)) + { + return Error(GL_NO_ERROR); + } -void ProgramBinary::getUniformfv(GLint location, GLfloat *v) { - mProgram->getUniformfv(location, v); -} + if (!linkUniformBlocks(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps)) + { + return Error(GL_NO_ERROR); + } -void ProgramBinary::getUniformiv(GLint location, GLint *v) { - mProgram->getUniformiv(location, v); -} + if (!gatherTransformFeedbackLinkedVaryings(mInfoLog, linkedVaryings, mTransformFeedbackVaryings, + mTransformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) + { + return Error(GL_NO_ERROR); + } -void ProgramBinary::getUniformuiv(GLint location, GLuint *v) { - mProgram->getUniformuiv(location, v); -} + // 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(mInfoLog, mFragmentShader, mVertexShader, registers); + if (result.error.isError() || !result.linkSuccess) + { + mInfoLog.append("Failed to create D3D shaders."); + unlink(false); + return result.error; + } -void ProgramBinary::updateSamplerMapping() -{ - return mProgram->updateSamplerMapping(); + mLinked = true; + return gl::Error(GL_NO_ERROR); } -// Applies all the uniforms set for this program object to the renderer -Error ProgramBinary::applyUniforms() +int AttributeBindings::getAttributeBinding(const std::string &name) const { - return mProgram->applyUniforms(); -} + for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++) + { + if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end()) + { + return location; + } + } -Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps) -{ - return mProgram->applyUniformBuffers(boundBuffers, caps); + return -1; } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) +// Returns the program object to an unlinked state, before re-linking, or at destruction +void Program::unlink(bool destroy) { - std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings(); - std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings(); - - for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) + if (destroy) // Object being destructed { - PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; - bool matched = false; - - // Built-in varyings obey special rules - if (input->isBuiltIn()) + if (mFragmentShader) { - continue; + mFragmentShader->release(); + mFragmentShader = NULL; } - for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) + if (mVertexShader) { - PackedVarying *output = &vertexVaryings[vertVaryingIndex]; - if (output->name == input->name) - { - if (!linkValidateVaryings(infoLog, output->name, *input, *output)) - { - return false; - } + mVertexShader->release(); + mVertexShader = NULL; + } + } - output->registerIndex = input->registerIndex; - output->columnIndex = input->columnIndex; + std::fill(mLinkedAttribute, mLinkedAttribute + ArraySize(mLinkedAttribute), sh::Attribute()); + mOutputVariables.clear(); - matched = true; - break; - } - } + mProgram->reset(); - // We permit unmatched, unreferenced varyings - if (!matched && input->staticUse) - { - infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); - return false; - } - } + mValidated = false; - return true; + mLinked = false; } -LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) +bool Program::isLinked() { -#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED - return LinkResult(false, Error(GL_NO_ERROR)); + return mLinked; +} + +Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei length) +{ + unlink(false); + +#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED + return Error(GL_NO_ERROR); #else ASSERT(binaryFormat == mProgram->getBinaryFormat()); - reset(); - BinaryInputStream stream(binary, length); GLenum format = stream.readInt<GLenum>(); if (format != mProgram->getBinaryFormat()) { - infoLog.append("Invalid program binary format."); - return LinkResult(false, Error(GL_NO_ERROR)); + mInfoLog.append("Invalid program binary format."); + return Error(GL_NO_ERROR); } int majorVersion = stream.readInt<int>(); int minorVersion = stream.readInt<int>(); if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) { - infoLog.append("Invalid program binary version."); - return LinkResult(false, Error(GL_NO_ERROR)); + mInfoLog.append("Invalid program binary version."); + return Error(GL_NO_ERROR); } unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE); if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { - infoLog.append("Invalid program binary version."); - return LinkResult(false, Error(GL_NO_ERROR)); - } - - int compileFlags = stream.readInt<int>(); - if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) - { - infoLog.append("Mismatched compilation flags."); - return LinkResult(false, Error(GL_NO_ERROR)); + mInfoLog.append("Invalid program binary version."); + return Error(GL_NO_ERROR); } for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) @@ -408,22 +452,21 @@ LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void stream.readString(&mLinkedAttribute[i].name); stream.readInt(&mProgram->getShaderAttributes()[i].type); stream.readString(&mProgram->getShaderAttributes()[i].name); - stream.readInt(&mSemanticIndex[i]); + stream.readInt(&mProgram->getSemanticIndexes()[i]); } - initAttributesByLayout(); - - LinkResult result = mProgram->load(infoLog, &stream); + rx::LinkResult result = mProgram->load(mInfoLog, &stream); if (result.error.isError() || !result.linkSuccess) { - return result; + return result.error; } - return LinkResult(true, Error(GL_NO_ERROR)); + mLinked = true; + return Error(GL_NO_ERROR); #endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED } -Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) +Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const { if (binaryFormat) { @@ -436,7 +479,6 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G stream.writeInt(ANGLE_MAJOR_VERSION); stream.writeInt(ANGLE_MINOR_VERSION); stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); - stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { @@ -444,10 +486,14 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G stream.writeString(mLinkedAttribute[i].name); stream.writeInt(mProgram->getShaderAttributes()[i].type); stream.writeString(mProgram->getShaderAttributes()[i].name); - stream.writeInt(mSemanticIndex[i]); + stream.writeInt(mProgram->getSemanticIndexes()[i]); } - mProgram->save(&stream); + gl::Error error = mProgram->save(&stream); + if (error.isError()) + { + return error; + } GLsizei streamLength = stream.length(); const void *streamData = stream.data(); @@ -467,7 +513,7 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G if (binary) { - char *ptr = (char*) binary; + char *ptr = reinterpret_cast<char*>(binary); memcpy(ptr, streamData, streamLength); ptr += streamLength; @@ -483,10 +529,10 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G return Error(GL_NO_ERROR); } -GLint ProgramBinary::getLength() +GLint Program::getBinaryLength() const { GLint length; - Error error = save(NULL, NULL, INT_MAX, &length); + Error error = saveBinary(NULL, NULL, std::numeric_limits<GLint>::max(), &length); if (error.isError()) { return 0; @@ -495,169 +541,742 @@ GLint ProgramBinary::getLength() return length; } -LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, - Shader *fragmentShader, Shader *vertexShader, - const std::vector<std::string> &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode) +void Program::release() { - if (!fragmentShader || !fragmentShader->isCompiled()) + mRefCount--; + + if (mRefCount == 0 && mDeleteStatus) { - return LinkResult(false, Error(GL_NO_ERROR)); + mResourceManager->deleteProgram(mHandle); } - ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); +} + +void Program::addRef() +{ + mRefCount++; +} - if (!vertexShader || !vertexShader->isCompiled()) +unsigned int Program::getRefCount() const +{ + return mRefCount; +} + +int Program::getInfoLogLength() const +{ + return mInfoLog.getLength(); +} + +void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) +{ + return mInfoLog.getLog(bufSize, length, infoLog); +} + +void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) +{ + int total = 0; + + if (mVertexShader) { - return LinkResult(false, Error(GL_NO_ERROR)); - } - ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); + if (total < maxCount) + { + shaders[total] = mVertexShader->getHandle(); + } - reset(); + total++; + } - 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) + if (mFragmentShader) { - return result; + if (total < maxCount) + { + shaders[total] = mFragmentShader->getHandle(); + } + + total++; } - if (!linkAttributes(infoLog, attributeBindings, vertexShader)) + if (count) { - return LinkResult(false, Error(GL_NO_ERROR)); + *count = total; } +} - if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps)) +GLuint Program::getAttributeLocation(const std::string &name) +{ + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) { - return LinkResult(false, Error(GL_NO_ERROR)); + if (mLinkedAttribute[index].name == name) + { + return index; + } } - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps)) + return static_cast<GLuint>(-1); +} + +int Program::getSemanticIndex(int attributeIndex) +{ + ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); + + return mProgram->getSemanticIndexes()[attributeIndex]; +} + +void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + if (mLinked) { - return LinkResult(false, Error(GL_NO_ERROR)); + // Skip over inactive attributes + unsigned int activeAttribute = 0; + unsigned int attribute; + for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) + { + if (mLinkedAttribute[attribute].name.empty()) + { + continue; + } + + if (activeAttribute == index) + { + break; + } + + activeAttribute++; + } + + if (bufsize > 0) + { + const char *string = mLinkedAttribute[attribute].name.c_str(); + + strncpy(name, string, bufsize); + name[bufsize - 1] = '\0'; + + if (length) + { + *length = strlen(name); + } + } + + *size = 1; // Always a single 'type' instance + + *type = mLinkedAttribute[attribute].type; + } + else + { + if (bufsize > 0) + { + name[0] = '\0'; + } + + if (length) + { + *length = 0; + } + + *type = GL_NONE; + *size = 1; } +} - if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) +GLint Program::getActiveAttributeCount() +{ + int count = 0; + + if (mLinked) { - return LinkResult(false, Error(GL_NO_ERROR)); + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (!mLinkedAttribute[attributeIndex].name.empty()) + { + count++; + } + } } - // 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) + return count; +} + +GLint Program::getActiveAttributeMaxLength() +{ + int maxLength = 0; + + if (mLinked) { - infoLog.append("Failed to create D3D shaders."); - reset(); - return result; + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (!mLinkedAttribute[attributeIndex].name.empty()) + { + maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength); + } + } } - return LinkResult(true, Error(GL_NO_ERROR)); + return maxLength; } -bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps) +// Returns one more than the highest sampler index used. +GLint Program::getUsedSamplerRange(SamplerType type) { - const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); - const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); + return mProgram->getUsedSamplerRange(type); +} - // Check that interface blocks defined in the vertex and fragment shaders are identical - typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap; - UniformBlockMap linkedUniformBlocks; +bool Program::usesPointSize() const +{ + return mProgram->usesPointSize(); +} - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) +GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) +{ + return mProgram->getSamplerMapping(type, samplerIndex, caps); +} + +GLenum Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +{ + return mProgram->getSamplerTextureType(type, samplerIndex); +} + +GLint Program::getFragDataLocation(const std::string &name) const +{ + std::string baseName(name); + unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName); + for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++) { - const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; - linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; + const VariableLocation &outputVariable = locationIt->second; + if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element)) + { + return static_cast<GLint>(locationIt->first); + } } + return -1; +} - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) +void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + if (mLinked) { - const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; - UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); - if (entry != linkedUniformBlocks.end()) + ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() + LinkedUniform *uniform = mProgram->getUniforms()[index]; + + if (bufsize > 0) { - const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; - if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) + std::string string = uniform->name; + if (uniform->isArray()) { - return false; + string += "[0]"; + } + + strncpy(name, string.c_str(), bufsize); + name[bufsize - 1] = '\0'; + + if (length) + { + *length = strlen(name); } } + + *size = uniform->elementCount(); + *type = uniform->type; } + else + { + if (bufsize > 0) + { + name[0] = '\0'; + } - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + if (length) + { + *length = 0; + } + + *size = 0; + *type = GL_NONE; + } +} + +GLint Program::getActiveUniformCount() +{ + if (mLinked) { - const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; + return mProgram->getUniforms().size(); + } + else + { + return 0; + } +} - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) +GLint Program::getActiveUniformMaxLength() +{ + int maxLength = 0; + + if (mLinked) + { + unsigned int numUniforms = mProgram->getUniforms().size(); + for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) { - if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + if (!mProgram->getUniforms()[uniformIndex]->name.empty()) { - return false; + int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); + if (mProgram->getUniforms()[uniformIndex]->isArray()) + { + length += 3; // Counting in "[0]". + } + maxLength = std::max(length, maxLength); } } } - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) + return maxLength; +} + +GLint Program::getActiveUniformi(GLuint index, GLenum pname) const +{ + const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; + switch (pname) { - const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type); + case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount()); + case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0)); + case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex; + case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset; + case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride; + case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride; + case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix); + default: + UNREACHABLE(); + break; + } + return 0; +} - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) +bool Program::isValidUniformLocation(GLint location) const +{ + ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size())); + return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size())); +} + +LinkedUniform *Program::getUniformByLocation(GLint location) const +{ + return mProgram->getUniformByLocation(location); +} + +LinkedUniform *Program::getUniformByName(const std::string &name) const +{ + return mProgram->getUniformByName(name); +} + +GLint Program::getUniformLocation(const std::string &name) +{ + return mProgram->getUniformLocation(name); +} + +GLuint Program::getUniformIndex(const std::string &name) +{ + return mProgram->getUniformIndex(name); +} + +void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform1fv(location, count, v); +} + +void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform2fv(location, count, v); +} + +void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform3fv(location, count, v); +} + +void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform4fv(location, count, v); +} + +void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform1iv(location, count, v); +} + +void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform2iv(location, count, v); +} + +void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform3iv(location, count, v); +} + +void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform4iv(location, count, v); +} + +void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform1uiv(location, count, v); +} + +void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform2uiv(location, count, v); +} + +void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform3uiv(location, count, v); +} + +void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform4uiv(location, count, v); +} + +void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix2fv(location, count, transpose, v); +} + +void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix3fv(location, count, transpose, v); +} + +void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix4fv(location, count, transpose, v); +} + +void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix2x3fv(location, count, transpose, v); +} + +void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix2x4fv(location, count, transpose, v); +} + +void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix3x2fv(location, count, transpose, v); +} + +void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix3x4fv(location, count, transpose, v); +} + +void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix4x2fv(location, count, transpose, v); +} + +void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix4x3fv(location, count, transpose, v); +} + +void Program::getUniformfv(GLint location, GLfloat *v) +{ + mProgram->getUniformfv(location, v); +} + +void Program::getUniformiv(GLint location, GLint *v) +{ + mProgram->getUniformiv(location, v); +} + +void Program::getUniformuiv(GLint location, GLuint *v) +{ + mProgram->getUniformuiv(location, v); +} + +// Applies all the uniforms set for this program object to the renderer +Error Program::applyUniforms() +{ + return mProgram->applyUniforms(); +} + +Error Program::applyUniformBuffers(const gl::Data &data) +{ + return mProgram->applyUniformBuffers(data, mUniformBlockBindings); +} + +void Program::flagForDeletion() +{ + mDeleteStatus = true; +} + +bool Program::isFlaggedForDeletion() const +{ + return mDeleteStatus; +} + +void Program::validate(const Caps &caps) +{ + mInfoLog.reset(); + mValidated = false; + + if (mLinked) + { + applyUniforms(); + mValidated = mProgram->validateSamplers(&mInfoLog, caps); + } + else + { + mInfoLog.append("Program has not been successfully linked."); + } +} + +bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps) +{ + return mProgram->validateSamplers(infoLog, caps); +} + +bool Program::isValidated() const +{ + return mValidated; +} + +void Program::updateSamplerMapping() +{ + return mProgram->updateSamplerMapping(); +} + +GLuint Program::getActiveUniformBlockCount() +{ + return mProgram->getUniformBlocks().size(); +} + +void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const +{ + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() + + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + + if (bufSize > 0) + { + std::string string = uniformBlock.name; + + if (uniformBlock.isArrayElement()) { - if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + string += ArrayString(uniformBlock.elementIndex); + } + + strncpy(uniformBlockName, string.c_str(), bufSize); + uniformBlockName[bufSize - 1] = '\0'; + + if (length) + { + *length = strlen(uniformBlockName); + } + } +} + +void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const +{ + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() + + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + + switch (pname) + { + case GL_UNIFORM_BLOCK_DATA_SIZE: + *params = static_cast<GLint>(uniformBlock.dataSize); + break; + case GL_UNIFORM_BLOCK_NAME_LENGTH: + *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); + break; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size()); + break; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + { + for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) { - return false; + params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]); } } + break; + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader()); + break; + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader()); + break; + default: UNREACHABLE(); } +} - return true; +GLint Program::getActiveUniformBlockMaxLength() +{ + int maxLength = 0; + + if (mLinked) + { + unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) + { + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + if (!uniformBlock.name.empty()) + { + const int length = uniformBlock.name.length() + 1; + + // Counting in "[0]". + const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); + + maxLength = std::max(length + arrayLength, maxLength); + } + } + } + + return maxLength; } -bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, - const sh::InterfaceBlock &fragmentInterfaceBlock) +GLuint Program::getUniformBlockIndex(const std::string &name) { - const char* blockName = vertexInterfaceBlock.name.c_str(); + return mProgram->getUniformBlockIndex(name); +} - // validate blocks for the same member types - if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) +const UniformBlock *Program::getUniformBlockByIndex(GLuint index) const +{ + return mProgram->getUniformBlockByIndex(index); +} + +void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; +} + +GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const +{ + return mUniformBlockBindings[uniformBlockIndex]; +} + +void Program::resetUniformBlockBindings() +{ + for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++) { - infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); - return false; + mUniformBlockBindings[blockId] = 0; } +} - if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) +void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) +{ + mTransformFeedbackVaryings.resize(count); + for (GLsizei i = 0; i < count; i++) { - infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; + mTransformFeedbackVaryings[i] = varyings[i]; } - if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) + mTransformFeedbackBufferMode = bufferMode; +} + +void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const +{ + if (mLinked) { - infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; + ASSERT(index < mProgram->getTransformFeedbackLinkedVaryings().size()); + const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[index]; + GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length())); + if (length) + { + *length = lastNameIdx; + } + if (size) + { + *size = varying.size; + } + if (type) + { + *type = varying.type; + } + if (name) + { + memcpy(name, varying.name.c_str(), lastNameIdx); + name[lastNameIdx] = '\0'; + } } +} - const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) +GLsizei Program::getTransformFeedbackVaryingCount() const +{ + if (mLinked) { - const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; - const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; + return static_cast<GLsizei>(mProgram->getTransformFeedbackLinkedVaryings().size()); + } + else + { + return 0; + } +} - if (vertexMember.name != fragmentMember.name) +GLsizei Program::getTransformFeedbackVaryingMaxLength() const +{ + if (mLinked) + { + GLsizei maxSize = 0; + for (size_t i = 0; i < mProgram->getTransformFeedbackLinkedVaryings().size(); i++) { - 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; + const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[i]; + maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1)); } - std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) + return maxSize; + } + else + { + return 0; + } +} + +GLenum Program::getTransformFeedbackBufferMode() const +{ + return mTransformFeedbackBufferMode; +} + +bool Program::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) +{ + std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings(); + std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings(); + + for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) + { + PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; + bool matched = false; + + // Built-in varyings obey special rules + if (input->isBuiltIn()) { + continue; + } + + for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) + { + PackedVarying *output = &vertexVaryings[vertVaryingIndex]; + if (output->name == input->name) + { + if (!linkValidateVaryings(infoLog, output->name, *input, *output)) + { + return false; + } + + output->registerIndex = input->registerIndex; + output->columnIndex = input->columnIndex; + + matched = true; + break; + } + } + + // We permit unmatched, unreferenced varyings + if (!matched && input->staticUse) + { + infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); return false; } } @@ -665,11 +1284,25 @@ bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::I return true; } -// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) +bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) { - const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) + { + return false; + } + + if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) + { + infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); + return false; + } + return true; +} + +// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices +bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) +{ unsigned int usedLocations = 0; const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes(); @@ -744,21 +1377,111 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) { - int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name); + int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); for (int r = 0; r < rows; r++) { - mSemanticIndex[attributeIndex++] = index++; + mProgram->getSemanticIndexes()[attributeIndex++] = index++; } } - initAttributesByLayout(); + return true; +} +bool Program::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 (!mProgram->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 (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } + } + } return true; } -bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, +bool Program::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()) + { + 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 Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision) { if (vertexVariable.type != fragmentVariable.type) @@ -808,7 +1531,7 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin return true; } -bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) +bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) { if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) { @@ -818,14 +1541,14 @@ bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &un return true; } -bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) +bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) { if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) { return false; } - if (vertexVarying.interpolation != fragmentVarying.interpolation) + if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation)) { infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str()); return false; @@ -834,27 +1557,11 @@ bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &va return true; } -bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) -{ - if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) - { - return false; - } - - if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) - { - infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); - return false; - } - - return true; -} - -bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, - const std::vector<std::string> &transformFeedbackVaryingNames, - GLenum transformFeedbackBufferMode, - std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings, - const Caps &caps) const +bool Program::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, + const std::vector<std::string> &transformFeedbackVaryingNames, + GLenum transformFeedbackBufferMode, + std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings, + const Caps &caps) const { size_t totalComponents = 0; @@ -907,327 +1614,4 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons return true; } -bool ProgramBinary::isValidated() const -{ - return mValidated; -} - -void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const -{ - // Skip over inactive attributes - unsigned int activeAttribute = 0; - unsigned int attribute; - for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) - { - if (mLinkedAttribute[attribute].name.empty()) - { - continue; - } - - if (activeAttribute == index) - { - break; - } - - activeAttribute++; - } - - if (bufsize > 0) - { - const char *string = mLinkedAttribute[attribute].name.c_str(); - - strncpy(name, string, bufsize); - name[bufsize - 1] = '\0'; - - if (length) - { - *length = strlen(name); - } - } - - *size = 1; // Always a single 'type' instance - - *type = mLinkedAttribute[attribute].type; -} - -GLint ProgramBinary::getActiveAttributeCount() const -{ - int count = 0; - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (!mLinkedAttribute[attributeIndex].name.empty()) - { - count++; - } - } - - return count; -} - -GLint ProgramBinary::getActiveAttributeMaxLength() const -{ - int maxLength = 0; - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (!mLinkedAttribute[attributeIndex].name.empty()) - { - maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength); - } - } - - return maxLength; -} - -void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const -{ - ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() - - if (bufsize > 0) - { - std::string string = mProgram->getUniforms()[index]->name; - - if (mProgram->getUniforms()[index]->isArray()) - { - string += "[0]"; - } - - strncpy(name, string.c_str(), bufsize); - name[bufsize - 1] = '\0'; - - if (length) - { - *length = strlen(name); - } - } - - *size = mProgram->getUniforms()[index]->elementCount(); - - *type = mProgram->getUniforms()[index]->type; -} - -GLint ProgramBinary::getActiveUniformCount() const -{ - return mProgram->getUniforms().size(); -} - -GLint ProgramBinary::getActiveUniformMaxLength() const -{ - int maxLength = 0; - - unsigned int numUniforms = mProgram->getUniforms().size(); - for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) - { - if (!mProgram->getUniforms()[uniformIndex]->name.empty()) - { - int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); - if (mProgram->getUniforms()[uniformIndex]->isArray()) - { - length += 3; // Counting in "[0]". - } - maxLength = std::max(length, maxLength); - } - } - - return maxLength; -} - -GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const -{ - const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; - - switch (pname) - { - case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type); - case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount()); - case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0)); - case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex; - - case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset; - case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride; - case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride; - case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix); - - default: - UNREACHABLE(); - break; - } - return 0; -} - -bool ProgramBinary::isValidUniformLocation(GLint location) const -{ - ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size())); - return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size())); -} - -LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const -{ - return mProgram->getUniformByLocation(location); -} - -LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const -{ - return mProgram->getUniformByName(name); -} - -void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const -{ - ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; - - if (bufSize > 0) - { - std::string string = uniformBlock.name; - - if (uniformBlock.isArrayElement()) - { - string += ArrayString(uniformBlock.elementIndex); - } - - strncpy(uniformBlockName, string.c_str(), bufSize); - uniformBlockName[bufSize - 1] = '\0'; - - if (length) - { - *length = strlen(uniformBlockName); - } - } -} - -void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const -{ - ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; - - switch (pname) - { - case GL_UNIFORM_BLOCK_DATA_SIZE: - *params = static_cast<GLint>(uniformBlock.dataSize); - break; - case GL_UNIFORM_BLOCK_NAME_LENGTH: - *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); - break; - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size()); - break; - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - { - for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) - { - params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]); - } - } - break; - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader()); - break; - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader()); - break; - default: UNREACHABLE(); - } -} - -GLuint ProgramBinary::getActiveUniformBlockCount() const -{ - return mProgram->getUniformBlocks().size(); -} - -GLuint ProgramBinary::getActiveUniformBlockMaxLength() const -{ - unsigned int maxLength = 0; - - unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) - { - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; - if (!uniformBlock.name.empty()) - { - const unsigned int length = uniformBlock.name.length() + 1; - - // Counting in "[0]". - const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); - - maxLength = std::max(length + arrayLength, maxLength); - } - } - - return maxLength; -} - -void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) -{ - applyUniforms(); - if (!validateSamplers(&infoLog, caps)) - { - mValidated = false; - } - else - { - mValidated = true; - } -} - -bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) -{ - return mProgram->validateSamplers(infoLog, caps); -} - -struct AttributeSorter -{ - AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS]) - : originalIndices(semanticIndices) - { - } - - bool operator()(int a, int b) - { - if (originalIndices[a] == -1) return false; - if (originalIndices[b] == -1) return true; - return (originalIndices[a] < originalIndices[b]); - } - - const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; -}; - -void ProgramBinary::initAttributesByLayout() -{ - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mAttributesByLayout[i] = i; - } - - std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex)); -} - -void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const -{ - rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS]; - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - oldTranslatedAttributes[i] = attributes[i]; - } - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - int oldIndex = mAttributesByLayout[i]; - sortedSemanticIndices[i] = oldIndex; - attributes[i] = oldTranslatedAttributes[oldIndex]; - } -} - -void ProgramBinary::reset() -{ - mOutputVariables.clear(); - - mProgram->reset(); - - mValidated = false; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libANGLE/Program.h index 3142d66c6d..38fc83d29d 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libANGLE/Program.h @@ -7,60 +7,79 @@ // Program.h: Defines the gl::Program class. Implements GL program objects // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. -#ifndef LIBGLESV2_PROGRAM_BINARY_H_ -#define LIBGLESV2_PROGRAM_BINARY_H_ +#ifndef LIBANGLE_PROGRAM_H_ +#define LIBANGLE_PROGRAM_H_ -#include "common/RefCountObject.h" -#include "angletypes.h" -#include "common/mathutil.h" -#include "libGLESv2/Uniform.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" -#include "angle_gl.h" +#include "common/angleutils.h" -#include <string> -#include <vector> - -namespace sh -{ -class HLSLBlockEncoder; -} - -#include <GLES3/gl3.h> #include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> +#include <GLSLANG/ShaderLang.h> -#include <string> #include <vector> +#include <string> +#include <set> namespace rx { -class ShaderExecutable; +class Renderer; +class Renderer; struct TranslatedAttribute; -class UniformStorage; class ProgramImpl; } namespace gl { struct Caps; +struct Data; +class ResourceManager; class Shader; class InfoLog; class AttributeBindings; class Buffer; class Framebuffer; -struct Data; +struct UniformBlock; +struct LinkedUniform; + +extern const char * const g_fakepath; + +class AttributeBindings +{ + public: + AttributeBindings(); + ~AttributeBindings(); + + void bindAttributeLocation(GLuint index, const char *name); + int getAttributeBinding(const std::string &name) const; + + private: + std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS]; +}; + +class InfoLog : angle::NonCopyable +{ + public: + InfoLog(); + ~InfoLog(); + + int getLength() const; + void getLog(GLsizei bufSize, GLsizei *length, char *infoLog); + + void appendSanitized(const char *message); + void append(const char *info, ...); + void reset(); + private: + char *mInfoLog; +}; // Struct used for correlating uniforms/elements of uniform arrays to handles struct VariableLocation { - VariableLocation() - { - } - + VariableLocation(); VariableLocation(const std::string &name, unsigned int element, unsigned int index); std::string name; @@ -72,7 +91,7 @@ struct LinkedVarying { LinkedVarying(); LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, - unsigned int semanticIndex, unsigned int semanticIndexCount); + unsigned int semanticIndex, unsigned int semanticIndexCount); // Original GL name std::string name; @@ -86,35 +105,58 @@ 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 +class Program : angle::NonCopyable { public: - explicit ProgramBinary(rx::ProgramImpl *impl); - ~ProgramBinary(); + Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle); + ~Program(); + + GLuint id() const { return mHandle; } rx::ProgramImpl *getImplementation() { return mProgram; } const rx::ProgramImpl *getImplementation() const { return mProgram; } - GLuint getAttributeLocation(const char *name); + bool attachShader(Shader *shader); + bool detachShader(Shader *shader); + int getAttachedShadersCount() const; + + void bindAttributeLocation(GLuint index, const char *name); + + Error link(const Data &data); + bool isLinked(); + + Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length); + Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const; + GLint getBinaryLength() const; + + int getInfoLogLength() const; + void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); + void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); + + GLuint getAttributeLocation(const std::string &name); int getSemanticIndex(int attributeIndex); + void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); + GLint getActiveAttributeCount(); + GLint getActiveAttributeMaxLength(); + GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; - GLint getUniformLocation(std::string name); - GLuint getUniformIndex(std::string name); - GLuint getUniformBlockIndex(std::string name); + GLint getFragDataLocation(const std::string &name) const; + + void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); + GLint getActiveUniformCount(); + GLint getActiveUniformMaxLength(); + GLint getActiveUniformi(GLuint index, GLenum pname) const; + bool isValidUniformLocation(GLint location) const; + LinkedUniform *getUniformByLocation(GLint location) const; + LinkedUniform *getUniformByName(const std::string &name) const; + + GLint getUniformLocation(const std::string &name); + GLuint getUniformIndex(const std::string &name); void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); @@ -142,59 +184,44 @@ class ProgramBinary : public RefCountObject void getUniformuiv(GLint location, GLuint *params); Error applyUniforms(); - Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps); - - LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); - Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); - GLint getLength(); - - 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; - GLint getActiveAttributeMaxLength() const; - - void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; - GLint getActiveUniformCount() const; - GLint getActiveUniformMaxLength() const; - GLint getActiveUniformi(GLuint index, GLenum pname) const; - bool isValidUniformLocation(GLint location) const; - LinkedUniform *getUniformByLocation(GLint location) const; - LinkedUniform *getUniformByName(const std::string &name) const; + Error applyUniformBuffers(const gl::Data &data); void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; - GLuint getActiveUniformBlockCount() const; - GLuint getActiveUniformBlockMaxLength() const; - UniformBlock *getUniformBlockByIndex(GLuint blockIndex); + GLuint getActiveUniformBlockCount(); + GLint getActiveUniformBlockMaxLength(); - GLint getFragDataLocation(const char *name) const; - - size_t getTransformFeedbackVaryingCount() const; - const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; - GLenum getTransformFeedbackBufferMode() const; + GLuint getUniformBlockIndex(const std::string &name); - void validate(InfoLog &infoLog, const Caps &caps); - bool validateSamplers(InfoLog *infoLog, const Caps &caps); - bool isValidated() const; - void updateSamplerMapping(); + void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); + GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; - unsigned int getSerial() const; + const UniformBlock *getUniformBlockByIndex(GLuint index) const; - void initAttributesByLayout(); - void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; + void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); + void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; + GLsizei getTransformFeedbackVaryingCount() const; + GLsizei getTransformFeedbackVaryingMaxLength() const; + GLenum getTransformFeedbackBufferMode() const; 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); + void addRef(); + void release(); + unsigned int getRefCount() const; + void flagForDeletion(); + bool isFlaggedForDeletion() const; - void reset(); + void validate(const Caps &caps); + bool validateSamplers(InfoLog *infoLog, const Caps &caps); + bool isValidated() const; + void updateSamplerMapping(); + + private: + void unlink(bool destroy = false); + void resetUniformBlockBindings(); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); @@ -219,19 +246,31 @@ class ProgramBinary : public RefCountObject rx::ProgramImpl *mProgram; sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; - int mSemanticIndex[MAX_VERTEX_ATTRIBS]; - int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; std::map<int, VariableLocation> mOutputVariables; bool mValidated; - const unsigned int mSerial; + Shader *mFragmentShader; + Shader *mVertexShader; - static unsigned int issueSerial(); - static unsigned int mCurrentSerial; -}; + AttributeBindings mAttributeBindings; + + GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + + std::vector<std::string> mTransformFeedbackVaryings; + GLenum mTransformFeedbackBufferMode; + bool mLinked; + bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use + + unsigned int mRefCount; + + ResourceManager *mResourceManager; + const GLuint mHandle; + + InfoLog mInfoLog; +}; } -#endif // LIBGLESV2_PROGRAM_BINARY_H_ +#endif // LIBANGLE_PROGRAM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libANGLE/Query.cpp index 4ee3525509..a402b732bf 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.cpp +++ b/src/3rdparty/angle/src/libANGLE/Query.cpp @@ -6,8 +6,8 @@ // Query.cpp: Implements the gl::Query class -#include "libGLESv2/Query.h" -#include "libGLESv2/renderer/QueryImpl.h" +#include "libANGLE/Query.h" +#include "libANGLE/renderer/QueryImpl.h" namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libANGLE/Query.h index a7ec404f85..8585fde0e2 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.h +++ b/src/3rdparty/angle/src/libANGLE/Query.h @@ -6,12 +6,13 @@ // Query.h: Defines the gl::Query class -#ifndef LIBGLESV2_QUERY_H_ -#define LIBGLESV2_QUERY_H_ +#ifndef LIBANGLE_QUERY_H_ +#define LIBANGLE_QUERY_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" -#include "libGLESv2/Error.h" #include "common/angleutils.h" -#include "common/RefCountObject.h" #include "angle_gl.h" @@ -38,11 +39,9 @@ class Query : public RefCountObject GLenum getType() const; private: - DISALLOW_COPY_AND_ASSIGN(Query); - rx::QueryImpl *mQuery; }; } -#endif // LIBGLESV2_QUERY_H_ +#endif // LIBANGLE_QUERY_H_ diff --git a/src/3rdparty/angle/src/common/RefCountObject.cpp b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp index c1ef90cdcc..b1210200cf 100644 --- a/src/3rdparty/angle/src/common/RefCountObject.cpp +++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp @@ -12,9 +12,9 @@ #include "RefCountObject.h" RefCountObject::RefCountObject(GLuint id) + : mId(id), + mRefCount(0) { - mId = id; - mRefCount = 0; } RefCountObject::~RefCountObject() @@ -37,11 +37,3 @@ void RefCountObject::release() const } } -void RefCountObjectBindingPointer::set(RefCountObject *newObject) -{ - // addRef first in case newObject == mObject and this is the last reference to it. - if (newObject != NULL) newObject->addRef(); - if (mObject != NULL) mObject->release(); - - mObject = newObject; -} diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.h b/src/3rdparty/angle/src/libANGLE/RefCountObject.h new file mode 100644 index 0000000000..48c0338c3f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.h @@ -0,0 +1,110 @@ +// +// Copyright (c) 2002-2010 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. +// + +// RefCountObject.h: Defines the gl::RefCountObject base class that provides +// lifecycle support for GL objects using the traditional BindObject scheme, but +// that need to be reference counted for correct cross-context deletion. +// (Concretely, textures, buffers and renderbuffers.) + +#ifndef LIBANGLE_REFCOUNTOBJECT_H_ +#define LIBANGLE_REFCOUNTOBJECT_H_ + +#include "common/debug.h" + +#include "angle_gl.h" + +#include <cstddef> + +class RefCountObject : angle::NonCopyable +{ + public: + explicit RefCountObject(GLuint id); + virtual ~RefCountObject(); + + virtual void addRef() const; + virtual void release() const; + + GLuint id() const { return mId; } + + private: + GLuint mId; + + mutable std::size_t mRefCount; +}; + +template <class ObjectType> +class BindingPointer +{ +public: + BindingPointer() + : mObject(nullptr) + { + } + + BindingPointer(const BindingPointer<ObjectType> &other) + : mObject(nullptr) + { + set(other.mObject); + } + + void operator=(const BindingPointer<ObjectType> &other) + { + set(other.mObject); + } + + virtual ~BindingPointer() + { + // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up. + ASSERT(mObject == nullptr); + } + + virtual void set(ObjectType *newObject) + { + // addRef first in case newObject == mObject and this is the last reference to it. + if (newObject != nullptr) reinterpret_cast<const RefCountObject*>(newObject)->addRef(); + if (mObject != nullptr) reinterpret_cast<const RefCountObject*>(mObject)->release(); + mObject = newObject; + } + + ObjectType *get() const { return mObject; } + ObjectType *operator->() const { return mObject; } + + GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; } + bool operator!() const { return (mObject == nullptr); } + + private: + ObjectType *mObject; +}; + +template <class ObjectType> +class OffsetBindingPointer : public BindingPointer<ObjectType> +{ + public: + OffsetBindingPointer() : mOffset(0), mSize(0) { } + + void set(ObjectType *newObject) override + { + BindingPointer<ObjectType>::set(newObject); + mOffset = 0; + mSize = 0; + } + + void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size) + { + BindingPointer<ObjectType>::set(newObject); + mOffset = offset; + mSize = size; + } + + GLintptr getOffset() const { return mOffset; } + GLsizeiptr getSize() const { return mSize; } + + private: + GLintptr mOffset; + GLsizeiptr mSize; +}; + +#endif // LIBANGLE_REFCOUNTOBJECT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp index 911a389dfa..6a0cde812b 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp @@ -8,29 +8,25 @@ // 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/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/RenderbufferImpl.h" +#include "libANGLE/Renderbuffer.h" #include "common/utilities.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/RenderbufferImpl.h" namespace gl { Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id) : RefCountObject(id), - mRenderbuffer(impl) + mRenderbuffer(impl), + mWidth(0), + mHeight(0), + mInternalFormat(GL_RGBA4), + mSamples(0) { - ASSERT(mRenderbuffer); - - mWidth = mRenderbuffer->getWidth(); - mHeight = mRenderbuffer->getHeight(); - mInternalFormat = mRenderbuffer->getInternalFormat(); - mActualFormat = mRenderbuffer->getActualFormat(); - mSamples = mRenderbuffer->getSamples(); } Renderbuffer::~Renderbuffer() @@ -38,9 +34,25 @@ Renderbuffer::~Renderbuffer() SafeDelete(mRenderbuffer); } -Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) +Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height) +{ + Error error = mRenderbuffer->setStorage(internalformat, width, height); + if (error.isError()) + { + return error; + } + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + mSamples = 0; + + return Error(GL_NO_ERROR); +} + +Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) { - Error error = mRenderbuffer->setStorage(width, height, internalformat, samples); + Error error = mRenderbuffer->setStorageMultisample(samples, internalformat, width, height); if (error.isError()) { return error; @@ -50,7 +62,6 @@ Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalfor mHeight = height; mInternalFormat = internalformat; mSamples = samples; - mActualFormat = mRenderbuffer->getActualFormat(); return Error(GL_NO_ERROR); } @@ -61,6 +72,11 @@ rx::RenderbufferImpl *Renderbuffer::getImplementation() return mRenderbuffer; } +const rx::RenderbufferImpl *Renderbuffer::getImplementation() const +{ + return mRenderbuffer; +} + GLsizei Renderbuffer::getWidth() const { return mWidth; @@ -76,11 +92,6 @@ GLenum Renderbuffer::getInternalFormat() const return mInternalFormat; } -GLenum Renderbuffer::getActualFormat() const -{ - return mActualFormat; -} - GLsizei Renderbuffer::getSamples() const { return mSamples; @@ -88,32 +99,32 @@ GLsizei Renderbuffer::getSamples() const GLuint Renderbuffer::getRedSize() const { - return GetInternalFormatInfo(getActualFormat()).redBits; + return GetInternalFormatInfo(mInternalFormat).redBits; } GLuint Renderbuffer::getGreenSize() const { - return GetInternalFormatInfo(getActualFormat()).greenBits; + return GetInternalFormatInfo(mInternalFormat).greenBits; } GLuint Renderbuffer::getBlueSize() const { - return GetInternalFormatInfo(getActualFormat()).blueBits; + return GetInternalFormatInfo(mInternalFormat).blueBits; } GLuint Renderbuffer::getAlphaSize() const { - return GetInternalFormatInfo(getActualFormat()).alphaBits; + return GetInternalFormatInfo(mInternalFormat).alphaBits; } GLuint Renderbuffer::getDepthSize() const { - return GetInternalFormatInfo(getActualFormat()).depthBits; + return GetInternalFormatInfo(mInternalFormat).depthBits; } GLuint Renderbuffer::getStencilSize() const { - return GetInternalFormatInfo(getActualFormat()).stencilBits; + return GetInternalFormatInfo(mInternalFormat).stencilBits; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h index e9f12af3ce..98c7eb0f10 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h @@ -8,15 +8,15 @@ // 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_ +#ifndef LIBANGLE_RENDERBUFFER_H_ +#define LIBANGLE_RENDERBUFFER_H_ #include "angle_gl.h" -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" #include "common/angleutils.h" -#include "common/RefCountObject.h" namespace rx { @@ -38,14 +38,15 @@ class Renderbuffer : public RefCountObject Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); virtual ~Renderbuffer(); - Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); + Error setStorage(GLenum internalformat, size_t width, size_t height); + Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height); rx::RenderbufferImpl *getImplementation(); + const rx::RenderbufferImpl *getImplementation() const; GLsizei getWidth() const; GLsizei getHeight() const; GLenum getInternalFormat() const; - GLenum getActualFormat() const; GLsizei getSamples() const; GLuint getRedSize() const; GLuint getGreenSize() const; @@ -55,17 +56,14 @@ class Renderbuffer : public RefCountObject GLuint getStencilSize() const; private: - DISALLOW_COPY_AND_ASSIGN(Renderbuffer); - rx::RenderbufferImpl *mRenderbuffer; GLsizei mWidth; GLsizei mHeight; GLenum mInternalFormat; - GLenum mActualFormat; GLsizei mSamples; }; } -#endif // LIBGLESV2_RENDERBUFFER_H_ +#endif // LIBANGLE_RENDERBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp index 38d53cad81..aaf144cfa9 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp @@ -7,21 +7,21 @@ // ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and // retrieves objects which may be shared by multiple Contexts. -#include "libGLESv2/ResourceManager.h" +#include "libANGLE/ResourceManager.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Sampler.h" -#include "libGLESv2/Fence.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/Fence.h" +#include "libANGLE/renderer/Renderer.h" namespace gl { -ResourceManager::ResourceManager(rx::Renderer *renderer) - : mRenderer(renderer), +ResourceManager::ResourceManager(rx::ImplFactory *factory) + : mFactory(factory), mRefCount(1) { } @@ -94,7 +94,7 @@ GLuint ResourceManager::createShader(const gl::Data &data, GLenum type) if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle); + mShaderMap[handle] = new Shader(this, mFactory->createShader(type), type, handle); } else UNREACHABLE(); @@ -106,7 +106,7 @@ GLuint ResourceManager::createProgram() { GLuint handle = mProgramShaderHandleAllocator.allocate(); - mProgramMap[handle] = new Program(mRenderer, this, handle); + mProgramMap[handle] = new Program(mFactory->createProgram(), this, handle); return handle; } @@ -146,7 +146,7 @@ GLuint ResourceManager::createFenceSync() { GLuint handle = mFenceSyncHandleAllocator.allocate(); - FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle); + FenceSync *fenceSync = new FenceSync(mFactory->createFenceSync(), handle); fenceSync->addRef(); mFenceSyncMap[handle] = fenceSync; @@ -356,56 +356,84 @@ void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer) mRenderbufferMap[handle] = buffer; } -void ResourceManager::checkBufferAllocation(unsigned int buffer) +void ResourceManager::checkBufferAllocation(GLuint handle) { - if (buffer != 0 && !getBuffer(buffer)) + if (handle != 0) { - Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer); - mBufferMap[buffer] = bufferObject; - bufferObject->addRef(); - } -} + auto bufferMapIt = mBufferMap.find(handle); + bool handleAllocated = (bufferMapIt != mBufferMap.end()); -void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type) -{ - if (!getTexture(texture) && texture != 0) - { - Texture *textureObject; + if (handleAllocated && bufferMapIt->second != nullptr) + { + return; + } + + Buffer *buffer = new Buffer(mFactory->createBuffer(), handle); + buffer->addRef(); - if (type == GL_TEXTURE_2D) + if (handleAllocated) { - textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture); + bufferMapIt->second = buffer; } - else if (type == GL_TEXTURE_CUBE_MAP) + else { - textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture); + mBufferHandleAllocator.reserve(handle); + mBufferMap[handle] = buffer; } - else if (type == GL_TEXTURE_3D) + } +} + +void ResourceManager::checkTextureAllocation(GLuint handle, GLenum type) +{ + if (handle != 0) + { + auto textureMapIt = mTextureMap.find(handle); + bool handleAllocated = (textureMapIt != mTextureMap.end()); + + if (handleAllocated && textureMapIt->second != nullptr) { - textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture); + return; } - else if (type == GL_TEXTURE_2D_ARRAY) + + Texture *texture = new Texture(mFactory->createTexture(type), handle, type); + texture->addRef(); + + if (handleAllocated) { - textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture); + textureMapIt->second = texture; } else { - UNREACHABLE(); - return; + mTextureHandleAllocator.reserve(handle); + mTextureMap[handle] = texture; } - - mTextureMap[texture] = textureObject; - textureObject->addRef(); } } -void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) +void ResourceManager::checkRenderbufferAllocation(GLuint handle) { - if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) + if (handle != 0) { - Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer); - mRenderbufferMap[renderbuffer] = renderbufferObject; - renderbufferObject->addRef(); + auto renderbufferMapIt = mRenderbufferMap.find(handle); + bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end()); + + if (handleAllocated && renderbufferMapIt->second != nullptr) + { + return; + } + + Renderbuffer *renderbuffer = new Renderbuffer(mFactory->createRenderbuffer(), handle); + renderbuffer->addRef(); + + if (handleAllocated) + { + renderbufferMapIt->second = renderbuffer; + } + else + { + mRenderbufferHandleAllocator.reserve(handle); + mRenderbufferMap[handle] = renderbuffer; + } } } @@ -416,6 +444,7 @@ void ResourceManager::checkSamplerAllocation(GLuint sampler) Sampler *samplerObject = new Sampler(sampler); mSamplerMap[sampler] = samplerObject; samplerObject->addRef(); + // Samplers cannot be created via Bind } } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libANGLE/ResourceManager.h index acad29b51d..8e95e8840a 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.h @@ -7,20 +7,19 @@ // ResourceManager.h : Defines the ResourceManager class, which tracks objects // shared by multiple GL contexts. -#ifndef LIBGLESV2_RESOURCEMANAGER_H_ -#define LIBGLESV2_RESOURCEMANAGER_H_ - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/HandleAllocator.h" +#ifndef LIBANGLE_RESOURCEMANAGER_H_ +#define LIBANGLE_RESOURCEMANAGER_H_ #include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/HandleAllocator.h" -#include <unordered_map> +#include <map> namespace rx { -class Renderer; +class ImplFactory; } namespace gl @@ -34,10 +33,10 @@ class Sampler; class FenceSync; struct Data; -class ResourceManager +class ResourceManager : angle::NonCopyable { public: - explicit ResourceManager(rx::Renderer *renderer); + explicit ResourceManager(rx::ImplFactory *factory); ~ResourceManager(); void addRef(); @@ -69,47 +68,47 @@ class ResourceManager void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); - void checkBufferAllocation(unsigned int buffer); - void checkTextureAllocation(GLuint texture, GLenum type); - void checkRenderbufferAllocation(GLuint renderbuffer); + void checkBufferAllocation(GLuint handle); + void checkTextureAllocation(GLuint handle, GLenum type); + void checkRenderbufferAllocation(GLuint handle); void checkSamplerAllocation(GLuint sampler); bool isSampler(GLuint sampler); private: - DISALLOW_COPY_AND_ASSIGN(ResourceManager); + void createTextureInternal(GLuint handle); - rx::Renderer *mRenderer; + rx::ImplFactory *mFactory; std::size_t mRefCount; - typedef std::unordered_map<GLuint, Buffer*> BufferMap; + typedef std::map<GLuint, Buffer*> BufferMap; BufferMap mBufferMap; HandleAllocator mBufferHandleAllocator; - typedef std::unordered_map<GLuint, Shader*> ShaderMap; + typedef std::map<GLuint, Shader*> ShaderMap; ShaderMap mShaderMap; - typedef std::unordered_map<GLuint, Program*> ProgramMap; + typedef std::map<GLuint, Program*> ProgramMap; ProgramMap mProgramMap; HandleAllocator mProgramShaderHandleAllocator; - typedef std::unordered_map<GLuint, Texture*> TextureMap; + typedef std::map<GLuint, Texture*> TextureMap; TextureMap mTextureMap; HandleAllocator mTextureHandleAllocator; - typedef std::unordered_map<GLuint, Renderbuffer*> RenderbufferMap; + typedef std::map<GLuint, Renderbuffer*> RenderbufferMap; RenderbufferMap mRenderbufferMap; HandleAllocator mRenderbufferHandleAllocator; - typedef std::unordered_map<GLuint, Sampler*> SamplerMap; + typedef std::map<GLuint, Sampler*> SamplerMap; SamplerMap mSamplerMap; HandleAllocator mSamplerHandleAllocator; - typedef std::unordered_map<GLuint, FenceSync*> FenceMap; + typedef std::map<GLuint, FenceSync*> FenceMap; FenceMap mFenceSyncMap; HandleAllocator mFenceSyncHandleAllocator; }; } -#endif // LIBGLESV2_RESOURCEMANAGER_H_ +#endif // LIBANGLE_RESOURCEMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libANGLE/Sampler.cpp index b906e65557..d58bd5a862 100644 --- a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp +++ b/src/3rdparty/angle/src/libANGLE/Sampler.cpp @@ -7,8 +7,8 @@ // Sampler.cpp : Implements the Sampler class, which represents a GLES 3 // sampler object. Sampler objects store some state needed to sample textures. -#include "libGLESv2/Sampler.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/angletypes.h" namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.h b/src/3rdparty/angle/src/libANGLE/Sampler.h index 257bc25d22..d33798ff15 100644 --- a/src/3rdparty/angle/src/libGLESv2/Sampler.h +++ b/src/3rdparty/angle/src/libANGLE/Sampler.h @@ -7,10 +7,10 @@ // Sampler.h : Defines the Sampler class, which represents a GLES 3 // sampler object. Sampler objects store some state needed to sample textures. -#ifndef LIBGLESV2_SAMPLER_H_ -#define LIBGLESV2_SAMPLER_H_ +#ifndef LIBANGLE_SAMPLER_H_ +#define LIBANGLE_SAMPLER_H_ -#include "common/RefCountObject.h" +#include "libANGLE/RefCountObject.h" namespace gl { @@ -57,4 +57,4 @@ class Sampler : public RefCountObject } -#endif // LIBGLESV2_SAMPLER_H_ +#endif // LIBANGLE_SAMPLER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libANGLE/Shader.cpp index 024ef8fb7c..7af4ff358d 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libANGLE/Shader.cpp @@ -8,11 +8,11 @@ // VertexShader and FragmentShader. Implements GL shader objects and related // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. -#include "libGLESv2/Shader.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/ShaderImpl.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/ResourceManager.h" +#include "libANGLE/Shader.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/ShaderImpl.h" +#include "libANGLE/Constants.h" +#include "libANGLE/ResourceManager.h" #include "common/utilities.h" @@ -131,9 +131,9 @@ void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, getSourceImpl(debugInfo, bufSize, length, buffer); } -void Shader::compile(const gl::Data &data) +void Shader::compile(Compiler *compiler) { - mCompiled = mShader->compile(data, mSource); + mCompiled = mShader->compile(compiler, mSource); } void Shader::addRef() @@ -216,4 +216,28 @@ std::vector<sh::Attribute> &Shader::getActiveOutputVariables() return mShader->getActiveOutputVariables(); } + +int Shader::getSemanticIndex(const std::string &attributeName) const +{ + if (!attributeName.empty()) + { + const auto &activeAttributes = mShader->getActiveAttributes(); + + int semanticIndex = 0; + for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + { + const sh::ShaderVariable &attribute = activeAttributes[attributeIndex]; + + if (attribute.name == attributeName) + { + return semanticIndex; + } + + semanticIndex += gl::VariableRegisterCount(attribute.type); + } + } + + return -1; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libANGLE/Shader.h index 904217dab8..10e79c7499 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libANGLE/Shader.h @@ -9,9 +9,8 @@ // related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section // 3.8 page 84. -#ifndef LIBGLESV2_SHADER_H_ -#define LIBGLESV2_SHADER_H_ - +#ifndef LIBANGLE_SHADER_H_ +#define LIBANGLE_SHADER_H_ #include <string> #include <list> @@ -21,7 +20,7 @@ #include <GLSLANG/ShaderLang.h> #include "common/angleutils.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/angletypes.h" namespace rx { @@ -30,6 +29,7 @@ class ShaderImpl; namespace gl { +class Compiler; class ResourceManager; struct Data; @@ -53,7 +53,7 @@ struct PackedVarying : public sh::Varying } }; -class Shader +class Shader : angle::NonCopyable { public: Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); @@ -76,7 +76,7 @@ class Shader void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const; - void compile(const gl::Data &data); + void compile(Compiler *compiler); bool isCompiled() const { return mCompiled; } void addRef(); @@ -97,9 +97,9 @@ class Shader std::vector<sh::Attribute> &getActiveAttributes(); std::vector<sh::Attribute> &getActiveOutputVariables(); - private: - DISALLOW_COPY_AND_ASSIGN(Shader); + int getSemanticIndex(const std::string &attributeName) const; + private: static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer); rx::ShaderImpl *mShader; @@ -115,4 +115,4 @@ class Shader } -#endif // LIBGLESV2_SHADER_H_ +#endif // LIBANGLE_SHADER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp index b5b62f5848..4c044d2950 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.cpp +++ b/src/3rdparty/angle/src/libANGLE/State.cpp @@ -6,16 +6,15 @@ // State.cpp: Implements the State class, encapsulating raw GL state. -#include "libGLESv2/State.h" +#include "libANGLE/State.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/RenderTarget.h" +#include "libANGLE/Context.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" namespace gl { @@ -36,7 +35,7 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mMaxDrawBuffers = caps.maxDrawBuffers; mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; - setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f); mDepthClearValue = 1.0f; mStencilClearValue = 0; @@ -76,11 +75,11 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mDepthStencil.depthMask = true; mDepthStencil.stencilTest = false; mDepthStencil.stencilFunc = GL_ALWAYS; - mDepthStencil.stencilMask = -1; - mDepthStencil.stencilWritemask = -1; + mDepthStencil.stencilMask = static_cast<GLuint>(-1); + mDepthStencil.stencilWritemask = static_cast<GLuint>(-1); mDepthStencil.stencilBackFunc = GL_ALWAYS; - mDepthStencil.stencilBackMask = -1; - mDepthStencil.stencilBackWritemask = -1; + mDepthStencil.stencilBackMask = static_cast<GLuint>(-1); + mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-1); mDepthStencil.stencilFail = GL_KEEP; mDepthStencil.stencilPassDepthFail = GL_KEEP; mDepthStencil.stencilPassDepthPass = GL_KEEP; @@ -138,11 +137,12 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); - mCurrentProgramId = 0; - mCurrentProgramBinary.set(NULL); + mProgram = NULL; mReadFramebuffer = NULL; mDrawFramebuffer = NULL; + + mPrimitiveRestart = false; } void State::reset() @@ -163,6 +163,12 @@ void State::reset() mArrayBuffer.set(NULL); mRenderbuffer.set(NULL); + if (mProgram) + { + mProgram->release(); + } + mProgram = NULL; + mTransformFeedback.set(NULL); for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) @@ -187,6 +193,8 @@ void State::reset() mPack.pixelBuffer.set(NULL); mUnpack.pixelBuffer.set(NULL); + + mProgram = NULL; } const RasterizerState &State::getRasterizerState() const @@ -204,7 +212,7 @@ const DepthStencilState &State::getDepthStencilState() const return mDepthStencil; } -void State::setClearColor(float red, float green, float blue, float alpha) +void State::setColorClearValue(float red, float green, float blue, float alpha) { mColorClearValue.red = red; mColorClearValue.green = green; @@ -212,72 +220,16 @@ void State::setClearColor(float red, float green, float blue, float alpha) mColorClearValue.alpha = alpha; } -void State::setClearDepth(float depth) +void State::setDepthClearValue(float depth) { mDepthClearValue = depth; } -void State::setClearStencil(int stencil) +void State::setStencilClearValue(int stencil) { mStencilClearValue = stencil; } -ClearParameters State::getClearParameters(GLbitfield mask) const -{ - ClearParameters clearParams = { 0 }; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mColorClearValue; - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = mBlend.colorMaskRed; - clearParams.colorMaskGreen = mBlend.colorMaskGreen; - clearParams.colorMaskBlue = mBlend.colorMaskBlue; - clearParams.colorMaskAlpha = mBlend.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = mDepthClearValue; - clearParams.clearStencil = false; - clearParams.stencilClearValue = mStencilClearValue; - clearParams.stencilWriteMask = mDepthStencil.stencilWritemask; - clearParams.scissorEnabled = mScissorTest; - clearParams.scissor = mScissor; - - const Framebuffer *framebufferObject = getDrawFramebuffer(); - if (mask & GL_COLOR_BUFFER_BIT) - { - if (framebufferObject->hasEnabledColorAttachment()) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = true; - } - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) - { - if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL) - { - clearParams.clearDepth = true; - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) - { - if (framebufferObject->getStencilbuffer() != NULL) - { - GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat(); - if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0) - { - clearParams.clearStencil = true; - } - } - } - - return clearParams; -} - void State::setColorMask(bool red, bool green, bool blue, bool alpha) { mBlend.colorMaskRed = red; @@ -527,6 +479,16 @@ void State::setDither(bool enabled) mBlend.dither = enabled; } +bool State::isPrimitiveRestartEnabled() const +{ + return mPrimitiveRestart; +} + +void State::setPrimitiveRestart(bool enabled) +{ + mPrimitiveRestart = enabled; +} + void State::setEnableFeature(GLenum feature, bool enabled) { switch (feature) @@ -540,7 +502,7 @@ void State::setEnableFeature(GLenum feature, bool enabled) case GL_DEPTH_TEST: setDepthTest(enabled); break; case GL_BLEND: setBlend(enabled); break; case GL_DITHER: setDither(enabled); break; - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break; case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; default: UNREACHABLE(); } @@ -559,7 +521,7 @@ bool State::getEnableFeature(GLenum feature) case GL_DEPTH_TEST: return isDepthTestEnabled(); case GL_BLEND: return isBlendEnabled(); case GL_DITHER: return isDitherEnabled(); - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled(); case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); default: UNREACHABLE(); return false; } @@ -613,12 +575,16 @@ void State::setSamplerTexture(GLenum type, Texture *texture) Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const { - return mSamplerTextures.at(type)[sampler].get(); + const auto it = mSamplerTextures.find(type); + ASSERT(it != mSamplerTextures.end()); + return it->second[sampler].get(); } GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const { - return mSamplerTextures.at(type)[sampler].id(); + const auto it = mSamplerTextures.find(type); + ASSERT(it != mSamplerTextures.end()); + return it->second[sampler].id(); } void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) @@ -641,8 +607,10 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) BindingPointer<Texture> &binding = textureVector[textureIdx]; if (binding.id() == texture) { + auto it = zeroTextures.find(textureType); + ASSERT(it != zeroTextures.end()); // Zero textures are the "default" textures instead of NULL - binding.set(zeroTextures.at(textureType).get()); + binding.set(it->second.get()); } } } @@ -665,13 +633,14 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) void State::initializeZeroTextures(const TextureMap &zeroTextures) { - for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++) + for (auto it = zeroTextures.cbegin(); it != zeroTextures.cend(); ++it) { - TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first]; + const auto &zeroTexture = *it; + auto &samplerTextureArray = mSamplerTextures[zeroTexture.first]; for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) { - samplerTextureArray[textureUnit].set(i->second.get()); + samplerTextureArray[textureUnit].set(zeroTexture.second.get()); } } } @@ -845,31 +814,27 @@ bool State::removeVertexArrayBinding(GLuint vertexArray) return false; } -void State::setCurrentProgram(GLuint programId, Program *newProgram) +void State::setProgram(Program *newProgram) { - mCurrentProgramId = programId; // set new ID before trying to delete program binary; otherwise it will only be flagged for deletion - mCurrentProgramBinary.set(NULL); - - if (newProgram) + if (mProgram != newProgram) { - newProgram->addRef(); - mCurrentProgramBinary.set(newProgram->getProgramBinary()); - } -} + if (mProgram) + { + mProgram->release(); + } -void State::setCurrentProgramBinary(ProgramBinary *binary) -{ - mCurrentProgramBinary.set(binary); -} + mProgram = newProgram; -GLuint State::getCurrentProgramId() const -{ - return mCurrentProgramId; + if (mProgram) + { + newProgram->addRef(); + } + } } -ProgramBinary *State::getCurrentProgramBinary() const +Program *State::getProgram() const { - return mCurrentProgramBinary.get(); + return mProgram; } void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback) @@ -882,6 +847,12 @@ TransformFeedback *State::getCurrentTransformFeedback() const return mTransformFeedback.get(); } +bool State::isTransformFeedbackActiveUnpaused() const +{ + gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); + return curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused(); +} + void State::detachTransformFeedback(GLuint transformFeedback) { if (mTransformFeedback.id() == transformFeedback) @@ -917,10 +888,12 @@ GLuint State::getActiveQueryId(GLenum target) const Query *State::getActiveQuery(GLenum target) const { + const auto it = mActiveQueries.find(target); + // All query types should already exist in the activeQueries map - ASSERT(mActiveQueries.find(target) != mActiveQueries.end()); + ASSERT(it != mActiveQueries.end()); - return mActiveQueries.at(target).get(); + return it->second.get(); } void State::setArrayBufferBinding(Buffer *buffer) @@ -968,6 +941,20 @@ Buffer *State::getIndexedUniformBuffer(GLuint index) const return mUniformBuffers[index].get(); } +GLintptr State::getIndexedUniformBufferOffset(GLuint index) const +{ + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); + + return mUniformBuffers[index].getOffset(); +} + +GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const +{ + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); + + return mUniformBuffers[index].getSize(); +} + void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer) { mGenericTransformFeedbackBuffer.set(buffer); @@ -1069,11 +1056,6 @@ void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GL getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); } -const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const -{ - return getVertexArray()->getVertexAttribute(attribNum); -} - const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const { ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size()); @@ -1110,6 +1092,11 @@ const PixelPackState &State::getPackState() const return mPack; } +PixelPackState &State::getPackState() +{ + return mPack; +} + void State::setUnpackAlignment(GLint alignment) { mUnpack.alignment = alignment; @@ -1120,11 +1107,26 @@ GLint State::getUnpackAlignment() const return mUnpack.alignment; } +void State::setUnpackRowLength(GLint rowLength) +{ + mUnpack.rowLength = rowLength; +} + +GLint State::getUnpackRowLength() const +{ + return mUnpack.rowLength; +} + const PixelUnpackState &State::getUnpackState() const { return mUnpack; } +PixelUnpackState &State::getUnpackState() +{ + return mUnpack; +} + void State::getBooleanv(GLenum pname, GLboolean *params) { switch (pname) @@ -1214,10 +1216,11 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; case GL_RENDERBUFFER_BINDING: *params = mRenderbuffer.id(); break; case GL_VERTEX_ARRAY_BINDING: *params = mVertexArray->id(); break; - case GL_CURRENT_PROGRAM: *params = mCurrentProgramId; break; + case GL_CURRENT_PROGRAM: *params = mProgram ? mProgram->id() : 0; break; case GL_PACK_ALIGNMENT: *params = mPack.alignment; break; case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break; case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break; + case GL_UNPACK_ROW_LENGTH: *params = mUnpack.rowLength; break; case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break; case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break; @@ -1243,11 +1246,13 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break; case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break; case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break; case GL_SAMPLE_BUFFERS: case GL_SAMPLES: { gl::Framebuffer *framebuffer = mDrawFramebuffer; - if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE) { switch (pname) { @@ -1342,19 +1347,19 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_TEXTURE_BINDING_2D: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id(); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D) ; break; case GL_TEXTURE_BINDING_CUBE_MAP: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id(); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_CUBE_MAP); break; case GL_TEXTURE_BINDING_3D: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id(); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_3D); break; case GL_TEXTURE_BINDING_2D_ARRAY: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id(); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D_ARRAY); break; case GL_UNIFORM_BUFFER_BINDING: *params = mGenericUniformBuffer.id(); @@ -1442,9 +1447,10 @@ bool State::hasMappedBuffer(GLenum target) const { if (target == GL_ARRAY_BUFFER) { + const VertexArray *vao = getVertexArray(); for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++) { - const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast<unsigned int>(attribIndex)); + const gl::VertexAttribute &vertexAttrib = vao->getVertexAttribute(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/libANGLE/State.h index c3e6106bd8..4370a2f16f 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.h +++ b/src/3rdparty/angle/src/libANGLE/State.h @@ -6,18 +6,18 @@ // State.h: Defines the State class, encapsulating raw GL state -#ifndef LIBGLESV2_STATE_H_ -#define LIBGLESV2_STATE_H_ +#ifndef LIBANGLE_STATE_H_ +#define LIBANGLE_STATE_H_ #include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/Sampler.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Texture.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/Program.h" +#include "libANGLE/Sampler.h" namespace gl { @@ -29,7 +29,7 @@ struct Data; typedef std::map< GLenum, BindingPointer<Texture> > TextureMap; -class State +class State : angle::NonCopyable { public: State(); @@ -44,10 +44,13 @@ class State const DepthStencilState &getDepthStencilState() const; // Clear behavior setters & state parameter block generation function - void setClearColor(float red, float green, float blue, float alpha); - void setClearDepth(float depth); - void setClearStencil(int stencil); - ClearParameters getClearParameters(GLbitfield mask) const; + void setColorClearValue(float red, float green, float blue, float alpha); + void setDepthClearValue(float depth); + void setStencilClearValue(int stencil); + + const ColorF &getColorClearValue() const { return mColorClearValue; } + float getDepthClearValue() const { return mDepthClearValue; } + int getStencilClearValue() const { return mStencilClearValue; } // Write mask manipulation void setColorMask(bool red, bool green, bool blue, bool alpha); @@ -57,6 +60,10 @@ class State bool isRasterizerDiscardEnabled() const; void setRasterizerDiscard(bool enabled); + // Primitive restart + bool isPrimitiveRestartEnabled() const; + void setPrimitiveRestart(bool enabled); + // Face culling state manipulation bool isCullFaceEnabled() const; void setCullFace(bool enabled); @@ -167,14 +174,13 @@ class State bool removeVertexArrayBinding(GLuint vertexArray); // Program binding manipulation - void setCurrentProgram(GLuint programId, Program *newProgram); - void setCurrentProgramBinary(ProgramBinary *binary); - GLuint getCurrentProgramId() const; - ProgramBinary *getCurrentProgramBinary() const; + void setProgram(Program *newProgram); + Program *getProgram() const; // Transform feedback object (not buffer) binding manipulation void setTransformFeedbackBinding(TransformFeedback *transformFeedback); TransformFeedback *getCurrentTransformFeedback() const; + bool isTransformFeedbackActiveUnpaused() const; void detachTransformFeedback(GLuint transformFeedback); // Query binding manipulation @@ -194,6 +200,8 @@ class State void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); GLuint getIndexedUniformBufferId(GLuint index) const; Buffer *getIndexedUniformBuffer(GLuint index) const; + GLintptr getIndexedUniformBufferOffset(GLuint index) const; + GLsizeiptr getIndexedUniformBufferSize(GLuint index) const; // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets void setGenericTransformFeedbackBufferBinding(Buffer *buffer); @@ -221,7 +229,6 @@ class State void setVertexAttribi(GLuint index, const GLint values[4]); void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; const void *getVertexAttribPointer(unsigned int attribNum) const; @@ -231,11 +238,15 @@ class State void setPackReverseRowOrder(bool reverseRowOrder); bool getPackReverseRowOrder() const; const PixelPackState &getPackState() const; + PixelPackState &getPackState(); // Pixel unpack state manipulation void setUnpackAlignment(GLint alignment); GLint getUnpackAlignment() const; + void setUnpackRowLength(GLint rowLength); + GLint getUnpackRowLength() const; const PixelUnpackState &getUnpackState() const; + PixelUnpackState &getUnpackState(); // State query functions void getBooleanv(GLenum pname, GLboolean *params); @@ -247,8 +258,6 @@ class State bool hasMappedBuffer(GLenum target) const; private: - DISALLOW_COPY_AND_ASSIGN(State); - // Cached values from Context's caps GLuint mMaxDrawBuffers; GLuint mMaxCombinedTextureImageUnits; @@ -284,8 +293,7 @@ class State Framebuffer *mReadFramebuffer; Framebuffer *mDrawFramebuffer; BindingPointer<Renderbuffer> mRenderbuffer; - GLuint mCurrentProgramId; - BindingPointer<ProgramBinary> mCurrentProgramBinary; + Program *mProgram; typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector; VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib @@ -317,9 +325,11 @@ class State PixelUnpackState mUnpack; PixelPackState mPack; + + bool mPrimitiveRestart; }; } -#endif // LIBGLESV2_STATE_H_ +#endif // LIBANGLE_STATE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Surface.cpp b/src/3rdparty/angle/src/libANGLE/Surface.cpp new file mode 100644 index 0000000000..ac455f3905 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Surface.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2002-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. +// + +// Surface.cpp: Implements the egl::Surface class, representing a drawing surface +// such as the client area of a window, including any back buffers. +// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. + +#include "libANGLE/Surface.h" + +#include "libANGLE/Config.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/SurfaceImpl.h" + +#include <EGL/eglext.h> + +namespace egl +{ + +Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes) + : RefCountObject(0), // id unused + mImplementation(impl), + mType(surfaceType), + mConfig(config), + mPostSubBufferRequested(false), + mFixedSize(false), + mFixedWidth(0), + mFixedHeight(0), + mTextureFormat(EGL_NO_TEXTURE), + mTextureTarget(EGL_NO_TEXTURE), + // FIXME: Determine actual pixel aspect ratio + mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)), + mRenderBuffer(EGL_BACK_BUFFER), + mSwapBehavior(EGL_BUFFER_PRESERVED), + mTexture(NULL) +{ + addRef(); + + mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE); + + mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE); + if (mFixedSize) + { + mFixedWidth = attributes.get(EGL_WIDTH, 0); + mFixedHeight = attributes.get(EGL_HEIGHT, 0); + } + + if (mType != EGL_WINDOW_BIT) + { + mTextureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); + mTextureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); + } +} + +Surface::~Surface() +{ + if (mTexture) + { + if (mImplementation) + { + mImplementation->releaseTexImage(mTexture->id()); + } + mTexture->releaseTexImage(); + mTexture = NULL; + } + + SafeDelete(mImplementation); +} + +EGLint Surface::getType() const +{ + return mType; +} + +Error Surface::swap() +{ + return mImplementation->swap(); +} + +Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return mImplementation->postSubBuffer(x, y, width, height); +} + +Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + return mImplementation->querySurfacePointerANGLE(attribute, value); +} + +EGLint Surface::isPostSubBufferSupported() const +{ + return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported(); +} + +void Surface::setSwapInterval(EGLint interval) +{ + mImplementation->setSwapInterval(interval); +} + +const Config *Surface::getConfig() const +{ + return mConfig; +} + +EGLint Surface::getPixelAspectRatio() const +{ + return mPixelAspectRatio; +} + +EGLenum Surface::getRenderBuffer() const +{ + return mRenderBuffer; +} + +EGLenum Surface::getSwapBehavior() const +{ + return mSwapBehavior; +} + +EGLenum Surface::getTextureFormat() const +{ + return mTextureFormat; +} + +EGLenum Surface::getTextureTarget() const +{ + return mTextureTarget; +} + +EGLint Surface::isFixedSize() const +{ + return mFixedSize; +} + +EGLint Surface::getWidth() const +{ + return mFixedSize ? mFixedWidth : mImplementation->getWidth(); +} + +EGLint Surface::getHeight() const +{ + return mFixedSize ? mFixedHeight : mImplementation->getHeight(); +} + +Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + ASSERT(!mTexture); + + texture->bindTexImage(this); + mTexture = texture; + return mImplementation->bindTexImage(buffer); +} + +Error Surface::releaseTexImage(EGLint buffer) +{ + ASSERT(mTexture); + gl::Texture *boundTexture = mTexture; + mTexture = NULL; + + boundTexture->releaseTexImage(); + return mImplementation->releaseTexImage(buffer); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Surface.h b/src/3rdparty/angle/src/libANGLE/Surface.h new file mode 100644 index 0000000000..430bf0195d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Surface.h @@ -0,0 +1,98 @@ +// +// Copyright (c) 2002-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. +// + +// Surface.h: Defines the egl::Surface class, representing a drawing surface +// such as the client area of a window, including any back buffers. +// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. + +#ifndef LIBANGLE_SURFACE_H_ +#define LIBANGLE_SURFACE_H_ + +#include <EGL/egl.h> + +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +namespace gl +{ +class Texture; +} + +namespace rx +{ +class SurfaceImpl; +} + +namespace egl +{ +class AttributeMap; +class Display; +struct Config; + +class Surface final : public RefCountObject +{ + public: + Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes); + + rx::SurfaceImpl *getImplementation() { return mImplementation; } + const rx::SurfaceImpl *getImplementation() const { return mImplementation; } + + EGLint getType() const; + + Error swap(); + Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); + Error querySurfacePointerANGLE(EGLint attribute, void **value); + Error bindTexImage(gl::Texture *texture, EGLint buffer); + Error releaseTexImage(EGLint buffer); + + EGLint isPostSubBufferSupported() const; + + void setSwapInterval(EGLint interval); + + const Config *getConfig() const; + + // width and height can change with client window resizing + EGLint getWidth() const; + EGLint getHeight() const; + EGLint getPixelAspectRatio() const; + EGLenum getRenderBuffer() const; + EGLenum getSwapBehavior() const; + EGLenum getTextureFormat() const; + EGLenum getTextureTarget() const; + + gl::Texture *getBoundTexture() const { return mTexture; } + + EGLint isFixedSize() const; + + private: + virtual ~Surface(); + + rx::SurfaceImpl *mImplementation; + + EGLint mType; + + const egl::Config *mConfig; + + bool mPostSubBufferRequested; + + bool mFixedSize; + size_t mFixedWidth; + size_t mFixedHeight; + + EGLenum mTextureFormat; + EGLenum mTextureTarget; + + EGLint mPixelAspectRatio; // Display aspect ratio + EGLenum mRenderBuffer; // Render buffer + EGLenum mSwapBehavior; // Buffer swap behavior + + gl::Texture *mTexture; +}; + +} + +#endif // LIBANGLE_SURFACE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp new file mode 100644 index 0000000000..cd4584f694 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp @@ -0,0 +1,573 @@ +// +// Copyright (c) 2002-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. +// + +// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63. + +#include "libANGLE/Texture.h" +#include "libANGLE/Data.h" +#include "libANGLE/formatutils.h" + +#include "libANGLE/Config.h" +#include "libANGLE/Surface.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +bool IsMipmapFiltered(const gl::SamplerState &samplerState) +{ + switch (samplerState.minFilter) + { + case GL_NEAREST: + case GL_LINEAR: + return false; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: UNREACHABLE(); + return false; + } +} + +bool IsPointSampled(const gl::SamplerState &samplerState) +{ + return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST)); +} + +static size_t GetImageDescIndex(GLenum target, size_t level) +{ + return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level; +} + +unsigned int Texture::mCurrentTextureSerial = 1; + +Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) + : RefCountObject(id), + mTexture(impl), + mTextureSerial(issueTextureSerial()), + mUsage(GL_NONE), + mImmutableLevelCount(0), + mTarget(target), + mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)), + mCompletenessCache(), + mBoundSurface(NULL) +{ +} + +Texture::~Texture() +{ + if (mBoundSurface) + { + mBoundSurface->releaseTexImage(EGL_BACK_BUFFER); + mBoundSurface = NULL; + } + SafeDelete(mTexture); +} + +GLenum Texture::getTarget() const +{ + return mTarget; +} + +void Texture::setUsage(GLenum usage) +{ + mUsage = usage; + getImplementation()->setUsage(usage); +} + +GLenum Texture::getUsage() const +{ + return mUsage; +} + +size_t Texture::getWidth(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).size.width; +} + +size_t Texture::getHeight(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).size.height; +} + +size_t Texture::getDepth(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).size.depth; +} + +GLenum Texture::getInternalFormat(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).internalFormat; +} + +bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const +{ + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat); + if (!mCompletenessCache.cacheValid || + mCompletenessCache.samplerState != samplerState || + mCompletenessCache.filterable != textureCaps.filterable || + mCompletenessCache.clientVersion != data.clientVersion || + mCompletenessCache.supportsNPOT != data.extensions->textureNPOT) + { + mCompletenessCache.cacheValid = true; + mCompletenessCache.samplerState = samplerState; + mCompletenessCache.filterable = textureCaps.filterable; + mCompletenessCache.clientVersion = data.clientVersion; + mCompletenessCache.supportsNPOT = data.extensions->textureNPOT; + mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data); + } + return mCompletenessCache.samplerComplete; +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool Texture::isCubeComplete() const +{ + ASSERT(mTarget == GL_TEXTURE_CUBE_MAP); + + const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0); + if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height) + { + return false; + } + + for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++) + { + const ImageDesc &faceImageDesc = getImageDesc(face, 0); + if (faceImageDesc.size.width != baseImageDesc.size.width || + faceImageDesc.size.height != baseImageDesc.size.height || + faceImageDesc.internalFormat != baseImageDesc.internalFormat) + { + return false; + } + } + + return true; +} + +unsigned int Texture::getTextureSerial() const +{ + return mTextureSerial; +} + +unsigned int Texture::issueTextureSerial() +{ + return mCurrentTextureSerial++; +} + +bool Texture::isImmutable() const +{ + return (mImmutableLevelCount > 0); +} + +int Texture::immutableLevelCount() +{ + return mImmutableLevelCount; +} + +Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type))); + + return Error(GL_NO_ERROR); +} + +Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + return mTexture->setSubImage(target, level, area, format, type, unpack, pixels); +} + +Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); + + return Error(GL_NO_ERROR); +} + +Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels); +} + +Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat, + const Framebuffer *source) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1), + GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); + + return Error(GL_NO_ERROR); +} + +Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea, + const Framebuffer *source) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + return mTexture->copySubImage(target, level, destOffset, sourceArea, source); +} + +Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size) +{ + ASSERT(target == mTarget); + + Error error = mTexture->setStorage(target, levels, internalFormat, size); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + mImmutableLevelCount = levels; + clearImageDescs(); + setImageDescChain(levels, size, internalFormat); + + return Error(GL_NO_ERROR); +} + + +Error Texture::generateMipmaps() +{ + Error error = mTexture->generateMipmaps(); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0); + size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1; + setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat); + + return Error(GL_NO_ERROR); +} + +void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat) +{ + for (size_t level = 0; level < levels; level++) + { + Extents levelSize(std::max<size_t>(baseSize.width >> level, 1), + std::max<size_t>(baseSize.height >> level, 1), + (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1)); + ImageDesc levelInfo(levelSize, sizedInternalFormat); + + if (mTarget == GL_TEXTURE_CUBE_MAP) + { + for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) + { + setImageDesc(face, level, levelInfo); + } + } + else + { + setImageDesc(mTarget, level, levelInfo); + } + } +} + +Texture::ImageDesc::ImageDesc() + : size(0, 0, 0), internalFormat(GL_NONE) +{ +} + +Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat) + : size(size), + internalFormat(internalFormat) +{ +} + +const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const +{ + size_t descIndex = GetImageDescIndex(target, level); + ASSERT(descIndex < mImageDescs.size()); + return mImageDescs[descIndex]; +} + +void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc) +{ + size_t descIndex = GetImageDescIndex(target, level); + ASSERT(descIndex < mImageDescs.size()); + mImageDescs[descIndex] = desc; + mCompletenessCache.cacheValid = false; +} + +void Texture::clearImageDesc(GLenum target, size_t level) +{ + setImageDesc(target, level, ImageDesc()); +} + +void Texture::clearImageDescs() +{ + for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++) + { + mImageDescs[descIndex] = ImageDesc(); + } + mCompletenessCache.cacheValid = false; +} + +void Texture::bindTexImage(egl::Surface *surface) +{ + ASSERT(surface); + + releaseTexImage(); + mTexture->bindTexImage(surface); + mBoundSurface = surface; + + // Set the image info to the size and format of the surface + ASSERT(mTarget == GL_TEXTURE_2D); + Extents size(surface->getWidth(), surface->getHeight(), 1); + ImageDesc desc(size, surface->getConfig()->renderTargetFormat); + setImageDesc(mTarget, 0, desc); +} + +void Texture::releaseTexImage() +{ + if (mBoundSurface) + { + mBoundSurface = NULL; + mTexture->releaseTexImage(); + + // Erase the image info for level 0 + ASSERT(mTarget == GL_TEXTURE_2D); + clearImageDesc(mTarget, 0); + } +} + +GLenum Texture::getBaseImageTarget() const +{ + return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget; +} + +size_t Texture::getExpectedMipLevels() const +{ + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0); + if (mTarget == GL_TEXTURE_3D) + { + return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1; + } + else + { + return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1; + } +} + +bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const +{ + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) + { + return false; + } + + if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height) + { + return false; + } + + const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat); + if (!textureCaps.filterable && !IsPointSampled(samplerState)) + { + return false; + } + + bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3; + if (!npotSupport) + { + if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) || + (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height))) + { + return false; + } + } + + if (IsMipmapFiltered(samplerState)) + { + if (!npotSupport) + { + if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height)) + { + return false; + } + } + + if (!computeMipmapCompleteness(samplerState)) + { + return false; + } + } + else + { + if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete()) + { + return false; + } + } + + // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if: + // The internalformat specified for the texture arrays is a sized internal depth or + // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_- + // MODE is NONE, and either the magnification filter is not NEAREST or the mini- + // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat); + if (formatInfo.depthBits > 0 && data.clientVersion > 2) + { + if (samplerState.compareMode == GL_NONE) + { + if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || + samplerState.magFilter != GL_NEAREST) + { + return false; + } + } + } + + return true; +} + +bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) const +{ + size_t expectedMipLevels = getExpectedMipLevels(); + + size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1); + + for (size_t level = samplerState.baseLevel; level < maxLevel; level++) + { + if (mTarget == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) + { + if (!computeLevelCompleteness(face, level, samplerState)) + { + return false; + } + } + } + else + { + if (!computeLevelCompleteness(mTarget, level, samplerState)) + { + return false; + } + } + } + + return true; +} + + +bool Texture::computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const +{ + ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (isImmutable()) + { + return true; + } + + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == 0) + { + return true; + } + + const ImageDesc &levelImageDesc = getImageDesc(target, level); + if (levelImageDesc.internalFormat != baseImageDesc.internalFormat) + { + return false; + } + + if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> level)) + { + return false; + } + + if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> level)) + { + return false; + } + + if (mTarget == GL_TEXTURE_3D) + { + if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> level)) + { + return false; + } + } + else if (mTarget == GL_TEXTURE_2D_ARRAY) + { + if (levelImageDesc.size.depth != baseImageDesc.size.depth) + { + return false; + } + } + + return true; +} + +Texture::SamplerCompletenessCache::SamplerCompletenessCache() + : cacheValid(false), + samplerState(), + filterable(false), + clientVersion(0), + supportsNPOT(false), + samplerComplete(false) +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Texture.h b/src/3rdparty/angle/src/libANGLE/Texture.h new file mode 100644 index 0000000000..b5a0717713 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Texture.h @@ -0,0 +1,156 @@ +// +// Copyright (c) 2002-2013 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. +// + +// Texture.h: Defines the gl::Texture class [OpenGL ES 2.0.24] section 3.7 page 63. + +#ifndef LIBANGLE_TEXTURE_H_ +#define LIBANGLE_TEXTURE_H_ + +#include "common/debug.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/Caps.h" + +#include "angle_gl.h" + +#include <vector> +#include <map> + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class Framebuffer; +struct Data; + +bool IsMipmapFiltered(const gl::SamplerState &samplerState); + +class Texture final : public RefCountObject +{ + public: + Texture(rx::TextureImpl *impl, GLuint id, GLenum target); + + virtual ~Texture(); + + GLenum getTarget() const; + + const SamplerState &getSamplerState() const { return mSamplerState; } + SamplerState &getSamplerState() { return mSamplerState; } + + void setUsage(GLenum usage); + GLenum getUsage() const; + + size_t getWidth(GLenum target, size_t level) const; + size_t getHeight(GLenum target, size_t level) const; + size_t getDepth(GLenum target, size_t level) const; + GLenum getInternalFormat(GLenum target, size_t level) const; + + bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const; + bool isCubeComplete() const; + + virtual Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels); + virtual Error setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels); + + virtual Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, + const PixelUnpackState &unpack, const uint8_t *pixels); + virtual Error setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format, + const PixelUnpackState &unpack, const uint8_t *pixels); + + virtual Error copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat, + const Framebuffer *source); + virtual Error copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea, + const Framebuffer *source); + + virtual Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size); + + virtual Error generateMipmaps(); + + // 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; + GLsizei immutableLevelCount(); + + void bindTexImage(egl::Surface *surface); + void releaseTexImage(); + + rx::TextureImpl *getImplementation() { return mTexture; } + const rx::TextureImpl *getImplementation() const { return mTexture; } + + static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. + + private: + static unsigned int issueTextureSerial(); + + rx::TextureImpl *mTexture; + + SamplerState mSamplerState; + GLenum mUsage; + + GLsizei mImmutableLevelCount; + + GLenum mTarget; + + + struct ImageDesc + { + Extents size; + GLenum internalFormat; + + ImageDesc(); + ImageDesc(const Extents &size, GLenum internalFormat); + }; + + const unsigned int mTextureSerial; + static unsigned int mCurrentTextureSerial; + + GLenum getBaseImageTarget() const; + size_t getExpectedMipLevels() const; + + bool computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const; + bool computeMipmapCompleteness(const gl::SamplerState &samplerState) const; + bool computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const; + + const ImageDesc &getImageDesc(GLenum target, size_t level) const; + void setImageDesc(GLenum target, size_t level, const ImageDesc &desc); + void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat); + void clearImageDesc(GLenum target, size_t level); + void clearImageDescs(); + + std::vector<ImageDesc> mImageDescs; + + struct SamplerCompletenessCache + { + SamplerCompletenessCache(); + + bool cacheValid; + + // All values that affect sampler completeness that are not stored within + // the texture itself + SamplerState samplerState; + bool filterable; + GLint clientVersion; + bool supportsNPOT; + + // Result of the sampler completeness with the above parameters + bool samplerComplete; + }; + mutable SamplerCompletenessCache mCompletenessCache; + + egl::Surface *mBoundSurface; +}; + +} + +#endif // LIBANGLE_TEXTURE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp index bfa7072326..6effaca976 100644 --- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp +++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/renderer/TransformFeedbackImpl.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/renderer/TransformFeedbackImpl.h" namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h index 885a4fe172..7673db93ff 100644 --- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h +++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h @@ -4,11 +4,12 @@ // found in the LICENSE file. // -#ifndef LIBGLESV2_TRANSFORM_FEEDBACK_H_ -#define LIBGLESV2_TRANSFORM_FEEDBACK_H_ +#ifndef LIBANGLE_TRANSFORM_FEEDBACK_H_ +#define LIBANGLE_TRANSFORM_FEEDBACK_H_ + +#include "libANGLE/RefCountObject.h" #include "common/angleutils.h" -#include "common/RefCountObject.h" #include "angle_gl.h" @@ -37,8 +38,6 @@ class TransformFeedback : public RefCountObject GLboolean isPaused() const; private: - DISALLOW_COPY_AND_ASSIGN(TransformFeedback); - rx::TransformFeedbackImpl* mTransformFeedback; GLboolean mStarted; @@ -48,4 +47,4 @@ class TransformFeedback : public RefCountObject } -#endif // LIBGLESV2_TRANSFORM_FEEDBACK_H_ +#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libANGLE/Uniform.cpp index bd0cd2eeec..f161b9d6bd 100644 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp +++ b/src/3rdparty/angle/src/libANGLE/Uniform.cpp @@ -4,10 +4,12 @@ // found in the LICENSE file. // -#include "libGLESv2/Uniform.h" +#include "libANGLE/Uniform.h" #include "common/utilities.h" +#include <cstring> + namespace gl { @@ -75,7 +77,7 @@ size_t LinkedUniform::dataSize() const bool LinkedUniform::isSampler() const { - return IsSampler(type); + return IsSamplerType(type); } UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libANGLE/Uniform.h index 633d70bb19..dcf30f23cc 100644 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.h +++ b/src/3rdparty/angle/src/libANGLE/Uniform.h @@ -4,24 +4,22 @@ // found in the LICENSE file. // -#ifndef LIBGLESV2_UNIFORM_H_ -#define LIBGLESV2_UNIFORM_H_ - -#include "common/debug.h" -#include "common/blocklayout.h" - -#include "libGLESv2/angletypes.h" - -#include "angle_gl.h" +#ifndef LIBANGLE_UNIFORM_H_ +#define LIBANGLE_UNIFORM_H_ #include <string> #include <vector> +#include "angle_gl.h" +#include "common/debug.h" +#include "compiler/translator/blocklayout.h" +#include "libANGLE/angletypes.h" + namespace gl { // Helper struct representing a single shader uniform -struct LinkedUniform +struct LinkedUniform : angle::NonCopyable { LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo); @@ -55,7 +53,7 @@ struct LinkedUniform }; // Helper struct representing a single shader uniform block -struct UniformBlock +struct UniformBlock : angle::NonCopyable { // use GL_INVALID_INDEX for non-array elements UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize); @@ -76,4 +74,4 @@ struct UniformBlock } -#endif // LIBGLESV2_UNIFORM_H_ +#endif // LIBANGLE_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp index f8ca661062..f0aded905d 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp +++ b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp @@ -6,9 +6,9 @@ // Implementation of the state class for mananging GLES 3 Vertex Array Objects. // -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/renderer/VertexArrayImpl.h" namespace gl { @@ -59,6 +59,11 @@ const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) co return mVertexAttributes[attributeIndex]; } +const std::vector<VertexAttribute> &VertexArray::getVertexAttributes() const +{ + return mVertexAttributes; +} + void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor) { ASSERT(index < getMaxAttribs()); @@ -93,4 +98,4 @@ void VertexArray::setElementArrayBuffer(Buffer *buffer) mVertexArray->setElementArrayBuffer(buffer); } -}
\ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libANGLE/VertexArray.h index a724c0be1c..5c79b9953d 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h +++ b/src/3rdparty/angle/src/libANGLE/VertexArray.h @@ -10,12 +10,12 @@ // by the vertex processor is encapsulated in a vertex array object. // -#ifndef LIBGLESV2_VERTEXARRAY_H_ -#define LIBGLESV2_VERTEXARRAY_H_ +#ifndef LIBANGLE_VERTEXARRAY_H_ +#define LIBANGLE_VERTEXARRAY_H_ -#include "common/RefCountObject.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/Constants.h" +#include "libANGLE/VertexAttribute.h" #include <vector> @@ -37,18 +37,22 @@ class VertexArray GLuint id() const; const VertexAttribute& getVertexAttribute(size_t attributeIndex) const; + const std::vector<VertexAttribute> &getVertexAttributes() const; + void detachBuffer(GLuint bufferName); void setVertexAttribDivisor(GLuint index, GLuint divisor); void enableAttribute(unsigned int attributeIndex, bool enabledState); 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[0]; } Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } void setElementArrayBuffer(Buffer *buffer); GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } size_t getMaxAttribs() const { return mVertexAttributes.size(); } + rx::VertexArrayImpl *getImplementation() { return mVertexArray; } + const rx::VertexArrayImpl *getImplementation() const { return mVertexArray; } + private: GLuint mId; @@ -59,4 +63,4 @@ class VertexArray } -#endif // LIBGLESV2_VERTEXARRAY_H_ +#endif // LIBANGLE_VERTEXARRAY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp index 1096856b8a..19934e7fac 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp @@ -6,7 +6,7 @@ // Implementation of the state class for mananging GLES 3 Vertex Array Objects. // -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/VertexAttribute.h" namespace gl { @@ -23,6 +23,24 @@ VertexAttribute::VertexAttribute() { } +bool operator==(const VertexAttribute &a, const VertexAttribute &b) +{ + return a.enabled == b.enabled && + a.type == b.type && + a.size == b.size && + a.normalized == b.normalized && + a.pureInteger == b.pureInteger && + a.stride == b.stride && + a.pointer == b.pointer && + a.buffer.get() == b.buffer.get() && + a.divisor == b.divisor; +} + +bool operator!=(const VertexAttribute &a, const VertexAttribute &b) +{ + return !(a == b); +} + size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib) { GLuint size = attrib.size; @@ -52,4 +70,4 @@ size_t ComputeVertexAttributeStride(const VertexAttribute& attrib) return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib); } -}
\ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h index e9757b618b..bdffe97466 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h @@ -6,10 +6,10 @@ // Helper structure describing a single vertex attribute // -#ifndef LIBGLESV2_VERTEXATTRIBUTE_H_ -#define LIBGLESV2_VERTEXATTRIBUTE_H_ +#ifndef LIBANGLE_VERTEXATTRIBUTE_H_ +#define LIBANGLE_VERTEXATTRIBUTE_H_ -#include "libGLESv2/Buffer.h" +#include "libANGLE/Buffer.h" namespace gl { @@ -36,6 +36,9 @@ struct VertexAttribute VertexAttribute(); }; +bool operator==(const VertexAttribute &a, const VertexAttribute &b); +bool operator!=(const VertexAttribute &a, const VertexAttribute &b); + template <typename T> T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) { @@ -116,4 +119,4 @@ struct VertexAttribCurrentValueData } -#endif // LIBGLESV2_VERTEXATTRIBUTE_H_ +#endif // LIBANGLE_VERTEXATTRIBUTE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libANGLE/angletypes.cpp index 5a0cfc5ad9..16879f8041 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp +++ b/src/3rdparty/angle/src/libANGLE/angletypes.cpp @@ -6,17 +6,28 @@ // angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 -#include "libGLESv2/angletypes.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/State.h" -#include "libGLESv2/VertexArray.h" - -#include <float.h> +#include "libANGLE/angletypes.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" namespace gl { +bool operator==(const Rectangle &a, const Rectangle &b) +{ + return a.x == b.x && + a.y == b.y && + a.width == b.width && + a.height == b.height; +} + +bool operator!=(const Rectangle &a, const Rectangle &b) +{ + return !(a == b); +} + SamplerState::SamplerState() : minFilter(GL_NEAREST_MIPMAP_LINEAR), magFilter(GL_LINEAR), @@ -26,8 +37,8 @@ SamplerState::SamplerState() maxAnisotropy(1.0f), baseLevel(0), maxLevel(1000), - minLod(-FLT_MAX), - maxLod(FLT_MAX), + minLod(-1000.0f), + maxLod(1000.0f), compareMode(GL_NONE), compareFunc(GL_LEQUAL), swizzleRed(GL_RED), @@ -42,6 +53,31 @@ bool SamplerState::swizzleRequired() const swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; } +bool SamplerState::operator==(const SamplerState &other) const +{ + return minFilter == other.minFilter && + magFilter == other.magFilter && + wrapS == other.wrapS && + wrapT == other.wrapT && + wrapR == other.wrapR && + maxAnisotropy == other.maxAnisotropy && + baseLevel == other.baseLevel && + maxLevel == other.maxLevel && + minLod == other.minLod && + maxLod == other.maxLod && + compareMode == other.compareMode && + compareFunc == other.compareFunc && + swizzleRed == other.swizzleRed && + swizzleGreen == other.swizzleGreen && + swizzleBlue == other.swizzleBlue && + swizzleAlpha == other.swizzleAlpha; +} + +bool SamplerState::operator!=(const SamplerState &other) const +{ + return !(*this == other); +} + static void MinMax(int a, int b, int *minimum, int *maximum) { if (a < b) @@ -151,13 +187,13 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp } void VertexFormat::GetInputLayout(VertexFormat *inputLayout, - ProgramBinary *programBinary, + Program *program, const State &state) { - const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes(); - for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + const std::vector<VertexAttribute> &vertexAttributes = state.getVertexArray()->getVertexAttributes(); + for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++) { - int semanticIndex = programBinary->getSemanticIndex(attributeIndex); + int semanticIndex = program->getSemanticIndex(attributeIndex); if (semanticIndex != -1) { diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h index 78fe6b0e26..e4e08b5512 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ b/src/3rdparty/angle/src/libANGLE/angletypes.h @@ -6,17 +6,20 @@ // angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 -#ifndef LIBGLESV2_ANGLETYPES_H_ -#define LIBGLESV2_ANGLETYPES_H_ +#ifndef LIBANGLE_ANGLETYPES_H_ +#define LIBANGLE_ANGLETYPES_H_ -#include "libGLESv2/Constants.h" -#include "common/RefCountObject.h" +#include "libANGLE/Constants.h" +#include "libANGLE/RefCountObject.h" + +#include <stdint.h> +#include <float.h> namespace gl { class Buffer; class State; -class ProgramBinary; +class Program; struct VertexAttribute; struct VertexAttribCurrentValueData; @@ -38,6 +41,21 @@ struct Color Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { } }; +template <typename T> +bool operator==(const Color<T> &a, const Color<T> &b) +{ + return a.red == b.red && + a.green == b.green && + a.blue == b.blue && + a.alpha == b.alpha; +} + +template <typename T> +bool operator!=(const Color<T> &a, const Color<T> &b) +{ + return !(a == b); +} + typedef Color<float> ColorF; typedef Color<int> ColorI; typedef Color<unsigned int> ColorUI; @@ -53,21 +71,19 @@ struct Rectangle Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { } }; +bool operator==(const Rectangle &a, const Rectangle &b); +bool operator!=(const Rectangle &a, const Rectangle &b); + bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); -struct Box +struct Offset { int x; int y; int z; - int width; - int height; - int depth; - 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; + Offset() : x(0), y(0), z(0) { } + Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) { } }; struct Extents @@ -78,8 +94,27 @@ struct Extents Extents() : width(0), height(0), depth(0) { } Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { } + + bool empty() const { return (width * height * depth) == 0; } +}; + +struct Box +{ + int x; + int y; + int z; + int width; + int height; + int depth; + + 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) { } + Box(const Offset &offset, const Extents &size) : x(offset.x), y(offset.y), z(offset.z), width(size.width), height(size.height), depth(size.depth) { } + bool operator==(const Box &other) const; + bool operator!=(const Box &other) const; }; + struct RasterizerState { bool cullFace; @@ -162,42 +197,37 @@ struct SamplerState GLenum swizzleAlpha; bool swizzleRequired() const; -}; - -struct ClearParameters -{ - bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - ColorF colorFClearValue; - ColorI colorIClearValue; - ColorUI colorUIClearValue; - GLenum colorClearType; - bool colorMaskRed; - bool colorMaskGreen; - bool colorMaskBlue; - bool colorMaskAlpha; - - bool clearDepth; - float depthClearValue; - - bool clearStencil; - GLint stencilClearValue; - GLuint stencilWriteMask; - bool scissorEnabled; - Rectangle scissor; + bool operator==(const SamplerState &other) const; + bool operator!=(const SamplerState &other) const; }; struct PixelUnpackState { BindingPointer<Buffer> pixelBuffer; GLint alignment; + GLint rowLength; + GLint skipRows; + GLint skipPixels; + GLint imageHeight; + GLint skipImages; PixelUnpackState() - : alignment(4) + : alignment(4), + rowLength(0), + skipRows(0), + skipPixels(0), + imageHeight(0), + skipImages(0) {} - explicit PixelUnpackState(GLint alignmentIn) - : alignment(alignmentIn) + PixelUnpackState(GLint alignmentIn, GLint rowLengthIn) + : alignment(alignmentIn), + rowLength(rowLengthIn), + skipRows(0), + skipPixels(0), + imageHeight(0), + skipImages(0) {} }; @@ -206,15 +236,24 @@ struct PixelPackState BindingPointer<Buffer> pixelBuffer; GLint alignment; bool reverseRowOrder; + GLint rowLength; + GLint skipRows; + GLint skipPixels; PixelPackState() : alignment(4), - reverseRowOrder(false) + reverseRowOrder(false), + rowLength(0), + skipRows(0), + skipPixels(0) {} explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn) : alignment(alignmentIn), - reverseRowOrder(reverseRowOrderIn) + reverseRowOrder(reverseRowOrderIn), + rowLength(0), + skipRows(0), + skipPixels(0) {} }; @@ -231,7 +270,7 @@ struct VertexFormat VertexFormat(const VertexAttribute &attribute, GLenum currentValueType); static void GetInputLayout(VertexFormat *inputLayout, - ProgramBinary *programBinary, + Program *program, const State& currentValues); bool operator==(const VertexFormat &other) const; @@ -244,14 +283,41 @@ struct VertexFormat namespace rx { -enum VertexConversionType +enum VendorID : uint32_t { - VERTEX_CONVERT_NONE = 0, - VERTEX_CONVERT_CPU = 1, - VERTEX_CONVERT_GPU = 2, - VERTEX_CONVERT_BOTH = 3 + VENDOR_ID_AMD = 0x1002, + VENDOR_ID_INTEL = 0x8086, + VENDOR_ID_NVIDIA = 0x10DE, }; +// Downcast a base implementation object (EG TextureImpl to TextureD3D) +template <typename DestT, typename SrcT> +inline DestT *GetAs(SrcT *src) +{ + ASSERT(HAS_DYNAMIC_TYPE(DestT*, src)); + return static_cast<DestT*>(src); +} + +template <typename DestT, typename SrcT> +inline const DestT *GetAs(const SrcT *src) +{ + ASSERT(HAS_DYNAMIC_TYPE(const DestT*, src)); + return static_cast<const DestT*>(src); +} + +// Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D) +template <typename DestT, typename SrcT> +inline DestT *GetImplAs(SrcT *src) +{ + return GetAs<DestT>(src->getImplementation()); +} + +template <typename DestT, typename SrcT> +inline const DestT *GetImplAs(const SrcT *src) +{ + return GetAs<const DestT>(src->getImplementation()); +} + } -#endif // LIBGLESV2_ANGLETYPES_H_ +#endif // LIBANGLE_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/libANGLE/features.h index b49a0ee852..fbe013f47d 100644 --- a/src/3rdparty/angle/src/common/features.h +++ b/src/3rdparty/angle/src/libANGLE/features.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef LIBANGLE_FEATURES_H_ +#define LIBANGLE_FEATURES_H_ + #define ANGLE_DISABLED 0 #define ANGLE_ENABLED 1 @@ -33,3 +36,5 @@ #if !defined(ANGLE_SHADER_DEBUG_INFO) #define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED #endif + +#endif // LIBANGLE_FEATURES_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp b/src/3rdparty/angle/src/libANGLE/formatutils.cpp index 8674d5337f..51e6a5a65d 100644 --- a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp +++ b/src/3rdparty/angle/src/libANGLE/formatutils.cpp @@ -7,12 +7,10 @@ // formatutils.cpp: Queries for GL image formats. #include "common/mathutil.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/imageformats.h" -#include "libGLESv2/renderer/copyimage.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Context.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/Renderer.h" namespace gl { @@ -21,145 +19,137 @@ namespace gl // can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid // format and type combinations. -FormatType::FormatType() - : internalFormat(GL_NONE), - colorWriteFunction(NULL) -{ -} - typedef std::pair<GLenum, GLenum> FormatTypePair; -typedef std::pair<FormatTypePair, FormatType> FormatPair; -typedef std::map<FormatTypePair, FormatType> FormatMap; +typedef std::pair<FormatTypePair, GLenum> FormatPair; +typedef std::map<FormatTypePair, GLenum> FormatMap; // A helper function to insert data into the format map with fewer characters. -static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat, ColorWriteFunction writeFunc) +static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat) { - FormatType info; - info.internalFormat = internalFormat; - info.colorWriteFunction = writeFunc; - map->insert(FormatPair(FormatTypePair(format, type), info)); + map->insert(FormatPair(FormatTypePair(format, type), internalFormat)); } FormatMap BuildFormatMap() { FormatMap map; - using namespace rx; - - // | Format | Type | Internal format | Color write function | - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8, WriteColor<R8G8B8A8, GLfloat> ); - InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM, WriteColor<R8G8B8A8S, GLfloat> ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, WriteColor<R4G4B4A4, GLfloat> ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1, WriteColor<R5G5B5A1, GLfloat> ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2, WriteColor<R10G10B10A2, GLfloat> ); - InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F, WriteColor<R32G32B32A32F, GLfloat>); - InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F, WriteColor<R16G16B16A16F, GLfloat>); - InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F, WriteColor<R16G16B16A16F, GLfloat>); - - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI, WriteColor<R8G8B8A8, GLuint> ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I, WriteColor<R8G8B8A8S, GLint> ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI, WriteColor<R16G16B16A16, GLuint> ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I, WriteColor<R16G16B16A16S, GLint> ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI, WriteColor<R32G32B32A32, GLuint> ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I, WriteColor<R32G32B32A32S, GLint> ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI, WriteColor<R10G10B10A2, GLuint> ); - - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8, WriteColor<R8G8B8, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM, WriteColor<R8G8B8S, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565, WriteColor<R5G6B5, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F, WriteColor<R11G11B10F, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5, WriteColor<R9G9B9E5, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F, WriteColor<R32G32B32F, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F, WriteColor<R16G16B16F, GLfloat> ); - InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F, WriteColor<R16G16B16F, GLfloat> ); - - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI, WriteColor<R8G8B8, GLuint> ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I, WriteColor<R8G8B8S, GLint> ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI, WriteColor<R16G16B16, GLuint> ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I, WriteColor<R16G16B16S, GLint> ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI, WriteColor<R32G32B32, GLuint> ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I, WriteColor<R32G32B32S, GLint> ); - - InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8, WriteColor<R8G8, GLfloat> ); - InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM, WriteColor<R8G8S, GLfloat> ); - InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F, WriteColor<R32G32F, GLfloat> ); - InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F, WriteColor<R16G16F, GLfloat> ); - InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F, WriteColor<R16G16F, GLfloat> ); - - InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI, WriteColor<R8G8, GLuint> ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I, WriteColor<R8G8S, GLint> ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI, WriteColor<R16G16, GLuint> ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I, WriteColor<R16G16S, GLint> ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI, WriteColor<R32G32, GLuint> ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I, WriteColor<R32G32S, GLint> ); - - InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8, WriteColor<R8, GLfloat> ); - InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM, WriteColor<R8S, GLfloat> ); - InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F, WriteColor<R32F, GLfloat> ); - InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F, WriteColor<R16F, GLfloat> ); - InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F, WriteColor<R16F, GLfloat> ); - - InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI, WriteColor<R8, GLuint> ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I, WriteColor<R8S, GLint> ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI, WriteColor<R16, GLuint> ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I, WriteColor<R16S, GLint> ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI, WriteColor<R32, GLuint> ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I, WriteColor<R32S, GLint> ); - - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT, WriteColor<L8A8, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT, WriteColor<L8, GLfloat> ); - InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT, WriteColor<A8, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, WriteColor<L32A32F, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor<L32F, GLfloat> ); - InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor<A32F, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT, WriteColor<L16F, GLfloat> ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor<L16F, GLfloat> ); - InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT, WriteColor<A16F, GLfloat> ); - InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor<A16F, GLfloat> ); - - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor<B8G8R8A8, GLfloat> ); - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor<B4G4R4A4, GLfloat> ); - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor<B5G5R5A1, GLfloat> ); - - InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8, WriteColor<R8G8B8, GLfloat> ); - InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8, WriteColor<R8G8B8A8, GLfloat> ); - - InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL ); - - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16, NULL ); - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES, NULL ); - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F, NULL ); - - InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8, NULL ); - - InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8, NULL ); - InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8, NULL ); + // | Format | Type | Internal format | + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8); + InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2); + InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F); + + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI); + + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8); + InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5); + InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F); + + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I); + + InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8); + InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM); + InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F); + + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I); + + InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8); + InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM); + InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F); + + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I); + + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT); + + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT); + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX); + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX); + + InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8); + InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8); + + InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F); + + InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8); + + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8); + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8); return map; } Type::Type() : bytes(0), + bytesShift(0), specialInterpretation(false) { } -// Map of sizes of input types -typedef std::pair<GLenum, Type> TypeInfoPair; -typedef std::map<GLenum, Type> TypeInfoMap; - -static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation) +static Type GenTypeInfo(GLuint bytes, bool specialInterpretation) { Type info; info.bytes = bytes; + GLuint i = 0; + while ((1u << i) < bytes) + { + ++i; + } + info.bytesShift = i; + ASSERT((1u << info.bytesShift) == bytes); info.specialInterpretation = specialInterpretation; - - map->insert(std::make_pair(type, info)); + return info; } bool operator<(const Type& a, const Type& b) @@ -167,34 +157,6 @@ bool operator<(const Type& a, const Type& b) return memcmp(&a, &b, sizeof(Type)) < 0; } -static TypeInfoMap BuildTypeInfoMap() -{ - TypeInfoMap map; - - InsertTypeInfo(&map, GL_UNSIGNED_BYTE, 1, false); - InsertTypeInfo(&map, GL_BYTE, 1, false); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT, 2, false); - InsertTypeInfo(&map, GL_SHORT, 2, false); - InsertTypeInfo(&map, GL_UNSIGNED_INT, 4, false); - InsertTypeInfo(&map, GL_INT, 4, false); - InsertTypeInfo(&map, GL_HALF_FLOAT, 2, false); - InsertTypeInfo(&map, GL_HALF_FLOAT_OES, 2, false); - InsertTypeInfo(&map, GL_FLOAT, 4, false); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_6_5, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_5_5_1, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_10F_11F_11F_REV, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_5_9_9_9_REV, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8_OES, 4, true ); - InsertTypeInfo(&map, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, true ); - - return map; -} - // Information about internal formats static bool AlwaysSupported(GLuint, const Extensions &) { @@ -454,7 +416,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported ))); map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported ))); map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, RequireES<2>, RequireES<2>, NeverSupported ))); + // STENCIL_INDEX8 is special-cased, see around the bottom of the list. // Luminance alpha formats // | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable | @@ -511,6 +473,13 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() // From GL_ANGLE_texture_compression_dxt5 map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); + // For STENCIL_INDEX8 we chose a normalized component type for the following reasons: + // - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8 + // - All other stencil formats (all depth-stencil) are either float or normalized + // - It affects only validation of internalformat in RenderbufferStorageMultisample. + // | Internal format | |D |S |X | Format | Type | Component type | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat(0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, NeverSupported))); + return map; } @@ -536,33 +505,59 @@ static FormatSet BuildAllSizedInternalFormatSet() return result; } -const FormatType &GetFormatTypeInfo(GLenum format, GLenum type) -{ - static const FormatMap formatMap = BuildFormatMap(); - FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type)); - if (iter != formatMap.end()) - { - return iter->second; - } - else - { - static const FormatType defaultInfo; - return defaultInfo; - } -} - const Type &GetTypeInfo(GLenum type) { - static const TypeInfoMap infoMap = BuildTypeInfoMap(); - TypeInfoMap::const_iterator iter = infoMap.find(type); - if (iter != infoMap.end()) + switch (type) { - return iter->second; - } - else - { - static const Type defaultInfo; - return defaultInfo; + case GL_UNSIGNED_BYTE: + case GL_BYTE: + { + static const Type info = GenTypeInfo(1, false); + return info; + } + case GL_UNSIGNED_SHORT: + case GL_SHORT: + case GL_HALF_FLOAT: + case GL_HALF_FLOAT_OES: + { + static const Type info = GenTypeInfo(2, false); + return info; + } + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + { + static const Type info = GenTypeInfo(4, false); + return info; + } + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + { + static const Type info = GenTypeInfo(2, true); + return info; + } + case GL_UNSIGNED_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_24_8: + case GL_UNSIGNED_INT_10F_11F_11F_REV: + case GL_UNSIGNED_INT_5_9_9_9_REV: + { + ASSERT(GL_UNSIGNED_INT_24_8_OES == GL_UNSIGNED_INT_24_8); + static const Type info = GenTypeInfo(4, true); + return info; + } + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + static const Type info = GenTypeInfo(8, true); + return info; + } + default: + { + static const Type defaultInfo; + return defaultInfo; + } } } @@ -581,18 +576,28 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat) } } -GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const +GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const { ASSERT(alignment > 0 && isPow2(alignment)); - return rx::roundUp(computeBlockSize(type, width, 1), static_cast<GLuint>(alignment)); + GLuint rowBytes; + if (rowLength > 0) + { + ASSERT(!compressed); + rowBytes = pixelBytes * rowLength; + } + else + { + rowBytes = computeBlockSize(formatType, width, 1); + } + return rx::roundUp(rowBytes, static_cast<GLuint>(alignment)); } -GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const +GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const { - return computeRowPitch(type, width, alignment) * height; + return computeRowPitch(formatType, width, alignment, rowLength) * height; } -GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const +GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const { if (compressed) { @@ -602,7 +607,7 @@ GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei heig } else { - const Type &typeInfo = GetTypeInfo(type); + const Type &typeInfo = GetTypeInfo(formatType); if (typeInfo.specialInterpretation) { return typeInfo.bytes * width * height; @@ -617,7 +622,23 @@ GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei heig GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) { const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); - return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat; + if (formatInfo.pixelBytes > 0) + { + return internalFormat; + } + else + { + static const FormatMap formatMap = BuildFormatMap(); + FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type)); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + return GL_NONE; + } + } } const FormatSet &GetAllSizedInternalFormats() diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.h b/src/3rdparty/angle/src/libANGLE/formatutils.h new file mode 100644 index 0000000000..37d4a8f8ef --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/formatutils.h @@ -0,0 +1,81 @@ +// +// Copyright (c) 2013 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. +// + +// formatutils.h: Queries for GL image formats. + +#ifndef LIBANGLE_FORMATUTILS_H_ +#define LIBANGLE_FORMATUTILS_H_ + +#include "libANGLE/Caps.h" +#include "libANGLE/angletypes.h" + +#include "angle_gl.h" + +#include <cstddef> +#include <stdint.h> + +namespace gl +{ + +struct Type +{ + Type(); + + GLuint bytes; + GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a more optimal way + bool specialInterpretation; +}; +const Type &GetTypeInfo(GLenum type); + +struct InternalFormat +{ + InternalFormat(); + + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + + GLuint luminanceBits; + + GLuint alphaBits; + GLuint sharedBits; + + GLuint depthBits; + GLuint stencilBits; + + GLuint pixelBytes; + + GLuint componentCount; + + bool compressed; + GLuint compressedBlockWidth; + GLuint compressedBlockHeight; + + GLenum format; + GLenum type; + + GLenum componentType; + GLenum colorEncoding; + + typedef bool (*SupportCheckFunction)(GLuint, const Extensions &); + SupportCheckFunction textureSupport; + SupportCheckFunction renderSupport; + SupportCheckFunction filterSupport; + + GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const; + GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const; + GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const; +}; +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat); + +GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); + +typedef std::set<GLenum> FormatSet; +const FormatSet &GetAllSizedInternalFormats(); + +} + +#endif // LIBANGLE_FORMATUTILS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp index 7245902c51..460e346eac 100644 --- a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp +++ b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp @@ -6,7 +6,7 @@ // queryconversions.cpp: Implementation of state query cast conversions -#include "libGLESv2/Context.h" +#include "libANGLE/Context.h" #include "common/utilities.h" namespace gl diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.h b/src/3rdparty/angle/src/libANGLE/queryconversions.h index da7047f730..da7047f730 100644 --- a/src/3rdparty/angle/src/libGLESv2/queryconversions.h +++ b/src/3rdparty/angle/src/libANGLE/queryconversions.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h index c031effabd..9bc5eaff58 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h @@ -6,18 +6,18 @@ // BufferImpl.h: Defines the abstract rx::BufferImpl class. -#ifndef LIBGLESV2_RENDERER_BUFFERIMPL_H_ -#define LIBGLESV2_RENDERER_BUFFERIMPL_H_ +#ifndef LIBANGLE_RENDERER_BUFFERIMPL_H_ +#define LIBANGLE_RENDERER_BUFFERIMPL_H_ #include "common/angleutils.h" -#include "libGLESv2/Buffer.h" +#include "libANGLE/Buffer.h" -#include <cstdint> +#include <stdint.h> namespace rx { -class BufferImpl +class BufferImpl : angle::NonCopyable { public: virtual ~BufferImpl() { } @@ -27,9 +27,12 @@ class BufferImpl virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0; virtual gl::Error unmap() = 0; - virtual void markTransformFeedbackUsage() = 0; + + // This method may not have a corresponding GL-backed function. It is necessary + // for validation, for certain indexed draw calls. + virtual gl::Error getData(const uint8_t **outData) = 0; }; } -#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_ +#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h new file mode 100644 index 0000000000..ccc78d8c2a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h @@ -0,0 +1,30 @@ +// +// 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. +// + +// CompilerImpl.h: Defines the rx::CompilerImpl class, an implementation interface +// for the gl::Compiler object. + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +#ifndef LIBANGLE_RENDERER_COMPILERIMPL_H_ +#define LIBANGLE_RENDERER_COMPILERIMPL_H_ + +namespace rx +{ + +class CompilerImpl : angle::NonCopyable +{ + public: + CompilerImpl() {} + virtual ~CompilerImpl() {} + + virtual gl::Error release() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_COMPILERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp new file mode 100644 index 0000000000..7713ee2d6d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp @@ -0,0 +1,58 @@ +// +// 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. +// + +// DisplayImpl.cpp: Implementation methods of egl::Display + +#include "libANGLE/renderer/DisplayImpl.h" + +#include "libANGLE/Surface.h" + +namespace rx +{ + +DisplayImpl::DisplayImpl() + : mExtensionsInitialized(false), + mCapsInitialized(false) +{ +} + +DisplayImpl::~DisplayImpl() +{ + while (!mSurfaceSet.empty()) + { + destroySurface(*mSurfaceSet.begin()); + } +} + +void DisplayImpl::destroySurface(egl::Surface *surface) +{ + mSurfaceSet.erase(surface); + surface->release(); +} + +const egl::DisplayExtensions &DisplayImpl::getExtensions() const +{ + if (!mExtensionsInitialized) + { + generateExtensions(&mExtensions); + mExtensionsInitialized = true; + } + + return mExtensions; +} + +const egl::Caps &DisplayImpl::getCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps); + mCapsInitialized = true; + } + + return mCaps; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h new file mode 100644 index 0000000000..381fa67f71 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h @@ -0,0 +1,99 @@ +// +// 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. +// + +// DisplayImpl.h: Implementation methods of egl::Display + +#ifndef LIBANGLE_RENDERER_DISPLAYIMPL_H_ +#define LIBANGLE_RENDERER_DISPLAYIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Config.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/Renderer.h" + +#include <set> +#include <vector> + +namespace egl +{ +class AttributeMap; +class Display; +struct Config; +class Surface; +} + +namespace gl +{ +class Context; +} + +namespace rx +{ +class SurfaceImpl; +struct ConfigDesc; + +class DisplayImpl : angle::NonCopyable +{ + public: + DisplayImpl(); + virtual ~DisplayImpl(); + + virtual egl::Error initialize(egl::Display *display) = 0; + virtual void terminate() = 0; + + virtual egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) = 0; + virtual egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) = 0; + virtual egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0; + virtual egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0; + virtual egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, + gl::Context **outContext) = 0; + + virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0; + + virtual egl::ConfigSet generateConfigs() const = 0; + + virtual bool isDeviceLost() const = 0; + virtual bool testDeviceLost() = 0; + virtual egl::Error restoreLostDevice() = 0; + + virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0; + + virtual std::string getVendorString() const = 0; + + const egl::Caps &getCaps() const; + + typedef std::set<egl::Surface*> SurfaceSet; + const SurfaceSet &getSurfaceSet() const { return mSurfaceSet; } + SurfaceSet &getSurfaceSet() { return mSurfaceSet; } + + void destroySurface(egl::Surface *surface); + + const egl::DisplayExtensions &getExtensions() const; + + protected: + // Place the surface set here so it can be accessible for handling + // context loss events. (It is shared between the Display and Impl.) + SurfaceSet mSurfaceSet; + + private: + virtual void generateExtensions(egl::DisplayExtensions *outExtensions) const = 0; + virtual void generateCaps(egl::Caps *outCaps) const = 0; + + mutable bool mExtensionsInitialized; + mutable egl::DisplayExtensions mExtensions; + + mutable bool mCapsInitialized; + mutable egl::Caps mCaps; +}; + +} + +#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h new file mode 100644 index 0000000000..3463921d6e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2015 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. +// + +// FenceNVImpl.h: Defines the rx::FenceNVImpl class. + +#ifndef LIBANGLE_RENDERER_FENCENVIMPL_H_ +#define LIBANGLE_RENDERER_FENCENVIMPL_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace rx +{ + +class FenceNVImpl : angle::NonCopyable +{ + public: + FenceNVImpl() { }; + virtual ~FenceNVImpl() { }; + + virtual gl::Error set() = 0; + virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0; + virtual gl::Error finishFence(GLboolean *outFinished) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_FENCENVIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h new file mode 100644 index 0000000000..321964113f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2015 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. +// + +// FenceSyncImpl.h: Defines the rx::FenceSyncImpl class. + +#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_ +#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace rx +{ + +class FenceSyncImpl : angle::NonCopyable +{ + public: + FenceSyncImpl() { }; + virtual ~FenceSyncImpl() { }; + + virtual gl::Error set() = 0; + virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0; + virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0; + virtual gl::Error getStatus(GLint *outResult) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h new file mode 100644 index 0000000000..728f949a0f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h @@ -0,0 +1,68 @@ +// +// Copyright 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. +// + +// FramebufferImpl.h: Defines the abstract rx::FramebufferImpl class. + +#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_ +#define LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" + +namespace gl +{ +class State; +class Framebuffer; +class FramebufferAttachment; +struct Rectangle; +} + +namespace rx +{ + +class FramebufferImpl : angle::NonCopyable +{ + public: + explicit FramebufferImpl(const gl::Framebuffer::Data &data) : mData(data) { } + virtual ~FramebufferImpl() { } + + virtual void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) = 0; + virtual void setDepthAttachment(const gl::FramebufferAttachment *attachment) = 0; + virtual void setStencilAttachment(const gl::FramebufferAttachment *attachment) = 0; + virtual void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) = 0; + + virtual void setDrawBuffers(size_t count, const GLenum *buffers) = 0; + virtual void setReadBuffer(GLenum buffer) = 0; + + virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0; + virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0; + + virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; + virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; + virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; + virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; + virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; + + virtual GLenum getImplementationColorReadFormat() const = 0; + virtual GLenum getImplementationColorReadType() const = 0; + virtual gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const = 0; + + virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0; + + virtual GLenum checkStatus() const = 0; + + const gl::Framebuffer::Data &getData() const { return mData; } + + protected: + const gl::Framebuffer::Data &mData; +}; + +} + +#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libANGLE/renderer/Image.h index 9071a88c67..62d854c9b6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/Image.h @@ -8,11 +8,11 @@ // renderer-specific classes which will define the interface to the underlying // surfaces or resources. -#ifndef LIBGLESV2_RENDERER_IMAGE_H_ -#define LIBGLESV2_RENDERER_IMAGE_H_ +#ifndef LIBANGLE_RENDERER_IMAGE_H_ +#define LIBANGLE_RENDERER_IMAGE_H_ #include "common/debug.h" -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include <GLES2/gl2.h> @@ -20,6 +20,9 @@ namespace gl { class Framebuffer; struct Rectangle; +struct Extents; +struct Box; +struct Offset; struct ImageIndex; } @@ -39,7 +42,6 @@ class Image GLsizei getHeight() const { return mHeight; } GLsizei getDepth() const { return mDepth; } GLenum getInternalFormat() const { return mInternalFormat; } - GLenum getActualFormat() const { return mActualFormat; } GLenum getTarget() const { return mTarget; } bool isRenderableFormat() const { return mRenderable; } @@ -47,16 +49,13 @@ class Image void markClean() {mDirty = false;} virtual bool isDirty() const = 0; - virtual bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; + virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0; - virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) = 0; - virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) = 0; + virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input) = 0; + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0; - gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, gl::Framebuffer *source); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) = 0; - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) = 0; + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; protected: @@ -64,7 +63,6 @@ class Image GLsizei mHeight; GLsizei mDepth; GLenum mInternalFormat; - GLenum mActualFormat; bool mRenderable; GLenum mTarget; @@ -76,4 +74,4 @@ class Image } -#endif // LIBGLESV2_RENDERER_IMAGE_H_ +#endif // LIBANGLE_RENDERER_IMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h new file mode 100644 index 0000000000..d77e59f7df --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h @@ -0,0 +1,68 @@ +// +// Copyright 2015 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. +// +// ImplFactory.h: +// Factory interface for Impl objects. +// + +#ifndef LIBANGLE_RENDERER_IMPLFACTORY_H_ +#define LIBANGLE_RENDERER_IMPLFACTORY_H_ + +#include "libANGLE/Framebuffer.h" + +namespace rx +{ +class BufferImpl; +class CompilerImpl; +class FenceNVImpl; +class FenceSyncImpl; +class FramebufferImpl; +class ProgramImpl; +class QueryImpl; +class RenderbufferImpl; +class ShaderImpl; +class TextureImpl; +class TransformFeedbackImpl; +class VertexArrayImpl; + +class ImplFactory : angle::NonCopyable +{ + public: + ImplFactory() {} + virtual ~ImplFactory() {} + + // Shader creation + virtual CompilerImpl *createCompiler(const gl::Data &data) = 0; + virtual ShaderImpl *createShader(GLenum type) = 0; + virtual ProgramImpl *createProgram() = 0; + + // Framebuffer creation + virtual FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) = 0; + virtual FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) = 0; + + // Texture creation + virtual TextureImpl *createTexture(GLenum target) = 0; + + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer() = 0; + + // Buffer creation + virtual BufferImpl *createBuffer() = 0; + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray() = 0; + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type) = 0; + virtual FenceNVImpl *createFenceNV() = 0; + virtual FenceSyncImpl *createFenceSync() = 0; + + // Transform Feedback creation + virtual TransformFeedbackImpl *createTransformFeedback() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_IMPLFACTORY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp index d472e1499e..4a71cf4b45 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp @@ -7,13 +7,11 @@ // IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about // ranges of indices. -#include "libGLESv2/renderer/IndexRangeCache.h" -#include "libGLESv2/formatutils.h" +#include "libANGLE/renderer/IndexRangeCache.h" +#include "libANGLE/formatutils.h" #include "common/debug.h" -#include <tuple> - namespace rx { @@ -48,10 +46,9 @@ RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsize } } -void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, - unsigned int streamOffset) +void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range) { - mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset); + mIndexRangeCache[IndexRange(type, offset, count)] = range; } void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) @@ -62,8 +59,8 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) IndexRangeMap::iterator i = mIndexRangeCache.begin(); while (i != mIndexRangeCache.end()) { - unsigned int rangeStart = i->second.streamOffset; - unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); + unsigned int rangeStart = i->first.offset; + unsigned int rangeEnd = i->first.offset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) { @@ -71,25 +68,23 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) } else { - i = mIndexRangeCache.erase(i); + mIndexRangeCache.erase(i++); } } } bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, - RangeUI *outRange, unsigned int *outStreamOffset) const + RangeUI *outRange) const { IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); if (i != mIndexRangeCache.end()) { - if (outRange) *outRange = i->second.range; - if (outStreamOffset) *outStreamOffset = i->second.streamOffset; + if (outRange) *outRange = i->second; return true; } else { if (outRange) *outRange = RangeUI(0, 0); - if (outStreamOffset) *outStreamOffset = 0; return false; } } @@ -111,18 +106,9 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const { - return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); -} - -IndexRangeCache::IndexBounds::IndexBounds() - : range(0, 0), - streamOffset(0) -{ -} - -IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset) - : range(rangeIn), streamOffset(offset) -{ + if (type != rhs.type) return type < rhs.type; + if (offset != rhs.offset) return offset < rhs.offset; + return count < rhs.count; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h index a7d91e035b..77249f5ff6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h @@ -7,8 +7,8 @@ // IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about // ranges of indices. -#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ -#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ +#ifndef LIBANGLE_RENDERER_INDEXRANGECACHE_H_ +#define LIBANGLE_RENDERER_INDEXRANGECACHE_H_ #include "common/angleutils.h" #include "common/mathutil.h" @@ -23,10 +23,8 @@ namespace rx class IndexRangeCache { public: - void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, - unsigned int streamOffset); - bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut, - unsigned int *outStreamOffset) const; + void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range); + bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut) const; void invalidateRange(unsigned int offset, unsigned int size); void clear(); @@ -46,19 +44,10 @@ class IndexRangeCache bool operator<(const IndexRange& rhs) const; }; - struct IndexBounds - { - RangeUI range; - unsigned int streamOffset; - - IndexBounds(); - IndexBounds(const RangeUI &range, unsigned int offset); - }; - - typedef std::map<IndexRange, IndexBounds> IndexRangeMap; + typedef std::map<IndexRange, RangeUI> IndexRangeMap; IndexRangeMap mIndexRangeCache; }; } -#endif // LIBGLESV2_RENDERER_INDEXRANGECACHE_H +#endif // LIBANGLE_RENDERER_INDEXRANGECACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp index f9fcad38a4..8fbc53768f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp @@ -6,10 +6,9 @@ // ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. -#include "libGLESv2/renderer/ProgramImpl.h" +#include "libANGLE/renderer/ProgramImpl.h" #include "common/utilities.h" -#include "libGLESv2/main.h" namespace rx { @@ -35,6 +34,12 @@ unsigned int ParseAndStripArrayIndex(std::string* name) } +LinkResult::LinkResult(bool linkSuccess, const gl::Error &error) + : linkSuccess(linkSuccess), + error(error) +{ +} + ProgramImpl::~ProgramImpl() { // Ensure that reset was called by the inherited class during destruction @@ -137,6 +142,7 @@ GLuint ProgramImpl::getUniformBlockIndex(std::string name) const void ProgramImpl::reset() { + std::fill(mSemanticIndex, mSemanticIndex + ArraySize(mSemanticIndex), -1); SafeDeleteContainer(mUniforms); mUniformIndex.clear(); SafeDeleteContainer(mUniformBlocks); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h index 6aaa23cf89..1128ab6741 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h @@ -6,61 +6,50 @@ // ProgramImpl.h: Defines the abstract rx::ProgramImpl class. -#ifndef LIBGLESV2_RENDERER_PROGRAMIMPL_H_ -#define LIBGLESV2_RENDERER_PROGRAMIMPL_H_ +#ifndef LIBANGLE_RENDERER_PROGRAMIMPL_H_ +#define LIBANGLE_RENDERER_PROGRAMIMPL_H_ #include "common/angleutils.h" -#include "libGLESv2/BinaryStream.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libANGLE/BinaryStream.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Program.h" +#include "libANGLE/Shader.h" +#include "libANGLE/renderer/Renderer.h" #include <map> namespace rx { -class ProgramImpl +struct LinkResult +{ + bool linkSuccess; + gl::Error error; + LinkResult(bool linkSuccess, const gl::Error &error); +}; + +class ProgramImpl : angle::NonCopyable { public: + typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS]; + ProgramImpl() { } virtual ~ProgramImpl(); - const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; } - const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; } - const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; } - const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } - const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } - - std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; } - std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; } - std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; } - std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } - sh::Attribute *getShaderAttributes() { return mShaderAttributes; } - - gl::LinkedUniform *getUniformByLocation(GLint location) const; - gl::LinkedUniform *getUniformByName(const std::string &name) const; - gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const; - - GLint getUniformLocation(std::string name); - GLuint getUniformIndex(std::string name); - GLuint getUniformBlockIndex(std::string name) const; - virtual bool usesPointSize() const = 0; virtual int getShaderVersion() const = 0; virtual GLenum getTransformFeedbackBufferMode() const = 0; virtual GLenum getBinaryFormat() = 0; - virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; + virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; - virtual gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector<std::string> &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, - std::map<int, gl::VariableLocation> *outputVariables) = 0; + virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector<std::string> &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, + std::map<int, gl::VariableLocation> *outputVariables) = 0; virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0; virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0; @@ -88,8 +77,6 @@ class ProgramImpl virtual void getUniformiv(GLint location, GLint *params) = 0; virtual void getUniformuiv(GLint location, GLuint *params) = 0; - virtual void reset(); - // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to // determine if they can be removed from this interface. virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0; @@ -98,8 +85,8 @@ class ProgramImpl virtual void updateSamplerMapping() = 0; virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0; - virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers) = 0; + virtual LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers) = 0; virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, const gl::Caps &caps) = 0; @@ -107,21 +94,44 @@ class ProgramImpl const gl::Caps &caps) = 0; virtual gl::Error applyUniforms() = 0; - virtual gl::Error applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps) = 0; + virtual gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) = 0; virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const gl::Caps &caps) = 0; - protected: - DISALLOW_COPY_AND_ASSIGN(ProgramImpl); + const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; } + const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; } + const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; } + const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } + const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } + const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndex; } + + std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; } + std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; } + std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; } + std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } + sh::Attribute *getShaderAttributes() { return mShaderAttributes; } + SemanticIndexArray &getSemanticIndexes() { return mSemanticIndex; } + + gl::LinkedUniform *getUniformByLocation(GLint location) const; + gl::LinkedUniform *getUniformByName(const std::string &name) const; + gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const; + + GLint getUniformLocation(std::string name); + GLuint getUniformIndex(std::string name); + GLuint getUniformBlockIndex(std::string name) const; + virtual void reset(); + + protected: std::vector<gl::LinkedUniform*> mUniforms; std::vector<gl::VariableLocation> mUniformIndex; std::vector<gl::UniformBlock*> mUniformBlocks; std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings; + SemanticIndexArray mSemanticIndex; sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS]; }; } -#endif // LIBGLESV2_RENDERER_PROGRAMIMPL_H_ +#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h index 6b45810a3b..bed63ea1b0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h @@ -6,10 +6,10 @@ // QueryImpl.h: Defines the abstract rx::QueryImpl class. -#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_ -#define LIBGLESV2_RENDERER_QUERYIMPL_H_ +#ifndef LIBANGLE_RENDERER_QUERYIMPL_H_ +#define LIBANGLE_RENDERER_QUERYIMPL_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include "common/angleutils.h" @@ -18,7 +18,7 @@ namespace rx { -class QueryImpl +class QueryImpl : angle::NonCopyable { public: explicit QueryImpl(GLenum type) { mType = type; } @@ -32,11 +32,9 @@ class QueryImpl GLenum getType() const { return mType; } private: - DISALLOW_COPY_AND_ASSIGN(QueryImpl); - GLenum mType; }; } -#endif // LIBGLESV2_RENDERER_QUERYIMPL_H_ +#endif // LIBANGLE_RENDERER_QUERYIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp index 770ae8e9c6..ea5a40a21a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp @@ -6,7 +6,7 @@ // RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl -#include "libGLESv2/renderer/RenderbufferImpl.h" +#include "libANGLE/renderer/RenderbufferImpl.h" namespace rx { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h new file mode 100644 index 0000000000..8ce257c833 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.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. +// + +// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl + +#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ +#define LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ + +#include "angle_gl.h" + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +namespace rx +{ + +class RenderbufferImpl : angle::NonCopyable +{ + public: + RenderbufferImpl(); + virtual ~RenderbufferImpl() = 0; + + virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0; + virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp new file mode 100644 index 0000000000..fbc2ad5d1c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2012-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. +// + +// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. + +#include "common/utilities.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/renderer/Renderer.h" + +#include <EGL/eglext.h> + +namespace rx +{ + +Renderer::Renderer() + : mCapsInitialized(false), + mWorkaroundsInitialized(false) +{ +} + +Renderer::~Renderer() +{ +} + +const gl::Caps &Renderer::getRendererCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mCaps; +} + +const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mTextureCaps; +} + +const gl::Extensions &Renderer::getRendererExtensions() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mExtensions; +} + +const Workarounds &Renderer::getWorkarounds() const +{ + if (!mWorkaroundsInitialized) + { + mWorkarounds = generateWorkarounds(); + mWorkaroundsInitialized = true; + } + + return mWorkarounds; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h new file mode 100644 index 0000000000..b607fe5613 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2012-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. +// + +// Renderer.h: Defines a back-end specific class that hides the details of the +// implementation-specific renderer. + +#ifndef LIBANGLE_RENDERER_RENDERER_H_ +#define LIBANGLE_RENDERER_RENDERER_H_ + +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Uniform.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/ImplFactory.h" +#include "libANGLE/renderer/Workarounds.h" +#include "common/mathutil.h" + +#include <stdint.h> + +#include <EGL/egl.h> + +namespace egl +{ +class AttributeMap; +class Display; +class Surface; +} + +namespace gl +{ +class Buffer; +struct Data; +} + +namespace rx +{ +struct TranslatedIndexData; +struct Workarounds; +class DisplayImpl; + +class Renderer : public ImplFactory +{ + public: + Renderer(); + virtual ~Renderer(); + + virtual gl::Error flush() = 0; + virtual gl::Error finish() = 0; + + virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, + GLint first, GLsizei count, GLsizei instances) = 0; + virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) = 0; + + // lost device + //TODO(jmadill): investigate if this stuff is necessary in GL + virtual void notifyDeviceLost() = 0; + virtual bool isDeviceLost() const = 0; + virtual bool testDeviceLost() = 0; + virtual bool testDeviceResettable() = 0; + + virtual VendorID getVendorId() const = 0; + virtual std::string getVendorString() const = 0; + virtual std::string getRendererDescription() const = 0; + + // Renderer capabilities + const gl::Caps &getRendererCaps() const; + const gl::TextureCapsMap &getRendererTextureCaps() const; + const gl::Extensions &getRendererExtensions() const; + const Workarounds &getWorkarounds() const; + + private: + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; + virtual Workarounds generateWorkarounds() const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mCaps; + mutable gl::TextureCapsMap mTextureCaps; + mutable gl::Extensions mExtensions; + + mutable bool mWorkaroundsInitialized; + mutable Workarounds mWorkarounds; +}; + +} +#endif // LIBANGLE_RENDERER_RENDERER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h index cb0d360f0b..3011bc57f8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h @@ -6,28 +6,29 @@ // ShaderImpl.h: Defines the abstract rx::ShaderImpl class. -#ifndef LIBGLESV2_RENDERER_SHADERIMPL_H_ -#define LIBGLESV2_RENDERER_SHADERIMPL_H_ +#ifndef LIBANGLE_RENDERER_SHADERIMPL_H_ +#define LIBANGLE_RENDERER_SHADERIMPL_H_ #include <vector> #include "common/angleutils.h" -#include "libGLESv2/Shader.h" +#include "libANGLE/Shader.h" namespace rx { -class ShaderImpl +class ShaderImpl : angle::NonCopyable { public: ShaderImpl() { } virtual ~ShaderImpl() { } - virtual bool compile(const gl::Data &data, const std::string &source) = 0; - virtual const std::string &getInfoLog() const = 0; - virtual const std::string &getTranslatedSource() const = 0; + virtual bool compile(gl::Compiler *compiler, const std::string &source) = 0; virtual std::string getDebugInfo() const = 0; + virtual const std::string &getInfoLog() const { return mInfoLog; } + virtual const std::string &getTranslatedSource() const { return mTranslatedSource; } + const std::vector<gl::PackedVarying> &getVaryings() const { return mVaryings; } const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; } const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; } @@ -41,7 +42,8 @@ class ShaderImpl std::vector<sh::Attribute> &getActiveOutputVariables() { return mActiveOutputVariables; } protected: - DISALLOW_COPY_AND_ASSIGN(ShaderImpl); + std::string mInfoLog; + std::string mTranslatedSource; std::vector<gl::PackedVarying> mVaryings; std::vector<sh::Uniform> mUniforms; @@ -52,4 +54,4 @@ class ShaderImpl } -#endif // LIBGLESV2_RENDERER_SHADERIMPL_H_ +#endif // LIBANGLE_RENDERER_SHADERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp new file mode 100644 index 0000000000..36f5fdca3f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2002-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. +// + +// SurfaceImpl.cpp: Implementation of Surface stub method class + +#include "libANGLE/renderer/SurfaceImpl.h" + +namespace rx +{ + +SurfaceImpl::SurfaceImpl() +{ +} + +SurfaceImpl::~SurfaceImpl() +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h new file mode 100644 index 0000000000..ca04a42bd1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h @@ -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. +// + +// SurfaceImpl.h: Implementation methods of egl::Surface + +#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_ +#define LIBANGLE_RENDERER_SURFACEIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +namespace egl +{ +class Display; +struct Config; +} + +namespace rx +{ + +class SurfaceImpl : angle::NonCopyable +{ + public: + SurfaceImpl(); + virtual ~SurfaceImpl(); + + virtual egl::Error initialize() = 0; + virtual egl::Error swap() = 0; + virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0; + virtual egl::Error bindTexImage(EGLint buffer) = 0; + virtual egl::Error releaseTexImage(EGLint buffer) = 0; + virtual void setSwapInterval(EGLint interval) = 0; + + // width and height can change with client window resizing + virtual EGLint getWidth() const = 0; + virtual EGLint getHeight() const = 0; + + virtual EGLint isPostSubBufferSupported() const = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_ + diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h new file mode 100644 index 0000000000..d628906116 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h @@ -0,0 +1,72 @@ +// +// Copyright 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. +// + +// TextureImpl.h: Defines the abstract rx::TextureImpl classes. + +#ifndef LIBANGLE_RENDERER_TEXTUREIMPL_H_ +#define LIBANGLE_RENDERER_TEXTUREIMPL_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/ImageIndex.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include <stdint.h> + +namespace egl +{ +class Surface; +} + +namespace gl +{ +struct Box; +struct Extents; +struct Offset; +struct Rectangle; +class Framebuffer; +struct PixelUnpackState; +struct SamplerState; +} + +namespace rx +{ + +class TextureImpl : angle::NonCopyable +{ + public: + virtual ~TextureImpl() {}; + + virtual void setUsage(GLenum usage) = 0; + + virtual gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + virtual gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + + virtual gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + virtual gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + + virtual gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) = 0; + virtual gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) = 0; + + virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0; + + virtual gl::Error generateMipmaps() = 0; + + virtual void bindTexImage(egl::Surface *surface) = 0; + virtual void releaseTexImage() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_TEXTUREIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h index 8425604d87..8f9133cfe5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h @@ -6,16 +6,16 @@ // TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class. -#ifndef LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ -#define LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ +#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_ +#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_ #include "common/angleutils.h" -#include "libGLESv2/TransformFeedback.h" +#include "libANGLE/TransformFeedback.h" namespace rx { -class TransformFeedbackImpl +class TransformFeedbackImpl : angle::NonCopyable { public: virtual ~TransformFeedbackImpl() { } @@ -28,4 +28,4 @@ class TransformFeedbackImpl } -#endif // LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ +#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h index b013f9cdf4..0e25f952c2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h @@ -6,17 +6,17 @@ // VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class. -#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ -#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ +#ifndef LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ +#define LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ #include "common/angleutils.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/VertexAttribute.h" namespace rx { -class VertexArrayImpl +class VertexArrayImpl : angle::NonCopyable { public: virtual ~VertexArrayImpl() { } @@ -29,4 +29,4 @@ class VertexArrayImpl } -#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ +#endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h new file mode 100644 index 0000000000..b73f4a5472 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h @@ -0,0 +1,74 @@ +// +// 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. +// + +// angletypes.h: Workarounds for driver bugs and other issues. + +#ifndef LIBANGLE_RENDERER_WORKAROUNDS_H_ +#define LIBANGLE_RENDERER_WORKAROUNDS_H_ + +// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate +// independent of ANGLE's renderer. Workarounds should also be accessible +// outside of the Renderer. + +namespace rx +{ + +struct D3DCompilerWorkarounds : angle::NonCopyable +{ + D3DCompilerWorkarounds() + : skipOptimization(false), + useMaxOptimization(false), + enableIEEEStrictness(false) + {} + + void reset() + { + skipOptimization = false; + useMaxOptimization = false; + enableIEEEStrictness = false; + } + + bool skipOptimization; + bool useMaxOptimization; + + // IEEE strictness needs to be enabled for NANs to work. + bool enableIEEEStrictness; +}; + +struct Workarounds +{ + Workarounds() + : mrtPerfWorkaround(false), + setDataFasterThanImageUpload(false), + zeroMaxLodWorkaround(false), + useInstancedPointSpriteEmulation(false) + {} + + // On some systems, having extra rendertargets than necessary slows down the shader. + // We can fix this by optimizing those out of the shader. At the same time, we can + // work around a bug on some nVidia drivers that they ignore "null" render targets + // in D3D11, by compacting the active color attachments list to omit null entries. + bool mrtPerfWorkaround; + + bool setDataFasterThanImageUpload; + + // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero, and ignore the other levels). + // D3D11 Feature Level 10+ does this by setting MaxLOD to 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. + // There is no equivalent to this in D3D11 Feature Level 9_3. + // This causes problems when (for example) an application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST (i.e disables mipmaps). + // To work around this, D3D11 FL9_3 has to create two copies of the texture. The textures' level zeros are identical, but only one texture has mips. + bool zeroMaxLodWorkaround; + + // Some renderers do not support Geometry Shaders so the Geometry Shader-based + // PointSprite emulation will not work. + // To work around this, D3D11 FL9_3 has to use a different pointsprite + // emulation that is implemented using instanced quads. + bool useInstancedPointSpriteEmulation; +}; + +} + +#endif // LIBANGLE_RENDERER_WORKAROUNDS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp index dd0d3f52ad..1af8794356 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -6,20 +6,22 @@ // BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" + +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" namespace rx { unsigned int BufferD3D::mNextSerial = 1; -BufferD3D::BufferD3D() +BufferD3D::BufferD3D(BufferFactoryD3D *factory) : BufferImpl(), - mStaticVertexBuffer(NULL), - mStaticIndexBuffer(NULL) + mFactory(factory), + mStaticVertexBuffer(nullptr), + mStaticIndexBuffer(nullptr), + mUnmodifiedDataUse(0) { updateSerial(); } @@ -30,19 +32,6 @@ BufferD3D::~BufferD3D() SafeDelete(mStaticIndexBuffer); } -BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer)); - return static_cast<BufferD3D*>(buffer); -} - -BufferD3D *BufferD3D::makeFromBuffer(gl::Buffer *buffer) -{ - BufferImpl *impl = buffer->getImplementation(); - ASSERT(impl); - return makeBufferD3D(impl); -} - void BufferD3D::updateSerial() { mSerial = mNextSerial++; @@ -52,11 +41,11 @@ void BufferD3D::initializeStaticData() { if (!mStaticVertexBuffer) { - mStaticVertexBuffer = new StaticVertexBufferInterface(getRenderer()); + mStaticVertexBuffer = new StaticVertexBufferInterface(mFactory); } if (!mStaticIndexBuffer) { - mStaticIndexBuffer = new StaticIndexBufferInterface(getRenderer()); + mStaticIndexBuffer = new StaticIndexBufferInterface(mFactory); } } @@ -66,6 +55,9 @@ void BufferD3D::invalidateStaticData() { SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticIndexBuffer); + + // Re-init static data to track that we're in a static buffer + initializeStaticData(); } mUnmodifiedDataUse = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h index 1a1308c545..a46398f911 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h @@ -4,37 +4,33 @@ // found in the LICENSE file. // -// BufferImpl.h: Defines the abstract rx::BufferImpl class. +// BufferD3D.h: Defines the rx::BufferD3D class, an implementation of BufferImpl. -#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_ -#define LIBGLESV2_RENDERER_BUFFERD3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ -#include "libGLESv2/renderer/BufferImpl.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/angletypes.h" -#include <cstdint> +#include <stdint.h> namespace rx { -class RendererD3D; +class BufferFactoryD3D; class StaticIndexBufferInterface; class StaticVertexBufferInterface; class BufferD3D : public BufferImpl { public: - BufferD3D(); + BufferD3D(BufferFactoryD3D *factory); virtual ~BufferD3D(); - static BufferD3D *makeBufferD3D(BufferImpl *buffer); - static BufferD3D *makeFromBuffer(gl::Buffer *buffer); - unsigned int getSerial() const { return mSerial; } - virtual gl::Error getData(const uint8_t **outData) = 0; virtual size_t getSize() const = 0; virtual bool supportsDirectBinding() const = 0; - virtual RendererD3D *getRenderer() = 0; + virtual void markTransformFeedbackUsage() = 0; StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } @@ -44,11 +40,12 @@ class BufferD3D : public BufferImpl void promoteStaticUsage(int dataSize); protected: + void updateSerial(); + + BufferFactoryD3D *mFactory; unsigned int mSerial; static unsigned int mNextSerial; - void updateSerial(); - StaticVertexBufferInterface *mStaticVertexBuffer; StaticIndexBufferInterface *mStaticIndexBuffer; unsigned int mUnmodifiedDataUse; @@ -56,4 +53,4 @@ class BufferD3D : public BufferImpl } -#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp new file mode 100644 index 0000000000..a22757cf9f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp @@ -0,0 +1,128 @@ +// +// 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. +// + +// CompilerD3D.cpp: Implementation of the rx::CompilerD3D class. + +#include "libANGLE/renderer/d3d/CompilerD3D.h" + +#include "libANGLE/Caps.h" +#include "libANGLE/Data.h" + +#include "common/debug.h" + +namespace rx +{ + +// Global count of active shader compiler handles. Needed to know when to call ShInitialize and ShFinalize. +static size_t activeCompilerHandles = 0; + +CompilerD3D::CompilerD3D(const gl::Data &data, ShShaderOutput outputType) + : mSpec(data.clientVersion > 2 ? SH_GLES3_SPEC : SH_GLES2_SPEC), + mOutputType(outputType), + mResources(), + mFragmentCompiler(NULL), + mVertexCompiler(NULL) +{ + ASSERT(data.clientVersion == 2 || data.clientVersion == 3); + + const gl::Caps &caps = *data.caps; + const gl::Extensions &extensions = *data.extensions; + + ShInitBuiltInResources(&mResources); + mResources.MaxVertexAttribs = caps.maxVertexAttributes; + mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; + mResources.MaxVaryingVectors = caps.maxVaryingVectors; + mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; + mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; + mResources.MaxTextureImageUnits = caps.maxTextureImageUnits; + mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; + mResources.MaxDrawBuffers = caps.maxDrawBuffers; + mResources.OES_standard_derivatives = extensions.standardDerivatives; + mResources.EXT_draw_buffers = extensions.drawBuffers; + mResources.EXT_shader_texture_lod = 1; + // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. + mResources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp + mResources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output + + // GLSL ES 3.0 constants + mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; + mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; + mResources.MinProgramTexelOffset = caps.minProgramTexelOffset; + mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; +} + +CompilerD3D::~CompilerD3D() +{ + release(); +} + +CompilerD3D *CompilerD3D::makeCompilerD3D(CompilerImpl *compiler) +{ + ASSERT(HAS_DYNAMIC_TYPE(CompilerD3D*, compiler)); + return static_cast<CompilerD3D*>(compiler); +} + +gl::Error CompilerD3D::release() +{ + if (mFragmentCompiler) + { + ShDestruct(mFragmentCompiler); + mFragmentCompiler = NULL; + + ASSERT(activeCompilerHandles > 0); + activeCompilerHandles--; + } + + if (mVertexCompiler) + { + ShDestruct(mVertexCompiler); + mVertexCompiler = NULL; + + ASSERT(activeCompilerHandles > 0); + activeCompilerHandles--; + } + + if (activeCompilerHandles == 0) + { + ShFinalize(); + } + + return gl::Error(GL_NO_ERROR); +} + +ShHandle CompilerD3D::getCompilerHandle(GLenum type) +{ + ShHandle *compiler = NULL; + switch (type) + { + case GL_VERTEX_SHADER: + compiler = &mVertexCompiler; + break; + + case GL_FRAGMENT_SHADER: + compiler = &mFragmentCompiler; + break; + + default: + UNREACHABLE(); + return NULL; + } + + if (!(*compiler)) + { + if (activeCompilerHandles == 0) + { + ShInitialize(); + } + + *compiler = ShConstructCompiler(type, mSpec, mOutputType, &mResources); + activeCompilerHandles++; + } + + return *compiler; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h new file mode 100644 index 0000000000..0f83e4f8c8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h @@ -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. +// + +// CompilerD3D.h: Defines the rx::CompilerD3D class, an implementation of rx::CompilerImpl. + +#ifndef LIBANGLE_RENDERER_COMPILERD3D_H_ +#define LIBANGLE_RENDERER_COMPILERD3D_H_ + +#include "libANGLE/renderer/CompilerImpl.h" +#include "libANGLE/Caps.h" + +#include "GLSLANG/ShaderLang.h" + +namespace gl +{ +struct Data; +} + +namespace rx +{ + +class CompilerD3D : public CompilerImpl +{ + public: + CompilerD3D(const gl::Data &data, ShShaderOutput outputType); + virtual ~CompilerD3D(); + + static CompilerD3D *makeCompilerD3D(CompilerImpl *compiler); + + gl::Error release() override; + + ShHandle getCompilerHandle(GLenum type); + + private: + ShShaderSpec mSpec; + ShShaderOutput mOutputType; + ShBuiltInResources mResources; + + ShHandle mFragmentCompiler; + ShHandle mVertexCompiler; +}; + +} + +#endif // LIBANGLE_RENDERER_COMPILERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp new file mode 100644 index 0000000000..add5d62fae --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -0,0 +1,357 @@ +// +// 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. +// + +// DisplayD3D.cpp: D3D implementation of egl::Display + +#include "libANGLE/renderer/d3d/DisplayD3D.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Config.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "platform/Platform.h" + +#include <EGL/eglext.h> + +#if defined (ANGLE_ENABLE_D3D9) +# include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#endif // ANGLE_ENABLE_D3D9 + +#if defined (ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#endif // ANGLE_ENABLE_D3D11 + +#if defined (ANGLE_TEST_CONFIG) +# define ANGLE_DEFAULT_D3D11 1 +#endif + +#if !defined(ANGLE_DEFAULT_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +# define ANGLE_DEFAULT_D3D11 0 +#endif + +namespace rx +{ + +typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display*); + +template <typename RendererType> +static RendererD3D *CreateTypedRendererD3D(egl::Display *display) +{ + return new RendererType(display); +} + +egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) +{ + ASSERT(outRenderer != nullptr); + + std::vector<CreateRendererD3DFunction> rendererCreationFunctions; + + const auto &attribMap = display->getAttributeMap(); + EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); + + EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + +# if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); + } +# endif + + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) + { + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +# if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); +# endif +# else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>); +# endif +# endif + } + + egl::Error result(EGL_NOT_INITIALIZED, "No available renderers."); + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) + { + RendererD3D *renderer = rendererCreationFunctions[i](display); + result = renderer->initialize(); + +# if defined(ANGLE_ENABLE_D3D11) + if (renderer->getRendererClass() == RENDERER_D3D11) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS); + + angle::Platform *platform = ANGLEPlatformCurrent(); + platform->histogramEnumeration("GPU.ANGLE.D3D11InitializeResult", + result.getID(), NUM_D3D11_INIT_ERRORS); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (renderer->getRendererClass() == RENDERER_D3D9) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS); + + angle::Platform *platform = ANGLEPlatformCurrent(); + platform->histogramEnumeration("GPU.ANGLE.D3D9InitializeResult", + result.getID(), NUM_D3D9_INIT_ERRORS); + } +# endif + + if (!result.isError()) + { + *outRenderer = renderer; + break; + } + else + { + // Failed to create the renderer, try the next + SafeDelete(renderer); + } + } + + return result; +} + +DisplayD3D::DisplayD3D() + : mRenderer(nullptr) +{ +} + +egl::Error DisplayD3D::createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + EGLint width = attribs.get(EGL_WIDTH, 0); + EGLint height = attribs.get(EGL_HEIGHT, 0); + EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE); + + if (!fixedSize) + { + width = -1; + height = -1; + } + + SurfaceD3D *surface = SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize, + width, height); + egl::Error error = surface->initialize(); + if (error.isError()) + { + SafeDelete(surface); + return error; + } + + *outSurface = surface; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + EGLint width = attribs.get(EGL_WIDTH, 0); + EGLint height = attribs.get(EGL_HEIGHT, 0); + + SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, NULL, width, height); + egl::Error error = surface->initialize(); + if (error.isError()) + { + SafeDelete(surface); + return error; + } + + *outSurface = surface; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + EGLint width = attribs.get(EGL_WIDTH, 0); + EGLint height = attribs.get(EGL_HEIGHT, 0); + + SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, shareHandle, + width, height); + egl::Error error = surface->initialize(); + if (error.isError()) + { + SafeDelete(surface); + return error; + } + + *outSurface = surface; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + UNIMPLEMENTED(); + *outSurface = nullptr; + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, + gl::Context **outContext) +{ + ASSERT(mRenderer != nullptr); + + EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1); + bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT); + bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE); + + *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::initialize(egl::Display *display) +{ + ASSERT(mRenderer == nullptr && display != nullptr); + mDisplay = display; + return CreateRendererD3D(display, &mRenderer); +} + +void DisplayD3D::terminate() +{ + SafeDelete(mRenderer); +} + +egl::ConfigSet DisplayD3D::generateConfigs() const +{ + ASSERT(mRenderer != nullptr); + return mRenderer->generateConfigs(); +} + +bool DisplayD3D::isDeviceLost() const +{ + ASSERT(mRenderer != nullptr); + return mRenderer->isDeviceLost(); +} + +bool DisplayD3D::testDeviceLost() +{ + ASSERT(mRenderer != nullptr); + return mRenderer->testDeviceLost(); +} + +egl::Error DisplayD3D::restoreLostDevice() +{ + // Release surface resources to make the Reset() succeed + for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + { + const auto &surface = *it; + if (surface->getBoundTexture()) + { + surface->releaseTexImage(EGL_BACK_BUFFER); + } + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + surfaceD3D->releaseSwapChain(); + } + + if (!mRenderer->resetDevice()) + { + return egl::Error(EGL_BAD_ALLOC); + } + + // Restore any surfaces that may have been lost + for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + { + const auto &surface = *it; + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + + egl::Error error = surfaceD3D->resetSwapChain(); + if (error.isError()) + { + return error; + } + } + + return egl::Error(EGL_SUCCESS); +} + +bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const +{ + return NativeWindow::isValidNativeWindow(window); +} + +void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = true; + + // ANGLE-specific extensions + if (mRenderer->getShareHandleSupport()) + { + outExtensions->d3dShareHandleClientBuffer = true; + outExtensions->surfaceD3DTexture2DShareHandle = true; + } + + outExtensions->querySurfacePointer = true; + outExtensions->windowFixedSize = true; + + if (mRenderer->getPostSubBufferSupport()) + { + outExtensions->postSubBuffer = true; + } + + outExtensions->createContext = true; +} + +std::string DisplayD3D::getVendorString() const +{ + std::string vendorString = "Google Inc."; + if (mRenderer) + { + vendorString += " " + mRenderer->getVendorString(); + } + + return vendorString; +} + +void DisplayD3D::generateCaps(egl::Caps *outCaps) const +{ + // Display must be initialized to generate caps + ASSERT(mRenderer != nullptr); + + outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h new file mode 100644 index 0000000000..f007ba9a19 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -0,0 +1,61 @@ +// +// 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. +// + +// DisplayD3D.h: D3D implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ +#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ + +#include "libANGLE/renderer/DisplayImpl.h" + +namespace rx +{ +class RendererD3D; + +class DisplayD3D : public DisplayImpl +{ + public: + DisplayD3D(); + + egl::Error initialize(egl::Display *display) override; + virtual void terminate() override; + + egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) override; + egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) override; + egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override; + egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override; + + egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, + gl::Context **outContext) override; + + egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override; + + egl::ConfigSet generateConfigs() const override; + + bool isDeviceLost() const override; + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + std::string getVendorString() const override; + + private: + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + egl::Display *mDisplay; + + rx::RendererD3D *mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp index 3d5bfe0cbe..0dbc30ae36 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -6,19 +6,18 @@ // DynamicHLSL.cpp: Implementation for link and run-time HLSL generation // -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/formatutils.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" #include "common/utilities.h" -#include "common/blocklayout.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/Program.h" +#include "libANGLE/Shader.h" +#include "libANGLE/formatutils.h" // For use with ArrayString, see angleutils.h -META_ASSERT(GL_INVALID_INDEX == UINT_MAX); +static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int."); using namespace gl; @@ -73,19 +72,18 @@ std::string HLSLTypeString(GLenum type) return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); } -const PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables, +const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables, unsigned int location) { for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) { if (outputVariables[variableIndex].outputIndex == location) { - return outputVariables[variableIndex]; + return &outputVariables[variableIndex]; } } - UNREACHABLE(); - return outputVariables[0]; + return NULL; } const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; @@ -100,11 +98,21 @@ DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing) { - GLenum transposedType = TransposeMatrixType(varying->type); + // Make sure we use transposed matrix types to count registers correctly. + int registers = 0; + int elements = 0; - // matrices within varying structs are not transposed - int registers = (varying->isStruct() ? HLSLVariableRegisterCount(*varying) : VariableRowCount(transposedType)) * varying->elementCount(); - int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType)); + if (varying->isStruct()) + { + registers = HLSLVariableRegisterCount(*varying, true) * varying->elementCount(); + elements = 4; + } + else + { + GLenum transposedType = TransposeMatrixType(varying->type); + registers = VariableRowCount(transposedType) * varying->elementCount(); + elements = VariableColumnCount(transposedType); + } if (elements >= 2 && elements <= 4) { @@ -342,15 +350,16 @@ std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const default: UNREACHABLE(); } - unsigned int semanticIndex = elementIndex * variableRows + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + varying.registerIndex + row; + unsigned int semanticIndex = elementIndex * variableRows + + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + + varying.registerIndex + row; std::string n = Str(semanticIndex); std::string typeString; if (varying.isStruct()) { - // matrices within structs are not transposed, so - // do not use the special struct prefix "rm" + // TODO(jmadill): pass back translated name from the shader translator typeString = decorateVariable(varying.structName); } else @@ -377,6 +386,26 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s int semanticIndex = 0; unsigned int inputIndex = 0; + // If gl_PointSize is used in the shader then pointsprites rendering is expected. + // If the renderer does not support Geometry shaders then Instanced PointSprite emulation + // must be used. + bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos; + bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + + // Instanced PointSprite emulation requires additional entries in the + // VS_INPUT structure to support the vertices that make up the quad vertices. + // These values must be in sync with the cooresponding values added during inputlayout creation + // in InputLayoutCache::applyVertexBuffers(). + // + // The additional entries must appear first in the VS_INPUT layout because + // Windows Phone 8 era devices require per vertex data to physically come + // before per instance data in the shader. + if (useInstancedPointSpriteEmulation) + { + structHLSL += " float3 spriteVertexPos : SPRITEPOSITION0;\n"; + structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; + } + for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; @@ -394,11 +423,31 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s else { GLenum componentType = mRenderer->getVertexComponentType(vertexFormat); - structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); + + if (shaderAttribute.name == "gl_InstanceID") + { + // The input type of the instance ID in HLSL (uint) differs from the one in ESSL (int). + structHLSL += " uint"; + } + else + { + structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); + } + } + + structHLSL += " " + decorateVariable(shaderAttribute.name) + " : "; + + if (shaderAttribute.name == "gl_InstanceID") + { + structHLSL += "SV_InstanceID"; + } + else + { + structHLSL += "TEXCOORD" + Str(semanticIndex); + semanticIndex += VariableRegisterCount(shaderAttribute.type); } - structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n"; - semanticIndex += VariableRegisterCount(shaderAttribute.type); + structHLSL += ";\n"; // HLSL code for initialization initHLSL += " " + decorateVariable(shaderAttribute.name) + " = "; @@ -458,12 +507,18 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string { unsigned int location = (binding - GL_COLOR_ATTACHMENT0); - const PixelShaderOutputVariable &outputVariable = GetOutputAtLocation(outputVariables, location); + const PixelShaderOutputVariable *outputVariable = FindOutputAtLocation(outputVariables, location); - declarationHLSL += " " + HLSLTypeString(outputVariable.type) + " " + outputVariable.name + - " : " + targetSemantic + Str(layoutIndex) + ";\n"; + // OpenGL ES 3.0 spec $4.2.1 + // If [...] not all user-defined output variables are written, the values of fragment colors + // corresponding to unwritten variables are similarly undefined. + if (outputVariable) + { + declarationHLSL += " " + HLSLTypeString(outputVariable->type) + " " + outputVariable->name + + " : " + targetSemantic + Str(layoutIndex) + ";\n"; - copyHLSL += " output." + outputVariable.name + " = " + outputVariable.source + ";\n"; + copyHLSL += " output." + outputVariable->name + " = " + outputVariable->source + ";\n"; + } } } @@ -543,8 +598,8 @@ struct DynamicHLSL::SemanticInfo BuiltinInfo glPointSize; }; -DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, - bool pointSize, bool pixelShader) const +DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool position, bool fragCoord, + bool pointCoord, bool pointSize, bool pixelShader) const { SemanticInfo info; bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4); @@ -565,7 +620,10 @@ DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool info.dxPosition.enableSystem("POSITION"); } - info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); + if (position) + { + info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); + } if (fragCoord) { @@ -599,10 +657,13 @@ std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const { std::string linkHLSL = "{\n"; - ASSERT(info.dxPosition.enabled && info.glPosition.enabled); - + ASSERT(info.dxPosition.enabled); linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n"; - linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; + + if (info.glPosition.enabled) + { + linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; + } if (info.glFragCoord.enabled) { @@ -614,13 +675,14 @@ std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n"; } - linkHLSL += varyingHLSL; - if (info.glPointSize.enabled) { linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n"; } + // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the same register. + linkHLSL += varyingHLSL; + linkHLSL += "};\n"; return linkHLSL; @@ -629,10 +691,11 @@ std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<LinkedVarying> *linkedVaryings) const { - ASSERT(info.glPosition.enabled); - - linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, - info.glPosition.index, 1)); + if (info.glPosition.enabled) + { + linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, + info.glPosition.index, 1)); + } if (info.glFragCoord.enabled) { @@ -690,6 +753,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, bool usesFragCoord = fragmentShader->mUsesFragCoord; bool usesPointCoord = fragmentShader->mUsesPointCoord; bool usesPointSize = vertexShader->mUsesPointSize; + bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; if (usesFragColor && usesFragData) { @@ -707,6 +771,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3); const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1); + // gl_Position only needs to be outputted from the vertex shader if transform feedback is active. + // This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from the vertex shader in this case. + // This saves us 1 output vector. + bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""); + int shaderVersion = vertexShader->getShaderVersion(); if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors) @@ -716,12 +785,29 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, } const std::string &varyingHLSL = generateVaryingHLSL(vertexShader); - const SemanticInfo &vertexSemantics = getSemanticInfo(registers, usesFragCoord, - false, usesPointSize, false); + + // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader VS_OUTPUT + // structure to ensure compatibility with the generated PS_INPUT of the pixel shader. + // GeometryShader PointSprite emulation does not require this additional entry because the + // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the PS_INPUT of the + // generated pixel shader. + // The Geometry Shader point sprite implementation needs gl_PointSize to be in VS_OUTPUT and GS_INPUT. + // Instanced point sprites doesn't need gl_PointSize in VS_OUTPUT. + const SemanticInfo &vertexSemantics = getSemanticInfo(registers, outputPositionFromVS, + usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord), + (!useInstancedPointSpriteEmulation && usesPointSize), false); storeUserLinkedVaryings(vertexShader, linkedVaryings); storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings); + // Instanced PointSprite emulation requires additional entries originally generated in the + // GeometryShader HLSL. These include pointsize clamp values. + if (useInstancedPointSpriteEmulation) + { + vertexHLSL += "static float minPointSize = " + Str((int)mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" + "static float maxPointSize = " + Str((int)mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"; + } + // Add stub string to be replaced when shader is dynamically defined by its layout vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n" "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n" @@ -729,32 +815,40 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, "{\n" " initAttributes(input);\n"; - if (shaderModel >= 4) + if (vertexShader->usesDeferredInit()) { vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position = gl_Position;\n" - " output.dx_Position.x = gl_Position.x;\n" + " initializeDeferredGlobals();\n"; + } + + vertexHLSL += "\n" + " gl_main();\n" + "\n" + " VS_OUTPUT output;\n"; + + if (outputPositionFromVS) + { + vertexHLSL += " output.gl_Position = gl_Position;\n"; + } + + // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + vertexHLSL += " output.dx_Position.x = gl_Position.x;\n" " output.dx_Position.y = -gl_Position.y;\n" " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" " output.dx_Position.w = gl_Position.w;\n"; } else { - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position = gl_Position;\n" - " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" + vertexHLSL += " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" " output.dx_Position.w = gl_Position.w;\n"; } - if (usesPointSize && shaderModel >= 3) + // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. + if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation) { vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; } @@ -797,12 +891,27 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, } } + // Instanced PointSprite emulation requires additional entries to calculate + // the final output vertex positions of the quad that represents each sprite. + if (useInstancedPointSpriteEmulation) + { + vertexHLSL += "\n" + " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n" + " output.dx_Position.xyz += float3(input.spriteVertexPos.x * gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * output.dx_Position.w;\n"; + + if (usesPointCoord) + { + vertexHLSL += "\n" + " output.gl_PointCoord = input.spriteTexCoord;\n"; + } + } + vertexHLSL += "\n" " return output;\n" "}\n"; - const SemanticInfo &pixelSemantics = getSemanticInfo(registers, usesFragCoord, usesPointCoord, - usesPointSize, true); + const SemanticInfo &pixelSemantics = getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord, + (!useInstancedPointSpriteEmulation && usesPointSize), true); pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n"; @@ -872,12 +981,14 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, { pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; - if (shaderModel >= 4) + // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader. + // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords. + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") { pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n" " gl_FragCoord.y = input.dx_Position.y;\n"; } - else if (shaderModel >= 3) + else if (shaderModel == 3) { pixelHLSL += " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; @@ -961,6 +1072,12 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, } } + if (fragmentShader->usesDeferredInit()) + { + pixelHLSL += "\n" + " initializeDeferredGlobals();\n"; + } + pixelHLSL += "\n" " gl_main();\n" "\n" @@ -1013,9 +1130,9 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragm std::string geomHLSL; - const SemanticInfo &inSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord, + const SemanticInfo &inSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, false, true, false); - const SemanticInfo &outSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord, + const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, fragmentShader->mUsesPointCoord, true, false); std::string varyingHLSL = generateVaryingHLSL(vertexShader); @@ -1028,31 +1145,31 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragm "struct GS_INPUT\n" + inLinkHLSL + "\n" + "struct GS_OUTPUT\n" + outLinkHLSL + "\n" + "\n" - "static float2 pointSpriteCorners[] = \n" - "{\n" - " float2( 0.5f, -0.5f),\n" - " float2( 0.5f, 0.5f),\n" - " float2(-0.5f, -0.5f),\n" - " float2(-0.5f, 0.5f)\n" - "};\n" - "\n" - "static float2 pointSpriteTexcoords[] = \n" - "{\n" - " float2(1.0f, 1.0f),\n" - " float2(1.0f, 0.0f),\n" - " float2(0.0f, 1.0f),\n" - " float2(0.0f, 0.0f)\n" - "};\n" - "\n" - "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" - "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n" - "\n" - "[maxvertexcount(4)]\n" - "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n" - "{\n" - " GS_OUTPUT output = (GS_OUTPUT)0;\n" - " output.gl_Position = input[0].gl_Position;\n" - " output.gl_PointSize = input[0].gl_PointSize;\n"; + "static float2 pointSpriteCorners[] = \n" + "{\n" + " float2( 0.5f, -0.5f),\n" + " float2( 0.5f, 0.5f),\n" + " float2(-0.5f, -0.5f),\n" + " float2(-0.5f, 0.5f)\n" + "};\n" + "\n" + "static float2 pointSpriteTexcoords[] = \n" + "{\n" + " float2(1.0f, 1.0f),\n" + " float2(1.0f, 0.0f),\n" + " float2(0.0f, 1.0f),\n" + " float2(0.0f, 0.0f)\n" + "};\n" + "\n" + "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" + "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n" + "\n" + "[maxvertexcount(4)]\n" + "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n" + "{\n" + " GS_OUTPUT output = (GS_OUTPUT)0;\n" + " output.gl_Position = input[0].gl_Position;\n" + " output.gl_PointSize = input[0].gl_PointSize;\n"; for (int r = 0; r < registers; r++) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h index c46bbf6ce0..26ae13b342 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -6,11 +6,11 @@ // DynamicHLSL.h: Interface for link and run-time HLSL generation // -#ifndef LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ -#define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ +#ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ +#define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ #include "common/angleutils.h" -#include "libGLESv2/Constants.h" +#include "libANGLE/Constants.h" #include "angle_gl.h" @@ -49,7 +49,7 @@ struct PixelShaderOutputVariable size_t outputIndex; }; -class DynamicHLSL +class DynamicHLSL : angle::NonCopyable { public: explicit DynamicHLSL(RendererD3D *const renderer); @@ -74,15 +74,13 @@ class DynamicHLSL void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; private: - DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); - RendererD3D *const mRenderer; struct SemanticInfo; std::string getVaryingSemantic(bool pointSize) const; - SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize, - bool pixelShader) const; + SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord, + bool pointSize, bool pixelShader) const; std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; std::string generateVaryingHLSL(const ShaderD3D *shader) const; void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const; @@ -98,4 +96,4 @@ class DynamicHLSL } -#endif // LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ +#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp new file mode 100644 index 0000000000..1a4734b269 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -0,0 +1,463 @@ +// +// Copyright 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. +// + +// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes. + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" + +namespace rx +{ + +namespace +{ + +ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) +{ + ClearParameters clearParams; + memset(&clearParams, 0, sizeof(ClearParameters)); + + const auto &blendState = state.getBlendState(); + + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = false; + } + clearParams.colorFClearValue = state.getColorClearValue(); + clearParams.colorClearType = GL_FLOAT; + clearParams.colorMaskRed = blendState.colorMaskRed; + clearParams.colorMaskGreen = blendState.colorMaskGreen; + clearParams.colorMaskBlue = blendState.colorMaskBlue; + clearParams.colorMaskAlpha = blendState.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthClearValue = state.getDepthClearValue(); + clearParams.clearStencil = false; + clearParams.stencilClearValue = state.getStencilClearValue(); + clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask; + clearParams.scissorEnabled = state.isScissorTestEnabled(); + clearParams.scissor = state.getScissor(); + + const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer(); + if (mask & GL_COLOR_BUFFER_BIT) + { + if (framebufferObject->hasEnabledColorAttachment()) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = true; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) + { + if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL) + { + clearParams.clearDepth = true; + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) + { + if (framebufferObject->getStencilbuffer() != NULL && + framebufferObject->getStencilbuffer()->getStencilSize() > 0) + { + clearParams.clearStencil = true; + } + } + + return clearParams; +} + +} + +FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer) + : FramebufferImpl(data), + mRenderer(renderer), + mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr), + mInvalidateColorAttachmentCache(true) +{ + ASSERT(mRenderer != nullptr); +} + +FramebufferD3D::~FramebufferD3D() +{ +} + +void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *) +{ + mInvalidateColorAttachmentCache = true; +} + +void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *) +{ +} + +void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *) +{ +} + +void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *) +{ +} + +void FramebufferD3D::setDrawBuffers(size_t, const GLenum *) +{ + mInvalidateColorAttachmentCache = true; +} + +void FramebufferD3D::setReadBuffer(GLenum) +{ +} + +gl::Error FramebufferD3D::invalidate(size_t, const GLenum *) +{ + // No-op in D3D + return gl::Error(GL_NO_ERROR); +} + +gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +{ + // No-op in D3D + return gl::Error(GL_NO_ERROR); +} + +gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask) +{ + const gl::State &state = *data.state; + ClearParameters clearParams = GetClearParameters(state, mask); + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +{ + // glClearBufferfv can be called to clear the color buffer or depth buffer + ClearParameters clearParams = GetClearParameters(state, 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 = gl::ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_FLOAT; + } + + if (buffer == GL_DEPTH) + { + clearParams.clearDepth = true; + clearParams.depthClearValue = values[0]; + } + + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +{ + // glClearBufferuiv can only be called to clear a color buffer + ClearParameters clearParams = GetClearParameters(state, 0); + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); + } + clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_UNSIGNED_INT; + + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +{ + // glClearBufferiv can be called to clear the color buffer or stencil buffer + ClearParameters clearParams = GetClearParameters(state, 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 = gl::ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_INT; + } + + if (buffer == GL_STENCIL) + { + clearParams.clearStencil = true; + clearParams.stencilClearValue = values[1]; + } + + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + // glClearBufferfi can only be called to clear a depth stencil buffer + ClearParameters clearParams = GetClearParameters(state, 0); + clearParams.clearDepth = true; + clearParams.depthClearValue = depth; + clearParams.clearStencil = true; + clearParams.stencilClearValue = stencil; + + return clear(state, clearParams); +} + +GLenum FramebufferD3D::getImplementationColorReadFormat() const +{ + const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + + if (readAttachment == nullptr) + { + return GL_NONE; + } + + RenderTargetD3D *attachmentRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget); + if (error.isError()) + { + return GL_NONE; + } + + GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); + const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + + return implementationFormatInfo.format; +} + +GLenum FramebufferD3D::getImplementationColorReadType() const +{ + const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + + if (readAttachment == nullptr) + { + return GL_NONE; + } + + RenderTargetD3D *attachmentRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget); + if (error.isError()) + { + return GL_NONE; + } + + GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); + const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + + return implementationFormatInfo.type; +} + +gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +{ + const gl::PixelPackState &packState = state.getPackState(); + + if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels"); + } + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0); + + return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels)); +} + +gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) +{ + bool blitRenderTarget = false; + if ((mask & GL_COLOR_BUFFER_BIT) && + sourceFramebuffer->getReadColorbuffer() != nullptr && + mData.getFirstColorAttachment() != nullptr) + { + blitRenderTarget = true; + } + + bool blitStencil = false; + if ((mask & GL_STENCIL_BUFFER_BIT) && + sourceFramebuffer->getStencilbuffer() != nullptr && + mData.mStencilAttachment != nullptr) + { + blitStencil = true; + } + + bool blitDepth = false; + if ((mask & GL_DEPTH_BUFFER_BIT) && + sourceFramebuffer->getDepthbuffer() != nullptr && + mData.mDepthAttachment != nullptr) + { + blitDepth = true; + } + + if (blitRenderTarget || blitDepth || blitStencil) + { + const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL; + gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil, + filter, sourceFramebuffer); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum FramebufferD3D::checkStatus() const +{ + // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness + for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++) + { + const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment]; + if (attachment != nullptr) + { + for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++) + { + const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment]; + if (prevAttachment != nullptr && + (attachment->id() == prevAttachment->id() && + attachment->type() == prevAttachment->type())) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + } + } + + return GL_FRAMEBUFFER_COMPLETE; +} + +const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const +{ + if (!workarounds.mrtPerfWorkaround) + { + return mData.mColorAttachments; + } + + if (!mInvalidateColorAttachmentCache) + { + return mColorAttachmentsForRender; + } + + // Does not actually free memory + mColorAttachmentsForRender.clear(); + + for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex) + { + GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex]; + gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex]; + + if (colorAttachment != nullptr && drawBufferState != GL_NONE) + { + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); + mColorAttachmentsForRender.push_back(colorAttachment); + } + } + + mInvalidateColorAttachmentCache = false; + return mColorAttachmentsForRender; +} + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT) +{ + if (attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + ASSERT(texture); + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + const gl::ImageIndex *index = attachment->getTextureImageIndex(); + ASSERT(index); + return textureD3D->getRenderTarget(*index, outRT); + } + else if (attachment->type() == GL_RENDERBUFFER) + { + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + *outRT = renderbufferD3D->getRenderTarget(); + return gl::Error(GL_NO_ERROR); + } + else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + { + const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment); + const egl::Surface *surface = defaultAttachment->getSurface(); + ASSERT(surface); + const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + ASSERT(surfaceD3D); + + if (defaultAttachment->getBinding() == GL_BACK) + { + *outRT = surfaceD3D->getSwapChain()->getColorRenderTarget(); + } + else + { + *outRT = surfaceD3D->getSwapChain()->getDepthStencilRenderTarget(); + } + return gl::Error(GL_NO_ERROR); + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } +} + +// Note: RenderTarget serials should ideally be in the RenderTargets themselves. +unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment) +{ + if (attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + ASSERT(texture); + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + const gl::ImageIndex *index = attachment->getTextureImageIndex(); + ASSERT(index); + return textureD3D->getRenderTargetSerial(*index); + } + else if (attachment->type() == GL_RENDERBUFFER) + { + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + return renderbufferD3D->getRenderTargetSerial(); + } + else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + { + const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment); + const egl::Surface *surface = defaultAttachment->getSurface(); + ASSERT(surface); + const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + ASSERT(surfaceD3D); + + if (defaultAttachment->getBinding() == GL_BACK) + { + return surfaceD3D->getSwapChain()->getColorRenderTarget()->getSerial(); + } + else + { + return surfaceD3D->getSwapChain()->getDepthStencilRenderTarget()->getSerial(); + } + } + else + { + UNREACHABLE(); + return 0; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h new file mode 100644 index 0000000000..d5d2dae8bd --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h @@ -0,0 +1,111 @@ +// +// Copyright 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. +// + +// FramebufferD3D.h: Defines the DefaultAttachmentD3D and FramebufferD3D classes. + +#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ + +#include <vector> +#include <cstdint> + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace gl +{ +class FramebufferAttachment; +struct PixelPackState; +} + +namespace rx +{ +class RenderTargetD3D; +class RendererD3D; + +struct ClearParameters +{ + bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + gl::ColorF colorFClearValue; + gl::ColorI colorIClearValue; + gl::ColorUI colorUIClearValue; + GLenum colorClearType; + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + bool clearDepth; + float depthClearValue; + + bool clearStencil; + GLint stencilClearValue; + GLuint stencilWriteMask; + + bool scissorEnabled; + gl::Rectangle scissor; +}; + +class FramebufferD3D : public FramebufferImpl +{ + public: + FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer); + virtual ~FramebufferD3D(); + + void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) override; + void setDepthAttachment(const gl::FramebufferAttachment *attachment) override; + void setStencilAttachment(const gl::FramebufferAttachment *attachment) override; + void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) override; + + void setDrawBuffers(size_t count, const GLenum *buffers) override; + void setReadBuffer(GLenum buffer) override; + + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; + + gl::Error clear(const gl::Data &data, GLbitfield mask) override; + gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override; + gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override; + gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override; + gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; + + GLenum getImplementationColorReadFormat() const override; + GLenum getImplementationColorReadType() const override; + gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const override; + + gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; + + GLenum checkStatus() const override; + + const gl::AttachmentList &getColorAttachmentsForRender(const Workarounds &workarounds) const; + + protected: + // Cache variable + mutable gl::AttachmentList mColorAttachmentsForRender; + mutable bool mInvalidateColorAttachmentCache; + + private: + RendererD3D *const mRenderer; + + virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0; + + virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, + const gl::PixelPackState &pack, uint8_t *pixels) const = 0; + + virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) = 0; + + virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0; +}; + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT); +unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment); + +} + +#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp index 776d92b202..8961a36ec5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -4,22 +4,17 @@ // found in the LICENSE file. // -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/Program.h" +#include "libANGLE/features.h" -#include "common/features.h" #include "common/utilities.h" +#include "third_party/trace_event/trace_event.h" + #ifndef QT_D3DCOMPILER_DLL #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL #endif -#ifndef D3DCOMPILE_RESERVED16 -#define D3DCOMPILE_RESERVED16 (1 << 16) -#endif -#ifndef D3DCOMPILE_RESERVED17 -#define D3DCOMPILE_RESERVED17 (1 << 17) -#endif // Definitions local to the translation unit namespace @@ -31,6 +26,15 @@ namespace #define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } +#if defined(ANGLE_MINGW32_COMPAT) +#ifndef D3DCOMPILE_RESERVED16 +#define D3DCOMPILE_RESERVED16 0x10000 +#endif +#ifndef D3DCOMPILE_RESERVED17 +#define D3DCOMPILE_RESERVED17 0x20000 +#endif +#endif + struct CompilerFlagInfo { UINT mFlag; @@ -128,6 +132,7 @@ HLSLCompiler::~HLSLCompiler() bool HLSLCompiler::initialize() { + TRACE_EVENT0("gpu", "initializeCompiler"); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. @@ -151,8 +156,6 @@ bool HLSLCompiler::initialize() defaultCompiler, L"d3dcompiler_47.dll", L"d3dcompiler_46.dll", - L"d3dcompiler_45.dll", - L"d3dcompiler_44.dll", L"d3dcompiler_43.dll", 0 }; @@ -215,7 +218,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string ASSERT(mD3DCompileFunc); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) - if (gl::perfActive()) + if (gl::DebugAnnotationsActive()) { std::string sourcePath = getTempPath(); std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); @@ -242,7 +245,11 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string TRACE("\n%s", hlsl.c_str()); TRACE("\n%s", message.c_str()); - if (message.find("error X3531:") != std::string::npos) // "can't unroll loops marked with loop attribute" + if (message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute" + message.find("error X4014:") != std::string::npos) // "cannot have gradient operations inside loops with divergent flow control", + // even though it is counter-intuitive to disable unrolling for this error, + // some very long shaders have trouble deciding which loops to unroll and + // turning off forced unrolls allows them to compile properly. { macros = NULL; // Disable [loop] and [flatten] diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h index ff56f8035a..a824952553 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h @@ -1,7 +1,7 @@ -#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ -#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ +#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ +#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include "common/angleutils.h" #include "common/platform.h" @@ -26,7 +26,7 @@ struct CompileConfig CompileConfig(UINT flags, const std::string &name); }; -class HLSLCompiler +class HLSLCompiler : angle::NonCopyable { public: HLSLCompiler(); @@ -44,8 +44,6 @@ class HLSLCompiler std::string disassembleBinary(ID3DBlob* shaderBinary) const; private: - DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); - HMODULE mD3DCompilerModule; pD3DCompile mD3DCompileFunc; pD3DDisassemble mD3DDisassembleFunc; @@ -53,4 +51,4 @@ class HLSLCompiler } -#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ +#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp new file mode 100644 index 0000000000..4e6f61150a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp @@ -0,0 +1,47 @@ +// +// Copyright (c) 2002-2015 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. +// + +// Image.h: Implements the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#include "libANGLE/renderer/d3d/ImageD3D.h" + +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ + +ImageD3D::ImageD3D() + : mWidth(0), + mHeight(0), + mDepth(0), + mInternalFormat(GL_NONE), + mTarget(GL_NONE), + mRenderable(false), + mDirty(false) +{ +} + +gl::Error ImageD3D::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) +{ + gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTargetD3D *renderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(renderTarget); + return copy(destOffset, sourceArea, renderTarget); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h new file mode 100644 index 0000000000..0fe88a8f59 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h @@ -0,0 +1,84 @@ +// +// Copyright (c) 2002-2015 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. +// + +// ImageD3D.h: Defines the rx::ImageD3D class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBANGLE_RENDERER_D3D_IMAGED3D_H_ +#define LIBANGLE_RENDERER_D3D_IMAGED3D_H_ + +#include "common/debug.h" + +#include "libANGLE/Error.h" + +namespace gl +{ +class Framebuffer; +struct ImageIndex; +struct Box; +struct Extents; +struct Offset; +struct Rectangle; +struct PixelUnpackState; +} + +namespace rx +{ +class TextureStorage; +class RendererD3D; +class RenderTargetD3D; + +class ImageD3D : angle::NonCopyable +{ + public: + ImageD3D(); + virtual ~ImageD3D() {}; + + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getTarget() const { return mTarget; } + bool isRenderableFormat() const { return mRenderable; } + + void markDirty() { mDirty = true; } + void markClean() { mDirty = false; } + virtual bool isDirty() const = 0; + + virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0; + + virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) = 0; + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0; + + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; + + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; + + gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source); + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + bool mRenderable; + GLenum mTarget; + + bool mDirty; + + private: + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp index aa614f6cc4..677b8bb240 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp @@ -7,8 +7,8 @@ // IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface // class with derivations, classes that perform graphics API agnostic index buffer operations. -#include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" namespace rx { @@ -35,9 +35,9 @@ void IndexBuffer::updateSerial() } -IndexBufferInterface::IndexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer) +IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic) { - mIndexBuffer = renderer->createIndexBuffer(); + mIndexBuffer = factory->createIndexBuffer(); mDynamic = dynamic; mWritePosition = 0; @@ -66,7 +66,7 @@ unsigned int IndexBufferInterface::getSerial() const return mIndexBuffer->getSerial(); } -gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) +gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset) { // Protect against integer overflow if (mWritePosition + size < mWritePosition) @@ -130,7 +130,8 @@ gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum in } } -StreamingIndexBufferInterface::StreamingIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, true) +StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory) + : IndexBufferInterface(factory, true) { } @@ -165,7 +166,8 @@ gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, G } -StaticIndexBufferInterface::StaticIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, false) +StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory) + : IndexBufferInterface(factory, false) { } @@ -191,9 +193,4 @@ gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLen } } -IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() -{ - return &mIndexRangeCache; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h index a34d30bbf3..36262f1d09 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h @@ -7,18 +7,18 @@ // IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface // class with derivations, classes that perform graphics API agnostic index buffer operations. -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER_H_ +#ifndef LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ +#define LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ #include "common/angleutils.h" -#include "libGLESv2/Error.h" -#include "libGLESv2/renderer/IndexRangeCache.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/IndexRangeCache.h" namespace rx { -class RendererD3D; +class BufferFactoryD3D; -class IndexBuffer +class IndexBuffer : angle::NonCopyable { public: IndexBuffer(); @@ -41,16 +41,14 @@ class IndexBuffer void updateSerial(); private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer); - unsigned int mSerial; static unsigned int mNextSerial; }; -class IndexBufferInterface +class IndexBufferInterface : angle::NonCopyable { public: - IndexBufferInterface(RendererD3D *renderer, bool dynamic); + IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic); virtual ~IndexBufferInterface(); virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0; @@ -74,11 +72,7 @@ class IndexBufferInterface gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType); private: - DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); - - RendererD3D *const mRenderer; - - IndexBuffer* mIndexBuffer; + IndexBuffer *mIndexBuffer; unsigned int mWritePosition; bool mDynamic; @@ -87,26 +81,21 @@ class IndexBufferInterface class StreamingIndexBufferInterface : public IndexBufferInterface { public: - StreamingIndexBufferInterface(RendererD3D *renderer); + explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory); ~StreamingIndexBufferInterface(); - virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); + gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; }; class StaticIndexBufferInterface : public IndexBufferInterface { public: - explicit StaticIndexBufferInterface(RendererD3D *renderer); + explicit StaticIndexBufferInterface(BufferFactoryD3D *factory); ~StaticIndexBufferInterface(); - virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); - - IndexRangeCache *getIndexRangeCache(); - - private: - IndexRangeCache mIndexRangeCache; + gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; }; } -#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ +#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp index eddd9de887..7dad269435 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -7,13 +7,11 @@ // IndexDataManager.cpp: Defines the IndexDataManager, a class that // runs the Buffer translation process for index buffers. -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/formatutils.h" namespace rx { @@ -57,10 +55,11 @@ static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void else UNREACHABLE(); } -IndexDataManager::IndexDataManager(RendererD3D *renderer) - : mRenderer(renderer), - mStreamingBufferShort(NULL), - mStreamingBufferInt(NULL) +IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) + : mFactory(factory), + mRendererClass(rendererClass), + mStreamingBufferShort(nullptr), + mStreamingBufferInt(nullptr) { } @@ -85,8 +84,10 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf { offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); - storage = BufferD3D::makeBufferD3D(buffer->getImplementation()); + storage = GetImplAs<BufferD3D>(buffer); + // We'll trust that the compiler will optimize the % below: + // the operands are unsigned and the divisor is a constant. switch (type) { case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; @@ -116,26 +117,18 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf if (directStorage) { streamOffset = offset; - - if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL)) - { - buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset); - } } else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) { indexBuffer = staticBuffer; - if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset)) - { - streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes; - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); - } + // Using bit-shift here is faster than using division. + streamOffset = (offset >> typeInfo.bytesShift) << gl::GetTypeInfo(destinationIndexType).bytesShift; } // Avoid D3D11's primitive restart index value // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx - if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3) + if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRendererClass == RENDERER_D3D11) { destinationIndexType = GL_UNSIGNED_INT; directStorage = false; @@ -159,7 +152,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf if (staticBuffer->getBufferSize() == 0 && alignedOffset) { indexBuffer = staticBuffer; - convertCount = storage->getSize() / typeInfo.bytes; + // Using bit-shift here is faster than using division. + convertCount = storage->getSize() >> typeInfo.bytesShift; } else { @@ -170,13 +164,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf ASSERT(indexBuffer); - if (convertCount > std::numeric_limits<unsigned int>::max() / destTypeInfo.bytes) + // Using bit-shift here is faster than using division. + if (convertCount > (std::numeric_limits<unsigned int>::max() >> destTypeInfo.bytesShift)) { return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", convertCount, destTypeInfo.bytes); } - unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes; + unsigned int bufferSizeRequired = convertCount << destTypeInfo.bytesShift; error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type); if (error.isError()) { @@ -209,21 +204,22 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf if (staticBuffer) { - streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes; - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); + // Using bit-shift here is faster than using division. + streamOffset = (offset >> typeInfo.bytesShift) << destTypeInfo.bytesShift; } } translated->storage = directStorage ? storage : NULL; translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / destTypeInfo.bytes; + // Using bit-shift here is faster than using division. + translated->startIndex = (streamOffset >> destTypeInfo.bytesShift); translated->startOffset = streamOffset; translated->indexType = destinationIndexType; if (storage) { - storage->promoteStaticUsage(count * typeInfo.bytes); + storage->promoteStaticUsage(count << typeInfo.bytesShift); } return gl::Error(GL_NO_ERROR); @@ -236,7 +232,7 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, { if (!mStreamingBufferInt) { - mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); + mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory); gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); if (error.isError()) { @@ -254,7 +250,7 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, if (!mStreamingBufferShort) { - mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); + mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory); gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); if (error.isError()) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h index a1aee1588b..275b3720c5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h @@ -7,14 +7,15 @@ // IndexDataManager.h: Defines the IndexDataManager, a class that // runs the Buffer translation process for index buffers. -#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ -#define LIBGLESV2_INDEXDATAMANAGER_H_ +#ifndef LIBANGLE_INDEXDATAMANAGER_H_ +#define LIBANGLE_INDEXDATAMANAGER_H_ + +#include <GLES2/gl2.h> #include "common/angleutils.h" #include "common/mathutil.h" -#include "libGLESv2/Error.h" - -#include <GLES2/gl2.h> +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" namespace { @@ -47,25 +48,23 @@ struct TranslatedIndexData unsigned int serial; }; -class IndexDataManager +class IndexDataManager : angle::NonCopyable { public: - explicit IndexDataManager(RendererD3D *renderer); + explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); virtual ~IndexDataManager(); gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); private: - gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); - - DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - - RendererD3D *const mRenderer; + gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); + BufferFactoryD3D *const mFactory; + RendererClass mRendererClass; StreamingIndexBufferInterface *mStreamingBufferShort; StreamingIndexBufferInterface *mStreamingBufferInt; }; } -#endif // LIBGLESV2_INDEXDATAMANAGER_H_ +#endif // LIBANGLE_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp index 75da78110e..9ce9a27cd3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -6,19 +6,19 @@ // ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. -#include "libGLESv2/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" -#include "common/features.h" #include "common/utilities.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/ShaderExecutable.h" -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" namespace rx { @@ -84,10 +84,12 @@ void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAtt std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars) { - std::vector<GLenum> defaultPixelOutput(1); + std::vector<GLenum> defaultPixelOutput; - ASSERT(!shaderOutputVars.empty()); - defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; + if (!shaderOutputVars.empty()) + { + defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex); + } return defaultPixelOutput; } @@ -102,11 +104,31 @@ bool IsRowMajorLayout(const sh::ShaderVariable &var) return false; } +struct AttributeSorter +{ + AttributeSorter(const ProgramImpl::SemanticIndexArray &semanticIndices) + : originalIndices(&semanticIndices) + { + } + + bool operator()(int a, int b) + { + int indexA = (*originalIndices)[a]; + int indexB = (*originalIndices)[b]; + + if (indexA == -1) return false; + if (indexB == -1) return true; + return (indexA < indexB); + } + + const ProgramImpl::SemanticIndexArray *originalIndices; +}; + } ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[], const GLenum signature[], - ShaderExecutable *shaderExecutable) + ShaderExecutableD3D *shaderExecutable) : mShaderExecutable(shaderExecutable) { for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) @@ -134,7 +156,7 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) co return true; } -ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable) +ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable) : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable) { @@ -149,20 +171,22 @@ ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureTy { } +unsigned int ProgramD3D::mCurrentSerial = 1; + ProgramD3D::ProgramD3D(RendererD3D *renderer) : ProgramImpl(), mRenderer(renderer), mDynamicHLSL(NULL), mGeometryExecutable(NULL), - mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE), - mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE), mUsesPointSize(false), mVertexUniformStorage(NULL), mFragmentUniformStorage(NULL), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), mDirtySamplerMapping(true), - mShaderVersion(100) + mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits), + mShaderVersion(100), + mSerial(issueSerial()) { mDynamicHLSL = new DynamicHLSL(renderer); } @@ -173,18 +197,6 @@ ProgramD3D::~ProgramD3D() SafeDelete(mDynamicHLSL); } -ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl)); - return static_cast<ProgramD3D*>(impl); -} - -const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl)); - return static_cast<const ProgramD3D*>(impl); -} - bool ProgramD3D::usesPointSpriteEmulation() const { return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; @@ -192,7 +204,12 @@ bool ProgramD3D::usesPointSpriteEmulation() const bool ProgramD3D::usesGeometryShader() const { - return usesPointSpriteEmulation(); + return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); +} + +bool ProgramD3D::usesInstancedPointSpriteEmulation() const +{ + return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; } GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const @@ -276,7 +293,7 @@ void ProgramD3D::updateSamplerMapping() if (targetUniform->dirty) { - if (gl::IsSampler(targetUniform->type)) + if (gl::IsSamplerType(targetUniform->type)) { int count = targetUniform->elementCount(); GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data); @@ -324,7 +341,7 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) // DrawArrays and DrawElements will issue the INVALID_OPERATION error. updateSamplerMapping(); - std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); + std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE); for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) { @@ -332,19 +349,19 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) { unsigned int unit = mSamplersPS[i].logicalTextureUnit; - if (unit >= textureUnitTypes.size()) + if (unit >= caps.maxCombinedTextureImageUnits) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits); } return false; } - if (textureUnitTypes[unit] != GL_NONE) + if (mTextureUnitTypesCache[unit] != GL_NONE) { - if (mSamplersPS[i].textureType != textureUnitTypes[unit]) + if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit]) { if (infoLog) { @@ -356,7 +373,7 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) } else { - textureUnitTypes[unit] = mSamplersPS[i].textureType; + mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType; } } } @@ -367,19 +384,19 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) { unsigned int unit = mSamplersVS[i].logicalTextureUnit; - if (unit >= textureUnitTypes.size()) + if (unit >= caps.maxCombinedTextureImageUnits) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits); } return false; } - if (textureUnitTypes[unit] != GL_NONE) + if (mTextureUnitTypesCache[unit] != GL_NONE) { - if (mSamplersVS[i].textureType != textureUnitTypes[unit]) + if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit]) { if (infoLog) { @@ -391,7 +408,7 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) } else { - textureUnitTypes[unit] = mSamplersVS[i].textureType; + mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType; } } } @@ -399,8 +416,15 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) return true; } -gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) { + int compileFlags = stream->readInt<int>(); + if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) + { + infoLog.append("Mismatched compilation flags."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + stream->readInt(&mShaderVersion); const unsigned int psSamplerCount = stream->readInt<unsigned int>(); @@ -429,7 +453,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str if (stream->error()) { infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } mUniforms.resize(uniformCount); @@ -462,7 +486,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str if (stream->error()) { infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } mUniformIndex.resize(uniformIndexCount); @@ -477,7 +501,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str if (stream->error()) { infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } mUniformBlocks.resize(uniformBlockCount); @@ -518,9 +542,9 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str } stream->readString(&mVertexHLSL); - stream->readInt(&mVertexWorkarounds); + stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); stream->readString(&mPixelHLSL); - stream->readInt(&mPixelWorkarounds); + stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); stream->readBool(&mUsesFragDepth); stream->readBool(&mUsesPointSize); @@ -553,7 +577,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str unsigned int vertexShaderSize = stream->readInt<unsigned int>(); const unsigned char *vertexShaderFunction = binary + stream->offset(); - ShaderExecutable *shaderExecutable = NULL; + ShaderExecutableD3D *shaderExecutable = NULL; gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mTransformFeedbackLinkedVaryings, @@ -561,13 +585,13 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str &shaderExecutable); if (error.isError()) { - return gl::LinkResult(false, error); + return LinkResult(false, error); } if (!shaderExecutable) { infoLog.append("Could not create vertex shader."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } // generated converted input layout @@ -592,20 +616,20 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str const size_t pixelShaderSize = stream->readInt<unsigned int>(); const unsigned char *pixelShaderFunction = binary + stream->offset(); - ShaderExecutable *shaderExecutable = NULL; + ShaderExecutableD3D *shaderExecutable = NULL; gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), &shaderExecutable); if (error.isError()) { - return gl::LinkResult(false, error); + return LinkResult(false, error); } if (!shaderExecutable) { infoLog.append("Could not create pixel shader."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } // add new binary @@ -625,13 +649,13 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str &mGeometryExecutable); if (error.isError()) { - return gl::LinkResult(false, error); + return LinkResult(false, error); } if (!mGeometryExecutable) { infoLog.append("Could not create geometry shader."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } stream->skip(geometryShaderSize); } @@ -643,16 +667,19 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0) { infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } initializeUniformStorage(); + initAttributesByLayout(); - return gl::LinkResult(true, gl::Error(GL_NO_ERROR)); + return LinkResult(true, gl::Error(GL_NO_ERROR)); } gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) { + stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); + stream->writeInt(mShaderVersion); stream->writeInt(mSamplersPS.size()); @@ -738,9 +765,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) } stream->writeString(mVertexHLSL); - stream->writeInt(mVertexWorkarounds); + stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); stream->writeString(mPixelHLSL); - stream->writeInt(mPixelWorkarounds); + stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); stream->writeInt(mUsesFragDepth); stream->writeInt(mUsesPointSize); @@ -810,11 +837,12 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) return gl::Error(GL_NO_ERROR); } -gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable) +gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable) { - std::vector<GLenum> outputs; + mPixelShaderOutputFormatCache.clear(); - const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(mRenderer->getWorkarounds()); + const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo); + const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { @@ -822,18 +850,20 @@ gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fb if (colorbuffer) { - outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); + mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); } else { - outputs.push_back(GL_NONE); + mPixelShaderOutputFormatCache.push_back(GL_NONE); } } - return getPixelExecutableForOutputLayout(outputs, outExecutable); + return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr); } -gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, ShaderExecutable **outExectuable) +gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) { for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) { @@ -848,9 +878,12 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum outputSignature); // Generate new pixel executable + ShaderExecutableD3D *pixelExecutable = NULL; + gl::InfoLog tempInfoLog; - ShaderExecutable *pixelExecutable = NULL; - gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL, + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, &pixelExecutable); @@ -859,22 +892,24 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum return error; } - if (!pixelExecutable) + if (pixelExecutable) + { + mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + } + else if (!infoLog) { 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)); - } *outExectuable = pixelExecutable; return gl::Error(GL_NO_ERROR); } -gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable) +gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) { GLenum signature[gl::MAX_VERTEX_ATTRIBS]; getInputLayoutSignature(inputLayout, signature); @@ -892,9 +927,12 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); // Generate new vertex executable + ShaderExecutableD3D *vertexExecutable = NULL; + gl::InfoLog tempInfoLog; - ShaderExecutable *vertexExecutable = NULL; - gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX, + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, &vertexExecutable); @@ -903,42 +941,42 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i return error; } - if (!vertexExecutable) + 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]); + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); } - else + else if (!infoLog) { - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, 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]); } *outExectuable = vertexExecutable; return gl::Error(GL_NO_ERROR); } -gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers) +LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers) { ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); - ShaderExecutable *defaultVertexExecutable = NULL; - gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable); + ShaderExecutableD3D *defaultVertexExecutable = NULL; + gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); if (error.isError()) { - return gl::LinkResult(false, error); + return LinkResult(false, error); } std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); - ShaderExecutable *defaultPixelExecutable = NULL; - error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable); + ShaderExecutableD3D *defaultPixelExecutable = NULL; + error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); if (error.isError()) { - return gl::LinkResult(false, error); + return LinkResult(false, error); } if (usesGeometryShader()) @@ -948,10 +986,10 @@ gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::S error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable); + D3DCompilerWorkarounds(), &mGeometryExecutable); if (error.isError()) { - return gl::LinkResult(false, error); + return LinkResult(false, error); } } @@ -977,15 +1015,15 @@ gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::S #endif bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable)); - return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); + return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); } -gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector<std::string> &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, - std::map<int, gl::VariableLocation> *outputVariables) +LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector<std::string> &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, + std::map<int, gl::VariableLocation> *outputVariables) { ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); @@ -996,10 +1034,10 @@ gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, mTransformFeedbackBufferMode = transformFeedbackBufferMode; mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); - mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds(); + fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); mVertexHLSL = vertexShaderD3D->getTranslatedSource(); - mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds(); + vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); mShaderVersion = vertexShaderD3D->getShaderVersion(); // Map the varyings to the register file @@ -1008,24 +1046,26 @@ gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, if (*registers < 0) { - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } - if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader)) + if (!gl::Program::linkVaryings(infoLog, fragmentShader, vertexShader)) { - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) { - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + return LinkResult(false, gl::Error(GL_NO_ERROR)); } mUsesPointSize = vertexShaderD3D->usesPointSize(); - return gl::LinkResult(true, gl::Error(GL_NO_ERROR)); + initAttributesByLayout(); + + return LinkResult(true, gl::Error(GL_NO_ERROR)); } void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const @@ -1042,7 +1082,7 @@ void ProgramD3D::initializeUniformStorage() { const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - if (!gl::IsSampler(uniform.type)) + if (!gl::IsSamplerType(uniform.type)) { if (uniform.isReferencedByVertexShader()) { @@ -1077,12 +1117,20 @@ gl::Error ProgramD3D::applyUniforms() return gl::Error(GL_NO_ERROR); } -gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps) +gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) { - ASSERT(boundBuffers.size() == mUniformBlocks.size()); + GLint vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLint fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; - const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; - const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; + for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; ++registerIndex) + { + vertexUniformBuffers[registerIndex] = -1; + } + + for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; ++registerIndex) + { + fragmentUniformBuffers[registerIndex] = -1; + } const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); @@ -1090,15 +1138,9 @@ gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBu for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) { gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex]; - gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; + GLuint blockBinding = uniformBlockBindings[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."); - } + ASSERT(uniformBlock); // Unnecessary to apply an unreferenced standard or shared UBO if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) @@ -1109,21 +1151,21 @@ gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBu if (uniformBlock->isReferencedByVertexShader()) { unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; - ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxVertexUniformBlocks); - vertexUniformBuffers[registerIndex] = uniformBuffer; + ASSERT(vertexUniformBuffers[registerIndex] == -1); + ASSERT(registerIndex < data.caps->maxVertexUniformBlocks); + vertexUniformBuffers[registerIndex] = blockBinding; } if (uniformBlock->isReferencedByFragmentShader()) { unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; - ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxFragmentUniformBlocks); - fragmentUniformBuffers[registerIndex] = uniformBuffer; + ASSERT(fragmentUniformBuffers[registerIndex] == -1); + ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks); + fragmentUniformBuffers[registerIndex] = blockBinding; } } - return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); + return mRenderer->setUniformBuffers(data, vertexUniformBuffers, fragmentUniformBuffers); } bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, @@ -1308,7 +1350,7 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad { const sh::Uniform &vertexUniform = *entry->second; const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!gl::ProgramBinary::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) + if (!gl::Program::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) { return false; } @@ -1321,7 +1363,7 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad if (uniform.staticUse) { - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); + defineUniformBase(vertexShaderD3D, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); } } @@ -1331,7 +1373,7 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad if (uniform.staticUse) { - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + defineUniformBase(fragmentShaderD3D, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); } } @@ -1355,17 +1397,17 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad return true; } -void ProgramD3D::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) +void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister) { - ShShaderOutput outputType = ShaderD3D::getCompilerOutputType(shader); + ShShaderOutput outputType = shader->getCompilerOutputType(); sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); encoder.skipRegisters(uniformRegister); defineUniform(shader, uniform, uniform.name, &encoder); } -void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, - const std::string &fullName, sh::HLSLBlockEncoder *encoder) +void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, + const std::string &fullName, sh::HLSLBlockEncoder *encoder) { if (uniform.isStruct()) { @@ -1396,30 +1438,28 @@ void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, gl::LinkedUniform *linkedUniform = getUniformByName(fullName); + // Advance the uniform offset, to track registers allocation for structs + sh::BlockMemberInfo blockInfo = encoder->encodeType(uniform.type, uniform.arraySize, false); + if (!linkedUniform) { linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, - -1, sh::BlockMemberInfo::getDefaultBlockInfo()); + -1, sh::BlockMemberInfo::getDefaultBlockInfo()); ASSERT(linkedUniform); - linkedUniform->registerElement = encoder->getCurrentElement(); + linkedUniform->registerElement = sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo); mUniforms.push_back(linkedUniform); } - ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); - - if (shader == GL_FRAGMENT_SHADER) + if (shader->getShaderType() == GL_FRAGMENT_SHADER) { - linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); + linkedUniform->psRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo); } - else if (shader == GL_VERTEX_SHADER) + else if (shader->getShaderType() == GL_VERTEX_SHADER) { - linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); + linkedUniform->vsRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo); } 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()) { @@ -1488,7 +1528,7 @@ void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum ta } } } - else if (gl::IsSampler(targetUniform->type)) + else if (gl::IsSamplerType(targetUniform->type)) { ASSERT(targetUniformType == GL_INT); @@ -1824,7 +1864,7 @@ bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex, bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps) { - ASSERT(gl::IsSampler(uniform.type)); + ASSERT(gl::IsSamplerType(uniform.type)); ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); if (uniform.vsRegisterIndex != GL_INVALID_INDEX) @@ -1874,7 +1914,7 @@ bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) { const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - if (gl::IsSampler(uniform.type)) + if (gl::IsSamplerType(uniform.type)) { if (!indexSamplerUniform(uniform, infoLog, caps)) { @@ -1902,11 +1942,11 @@ void ProgramD3D::reset() mTransformFeedbackBufferMode = GL_NONE; mVertexHLSL.clear(); - mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE; + mVertexWorkarounds.reset(); mShaderVersion = 100; mPixelHLSL.clear(); - mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE; + mPixelWorkarounds.reset(); mUsesFragDepth = false; mPixelShaderKey.clear(); mUsesPointSize = false; @@ -1920,6 +1960,46 @@ void ProgramD3D::reset() mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; mDirtySamplerMapping = true; + + std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1); +} + +unsigned int ProgramD3D::getSerial() const +{ + return mSerial; +} + +unsigned int ProgramD3D::issueSerial() +{ + return mCurrentSerial++; +} + +void ProgramD3D::initAttributesByLayout() +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAttributesByLayout[i] = i; + } + + std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex)); +} + +void ProgramD3D::sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const +{ + rx::TranslatedAttribute oldTranslatedAttributes[gl::MAX_VERTEX_ATTRIBS]; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + oldTranslatedAttributes[i] = attributes[i]; + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + int oldIndex = mAttributesByLayout[i]; + sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; + attributes[i] = oldTranslatedAttributes[oldIndex]; + } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h index 4baab9aa19..6f3eade81d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -6,11 +6,14 @@ // ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. -#ifndef LIBGLESV2_RENDERER_PROGRAMD3D_H_ -#define LIBGLESV2_RENDERER_PROGRAMD3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ +#define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ -#include "libGLESv2/renderer/ProgramImpl.h" -#include "libGLESv2/renderer/Workarounds.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/Constants.h" +#include "libANGLE/renderer/ProgramImpl.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" #include <string> #include <vector> @@ -25,7 +28,14 @@ struct VertexFormat; namespace rx { class RendererD3D; -class UniformStorage; +class UniformStorageD3D; +class ShaderExecutableD3D; + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. +// It should only be used selectively to work around specific bugs. +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 +#endif class ProgramD3D : public ProgramImpl { @@ -33,9 +43,6 @@ class ProgramD3D : public ProgramImpl ProgramD3D(RendererD3D *renderer); virtual ~ProgramD3D(); - static ProgramD3D *makeProgramD3D(ProgramImpl *impl); - static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl); - const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; } int getShaderVersion() const { return mShaderVersion; } GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } @@ -49,31 +56,32 @@ class ProgramD3D : public ProgramImpl bool usesPointSize() const { return mUsesPointSize; } bool usesPointSpriteEmulation() const; bool usesGeometryShader() const; + bool usesInstancedPointSpriteEmulation() const; GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } - gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); + LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); gl::Error save(gl::BinaryOutputStream *stream); - gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable); - gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutable **outExectuable); - gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable); - ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; } + gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable); + gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); + gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); + ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; } - gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers); + LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers); - gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector<std::string> &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, - std::map<int, gl::VariableLocation> *outputVariables); + LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector<std::string> &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector<gl::LinkedVarying> *linkedVaryings, + std::map<int, gl::VariableLocation> *outputVariables); void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; void initializeUniformStorage(); gl::Error applyUniforms(); - gl::Error applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps); + gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) override; bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const gl::Caps &caps); void dirtyAllUniforms(); @@ -104,8 +112,8 @@ class ProgramD3D : public ProgramImpl void getUniformiv(GLint location, GLint *params); void getUniformuiv(GLint location, GLuint *params); - const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } - const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; } + const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, const gl::Caps &caps); @@ -113,43 +121,47 @@ class ProgramD3D : public ProgramImpl void reset(); - private: - DISALLOW_COPY_AND_ASSIGN(ProgramD3D); + unsigned int getSerial() const; + void initAttributesByLayout(); + void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const; + + private: class VertexExecutable { public: VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], const GLenum signature[gl::MAX_VERTEX_ATTRIBS], - ShaderExecutable *shaderExecutable); + ShaderExecutableD3D *shaderExecutable); ~VertexExecutable(); bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const; const gl::VertexFormat *inputs() const { return mInputs; } const GLenum *signature() const { return mSignature; } - ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } private: gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS]; GLenum mSignature[gl::MAX_VERTEX_ATTRIBS]; - ShaderExecutable *mShaderExecutable; + ShaderExecutableD3D *mShaderExecutable; }; class PixelExecutable { public: - PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable); + PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable); ~PixelExecutable(); bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; } const std::vector<GLenum> &outputSignature() const { return mOutputSignature; } - ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } private: std::vector<GLenum> mOutputSignature; - ShaderExecutable *mShaderExecutable; + ShaderExecutableD3D *mShaderExecutable; }; struct Sampler @@ -161,8 +173,8 @@ class ProgramD3D : public ProgramImpl GLenum textureType; }; - void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, + void defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister); + void defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps); bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); @@ -188,20 +200,20 @@ class ProgramD3D : public ProgramImpl std::vector<VertexExecutable *> mVertexExecutables; std::vector<PixelExecutable *> mPixelExecutables; - ShaderExecutable *mGeometryExecutable; + ShaderExecutableD3D *mGeometryExecutable; std::string mVertexHLSL; - D3DWorkaroundType mVertexWorkarounds; + D3DCompilerWorkarounds mVertexWorkarounds; std::string mPixelHLSL; - D3DWorkaroundType mPixelWorkarounds; + D3DCompilerWorkarounds mPixelWorkarounds; bool mUsesFragDepth; std::vector<PixelShaderOutputVariable> mPixelShaderKey; bool mUsesPointSize; - UniformStorage *mVertexUniformStorage; - UniformStorage *mFragmentUniformStorage; + UniformStorageD3D *mVertexUniformStorage; + UniformStorageD3D *mFragmentUniformStorage; GLenum mTransformFeedbackBufferMode; @@ -211,9 +223,22 @@ class ProgramD3D : public ProgramImpl GLuint mUsedPixelSamplerRange; bool mDirtySamplerMapping; + // Cache for validateSamplers + std::vector<GLenum> mTextureUnitTypesCache; + + // Cache for getPixelExecutableForFramebuffer + std::vector<GLenum> mPixelShaderOutputFormatCache; + int mShaderVersion; + + int mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS]; + + unsigned int mSerial; + + static unsigned int issueSerial(); + static unsigned int mCurrentSerial; }; } -#endif // LIBGLESV2_RENDERER_PROGRAMD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp new file mode 100644 index 0000000000..84b30aa106 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012-2015 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. +// + +// RenderTargetD3D.cpp: Implements serial handling for rx::RenderTargetD3D + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +unsigned int RenderTargetD3D::mCurrentSerial = 1; + +RenderTargetD3D::RenderTargetD3D() + : mSerial(issueSerials(1)) +{ +} + +RenderTargetD3D::~RenderTargetD3D() +{ +} + +unsigned int RenderTargetD3D::getSerial() const +{ + return mSerial; +} + +unsigned int RenderTargetD3D::issueSerials(unsigned int count) +{ + unsigned int firstSerial = mCurrentSerial; + mCurrentSerial += count; + return firstSerial; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h new file mode 100644 index 0000000000..fe6afcecae --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2012-2015 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. +// + +// RenderTargetD3D.h: Defines an abstract wrapper class to manage IDirect3DSurface9 +// and ID3D11View objects belonging to renderbuffers and renderable textures. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" + +namespace rx +{ + +class RenderTargetD3D : angle::NonCopyable +{ + public: + RenderTargetD3D(); + virtual ~RenderTargetD3D(); + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLsizei getDepth() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLsizei getSamples() const = 0; + gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } + + virtual unsigned int getSerial() const; + static unsigned int issueSerials(unsigned int count); + + private: + const unsigned int mSerial; + static unsigned int mCurrentSerial; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp index cb4af367a2..c91fedff06 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp @@ -7,10 +7,10 @@ // RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" namespace rx { @@ -30,7 +30,12 @@ RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbu return static_cast<RenderbufferD3D*>(renderbuffer); } -gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) +gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height) +{ + return setStorageMultisample(0, internalformat, width, height); +} + +gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) { // If the renderbuffer parameters are queried, the calling function // will expect one of the valid renderbuffer formats for use in @@ -42,7 +47,7 @@ gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum inte creationFormat = GL_DEPTH24_STENCIL8_OES; } - RenderTarget *newRT = NULL; + RenderTargetD3D *newRT = NULL; gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT); if (error.isError()) { @@ -55,47 +60,7 @@ gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum inte return gl::Error(GL_NO_ERROR); } -gl::Error RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth) -{ - RenderTarget *newRT = NULL; - gl::Error error = mRenderer->createRenderTarget(swapChain, depth, &newRT); - if (error.isError()) - { - return error; - } - - SafeDelete(mRenderTarget); - mRenderTarget = newRT; - - return gl::Error(GL_NO_ERROR); -} - -GLsizei RenderbufferD3D::getWidth() const -{ - return (mRenderTarget ? mRenderTarget->getWidth() : 0); -} - -GLsizei RenderbufferD3D::getHeight() const -{ - return (mRenderTarget ? mRenderTarget->getHeight() : 0); -} - -GLenum RenderbufferD3D::getInternalFormat() const -{ - return (mRenderTarget ? mRenderTarget->getInternalFormat() : GL_RGBA4); -} - -GLenum RenderbufferD3D::getActualFormat() const -{ - return (mRenderTarget ? mRenderTarget->getActualFormat() : GL_RGBA4); -} - -GLsizei RenderbufferD3D::getSamples() const -{ - return (mRenderTarget ? mRenderTarget->getSamples() : 0); -} - -RenderTarget *RenderbufferD3D::getRenderTarget() +RenderTargetD3D *RenderbufferD3D::getRenderTarget() { return mRenderTarget; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h new file mode 100644 index 0000000000..4c4b998683 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h @@ -0,0 +1,43 @@ +// +// 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. +// + +// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ + +#include "angle_gl.h" + +#include "common/angleutils.h" +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace rx +{ +class RendererD3D; +class RenderTargetD3D; +class SwapChainD3D; + +class RenderbufferD3D : public RenderbufferImpl +{ + public: + RenderbufferD3D(RendererD3D *renderer); + virtual ~RenderbufferD3D(); + + static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); + + virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; + virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override; + + RenderTargetD3D *getRenderTarget(); + unsigned int getRenderTargetSerial() const; + + private: + RendererD3D *mRenderer; + RenderTargetD3D *mRenderTarget; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp new file mode 100644 index 0000000000..2ce0ce5a1b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -0,0 +1,628 @@ +// +// 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. +// + +// RendererD3D.cpp: Implementation of the base D3D Renderer. + +#include "libANGLE/renderer/d3d/RendererD3D.h" + +#include "common/MemoryBuffer.h" +#include "common/utilities.h" +#include "libANGLE/Display.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/DisplayD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" + +namespace rx +{ + +namespace +{ +// If we request a scratch buffer requesting a smaller size this many times, +// release and recreate the scratch buffer. This ensures we don't have a +// degenerate case where we are stuck hogging memory. +const int ScratchMemoryBufferLifetime = 1000; +} + +RendererD3D::RendererD3D(egl::Display *display) + : mDisplay(display), + mDeviceLost(false), + mScratchMemoryBufferResetCounter(0) +{ +} + +RendererD3D::~RendererD3D() +{ + cleanup(); +} + +void RendererD3D::cleanup() +{ + mScratchMemoryBuffer.resize(0); + for (auto it = mIncompleteTextures.begin(); it != mIncompleteTextures.end(); ++it) + { + it->second.set(NULL); + } + mIncompleteTextures.clear(); +} + +// static +RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer)); + return static_cast<RendererD3D*>(renderer); +} + +gl::Error RendererD3D::drawElements(const gl::Data &data, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) +{ + if (data.state->isPrimitiveRestartEnabled()) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented"); + } + + gl::Program *program = data.state->getProgram(); + ASSERT(program != NULL); + + program->updateSamplerMapping(); + + gl::Error error = generateSwizzles(data); + if (error.isError()) + { + return error; + } + + if (!applyPrimitiveType(mode, count, program->usesPointSize())) + { + return gl::Error(GL_NO_ERROR); + } + + error = applyRenderTarget(data, mode, false); + if (error.isError()) + { + return error; + } + + error = applyState(data, mode); + if (error.isError()) + { + return error; + } + + gl::VertexArray *vao = data.state->getVertexArray(); + TranslatedIndexData indexInfo; + indexInfo.indexRange = indexRange; + error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); + if (error.isError()) + { + return error; + } + + applyTransformFeedbackBuffers(*data.state); + // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation + // layer. + ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); + + GLsizei vertexCount = indexInfo.indexRange.length() + 1; + error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances); + if (error.isError()) + { + return error; + } + + error = applyShaders(data); + if (error.isError()) + { + return error; + } + + error = applyTextures(data); + if (error.isError()) + { + return error; + } + + error = program->applyUniformBuffers(data); + if (error.isError()) + { + return error; + } + + if (!skipDraw(data, mode)) + { + error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::drawArrays(const gl::Data &data, + GLenum mode, GLint first, + GLsizei count, GLsizei instances) +{ + gl::Program *program = data.state->getProgram(); + ASSERT(program != NULL); + + program->updateSamplerMapping(); + + gl::Error error = generateSwizzles(data); + if (error.isError()) + { + return error; + } + + if (!applyPrimitiveType(mode, count, program->usesPointSize())) + { + return gl::Error(GL_NO_ERROR); + } + + error = applyRenderTarget(data, mode, false); + if (error.isError()) + { + return error; + } + + error = applyState(data, mode); + if (error.isError()) + { + return error; + } + + applyTransformFeedbackBuffers(*data.state); + + error = applyVertexBuffer(*data.state, mode, first, count, instances); + if (error.isError()) + { + return error; + } + + error = applyShaders(data); + if (error.isError()) + { + return error; + } + + error = applyTextures(data); + if (error.isError()) + { + return error; + } + + error = program->applyUniformBuffers(data); + if (error.isError()) + { + return error; + } + + if (!skipDraw(data, mode)) + { + error = drawArrays(data, mode, count, instances, program->usesPointSize()); + if (error.isError()) + { + return error; + } + + if (data.state->isTransformFeedbackActiveUnpaused()) + { + markTransformFeedbackUsage(data); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) +{ + gl::Program *program = data.state->getProgram(); + + size_t samplerRange = program->getUsedSamplerRange(type); + + for (size_t i = 0; i < samplerRange; i++) + { + GLenum textureType = program->getSamplerTextureType(type, i); + GLint textureUnit = program->getSamplerMapping(type, i, *data.caps); + if (textureUnit != -1) + { + gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + if (texture->getSamplerState().swizzleRequired()) + { + gl::Error error = generateSwizzle(texture); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::generateSwizzles(const gl::Data &data) +{ + gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX); + if (error.isError()) + { + return error; + } + + error = generateSwizzles(data, gl::SAMPLER_PIXEL); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +// Applies the render target surface, depth stencil surface, viewport rectangle and +// scissor rectangle to the renderer +gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) +{ + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); + + gl::Error error = applyRenderTarget(framebufferObject); + if (error.isError()) + { + return error; + } + + float nearZ, farZ; + data.state->getDepthRange(&nearZ, &farZ); + setViewport(data.state->getViewport(), nearZ, farZ, drawMode, + data.state->getRasterizerState().frontFace, ignoreViewport); + + setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); + + return gl::Error(GL_NO_ERROR); +} + +// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device +gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) +{ + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + int samples = framebufferObject->getSamples(data); + + gl::RasterizerState rasterizer = data.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + gl::Error error = setRasterizerState(rasterizer); + if (error.isError()) + { + return error; + } + + unsigned int mask = 0; + if (data.state->isSampleCoverageEnabled()) + { + GLclampf coverageValue; + bool coverageInvert = false; + data.state->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 = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); + if (error.isError()) + { + return error; + } + + error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), + data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +// Applies the shaders and shader constants to the Direct3D device +gl::Error RendererD3D::applyShaders(const gl::Data &data) +{ + gl::Program *program = data.state->getProgram(); + + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + gl::VertexFormat::GetInputLayout(inputLayout, program, *data.state); + + const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); + + gl::Error error = applyShaders(program, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused()); + if (error.isError()) + { + return error; + } + + return program->applyUniforms(); +} + +// 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). +gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) +{ + gl::Program *program = data.state->getProgram(); + + size_t samplerRange = program->getUsedSamplerRange(shaderType); + for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLenum textureType = program->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = program->getSamplerMapping(shaderType, samplerIndex, *data.caps); + if (textureUnit != -1) + { + gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + gl::SamplerState sampler = texture->getSamplerState(); + + gl::Sampler *samplerObject = data.state->getSampler(textureUnit); + if (samplerObject) + { + samplerObject->getState(&sampler); + } + + // TODO: std::binary_search may become unavailable using older versions of GCC + if (texture->isSamplerComplete(sampler, data) && + !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) + { + gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler); + if (error.isError()) + { + return error; + } + + error = 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. + gl::Texture *incompleteTexture = getIncompleteTexture(textureType); + gl::Error error = 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 + gl::Error error = setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits + : data.caps->maxVertexTextureImageUnits; + for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) + { + gl::Error error = setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::applyTextures(const gl::Data &data) +{ + FramebufferTextureSerialArray framebufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials); + + gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +bool RendererD3D::skipDraw(const gl::Data &data, 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 (!data.state->getProgram()->usesPointSize() && !data.state->isTransformFeedbackActiveUnpaused()) + { + // 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 (gl::IsTriangleMode(drawMode)) + { + if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK) + { + return true; + } + } + + return false; +} + +void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) +{ + for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) + { + gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); + if (buffer) + { + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); + bufferD3D->markTransformFeedbackUsage(); + } + } +} + +size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data, + FramebufferTextureSerialArray *outSerialArray) +{ + size_t serialCount = 0; + + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); + for (unsigned int i = 0; i < data.caps->maxColorAttachments; i++) + { + gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + if (attachment && attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + (*outSerialArray)[serialCount++] = texture->getTextureSerial(); + } + } + + gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE) + { + gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture(); + (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); + } + + std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); + + return serialCount; +} + +gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) +{ + if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) + { + const GLubyte color[] = { 0, 0, 0, 255 }; + const gl::Extents colorSize(1, 1, 1); + const gl::PixelUnpackState incompleteUnpackState(1, 0); + + gl::Texture* t = new gl::Texture(createTexture(type), gl::Texture::INCOMPLETE_TEXTURE_ID, type); + + if (type == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) + { + t->setImage(face, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + } + } + else + { + t->setImage(type, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + } + + mIncompleteTextures[type].set(t); + } + + return mIncompleteTextures[type].get(); +} + +bool RendererD3D::isDeviceLost() const +{ + return mDeviceLost; +} + +void RendererD3D::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +std::string RendererD3D::getVendorString() const +{ + LUID adapterLuid = { 0 }; + + if (getLUID(&adapterLuid)) + { + char adapterLuidString[64]; + sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + return std::string(adapterLuidString); + } + + return std::string(""); +} + +gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut) +{ + if (mScratchMemoryBuffer.size() == requestedSize) + { + mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; + *bufferOut = &mScratchMemoryBuffer; + return gl::Error(GL_NO_ERROR); + } + + if (mScratchMemoryBuffer.size() > requestedSize) + { + mScratchMemoryBufferResetCounter--; + } + + if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize) + { + mScratchMemoryBuffer.resize(0); + if (!mScratchMemoryBuffer.resize(requestedSize)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + } + mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; + } + + ASSERT(mScratchMemoryBuffer.size() >= requestedSize); + + *bufferOut = &mScratchMemoryBuffer; + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h index a2f778763c..3de6c20886 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h @@ -6,15 +6,23 @@ // RendererD3D.h: Defines a back-end specific class for the DirectX renderer. -#ifndef LIBGLESV2_RENDERER_RENDERERD3D_H_ -#define LIBGLESV2_RENDERER_RENDERERD3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Data.h" +#include "common/MemoryBuffer.h" +#include "libANGLE/Data.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" //FIXME(jmadill): std::array is currently prohibited by Chromium style guide #include <array> +namespace egl +{ +class ConfigSet; +} + namespace gl { class InfoLog; @@ -24,24 +32,55 @@ class Texture; namespace rx { -class TextureStorage; -class VertexBuffer; +class ImageD3D; class IndexBuffer; -class ShaderExecutable; -class SwapChain; -class RenderTarget; -class Image; +class RenderTargetD3D; +class ShaderExecutableD3D; +class SwapChainD3D; class TextureStorage; -class UniformStorage; +class UniformStorageD3D; +class VertexBuffer; + +enum ShaderType +{ + SHADER_VERTEX, + SHADER_PIXEL, + SHADER_GEOMETRY +}; + +enum RendererClass +{ + RENDERER_D3D11, + RENDERER_D3D9, +}; + +// Useful for unit testing +class BufferFactoryD3D +{ + public: + BufferFactoryD3D() {} + virtual ~BufferFactoryD3D() {} + + virtual VertexBuffer *createVertexBuffer() = 0; + virtual IndexBuffer *createIndexBuffer() = 0; + + // TODO(jmadill): add VertexFormatCaps + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; +}; -class RendererD3D : public Renderer +class RendererD3D : public Renderer, public BufferFactoryD3D { public: explicit RendererD3D(egl::Display *display); virtual ~RendererD3D(); + virtual egl::Error initialize() = 0; + static RendererD3D *makeRendererD3D(Renderer *renderer); + virtual egl::ConfigSet generateConfigs() const = 0; + gl::Error drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count, GLsizei instances) override; @@ -51,28 +90,24 @@ class RendererD3D : public Renderer const GLvoid *indices, GLsizei instances, const RangeUI &indexRange) override; - gl::Error clear(const gl::Data &data, GLbitfield mask) override; - gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLfloat *values) override; - gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLuint *values) override; - gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLint *values) override; - gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; - - gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) override; + bool isDeviceLost() const override; + std::string getVendorString() const override; - gl::Error blitFramebuffer(const gl::Data &data, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) override; + virtual int getMinorShaderModel() const = 0; + virtual std::string getShaderModelSuffix() const = 0; // Direct3D Specific methods - virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + virtual GUID getAdapterIdentifier() const = 0; + + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0; virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; + virtual gl::Error setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) = 0; virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, @@ -85,11 +120,11 @@ class RendererD3D : public Renderer bool ignoreViewport) = 0; virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive) = 0; virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0; - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0; + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0; + virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) = 0; virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; @@ -102,71 +137,66 @@ class RendererD3D : public Renderer virtual bool getShareHandleSupport() const = 0; virtual bool getPostSubBufferSupport() const = 0; + virtual int getMajorShaderModel() const = 0; + // Pixel operations - virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0; - virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0; - virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; - virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; - - virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0; + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0; + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; // RenderTarget creation - virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0; - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0; + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0; // Shader operations - virtual void releaseShaderCompiler() = 0; virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0; + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0; virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable) = 0; - virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) = 0; + virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; // Image operations - virtual Image *createImage() = 0; - virtual gl::Error generateMipmap(Image *dest, Image *source) = 0; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0; - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0; + virtual ImageD3D *createImage() = 0; + virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0; + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0; + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0; virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; + // Device lost + void notifyDeviceLost() override; + virtual bool resetDevice() = 0; - virtual VertexBuffer *createVertexBuffer() = 0; - virtual IndexBuffer *createIndexBuffer() = 0; + virtual RendererClass getRendererClass() const = 0; + + gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut); protected: - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0; + virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) = 0; virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; - virtual gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, - const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) = 0; + + virtual bool getLUID(LUID *adapterLuid) const = 0; void cleanup(); egl::Display *mDisplay; + bool mDeviceLost; private: - DISALLOW_COPY_AND_ASSIGN(RendererD3D); - //FIXME(jmadill): std::array is currently prohibited by Chromium style guide typedef std::array<unsigned int, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray; @@ -175,12 +205,10 @@ class RendererD3D : public Renderer gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); gl::Error applyState(const gl::Data &data, GLenum drawMode); - bool applyTransformFeedbackBuffers(const gl::Data &data); - gl::Error applyShaders(const gl::Data &data, bool transformFeedbackActive); + gl::Error applyShaders(const gl::Data &data); gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount); gl::Error applyTextures(const gl::Data &data); - gl::Error applyUniformBuffers(const gl::Data &data); bool skipDraw(const gl::Data &data, GLenum drawMode); void markTransformFeedbackUsage(const gl::Data &data); @@ -190,8 +218,24 @@ class RendererD3D : public Renderer gl::Texture *getIncompleteTexture(GLenum type); gl::TextureMap mIncompleteTextures; + MemoryBuffer mScratchMemoryBuffer; + unsigned int mScratchMemoryBufferResetCounter; +}; + +struct dx_VertexConstants +{ + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; +}; + +struct dx_PixelConstants +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; }; } -#endif // LIBGLESV2_RENDERER_RENDERERD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp index 8a97579e16..7d522a95d4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -6,12 +6,13 @@ // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. -#include "libGLESv2/Shader.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/features.h" -#include "common/features.h" #include "common/utilities.h" // Definitions local to the translation unit @@ -57,9 +58,6 @@ void FilterInactiveVariables(std::vector<VarT> *variableList) } } -void *ShaderD3D::mFragmentCompiler = NULL; -void *ShaderD3D::mVertexCompiler = NULL; - template <typename VarT> const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList) { @@ -67,13 +65,11 @@ const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableLis return variableList; } -ShaderD3D::ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer) - : mType(type), - mRenderer(renderer), +ShaderD3D::ShaderD3D(GLenum type) + : mShaderType(type), mShaderVersion(100) { uncompile(); - initializeCompiler(data); } ShaderD3D::~ShaderD3D() @@ -94,67 +90,13 @@ const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl) std::string ShaderD3D::getDebugInfo() const { - return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mType) + " SHADER END\n"; + return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mShaderType) + " SHADER END\n"; } -// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) -void ShaderD3D::initializeCompiler(const gl::Data &data) -{ - if (!mFragmentCompiler) - { - bool result = ShInitialize(); - if (result) - { - ShShaderSpec specVersion = (data.clientVersion >= 3) ? SH_GLES3_SPEC : SH_GLES2_SPEC; - ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; - - ShBuiltInResources resources; - ShInitBuiltInResources(&resources); - - const gl::Caps &caps = *data.caps; - const gl::Extensions &extensions = *data.extensions; - - resources.MaxVertexAttribs = caps.maxVertexAttributes; - resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; - resources.MaxVaryingVectors = caps.maxVaryingVectors; - resources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; - resources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; - resources.MaxTextureImageUnits = caps.maxTextureImageUnits; - resources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; - resources.MaxDrawBuffers = caps.maxDrawBuffers; - resources.OES_standard_derivatives = extensions.standardDerivatives; - resources.EXT_draw_buffers = extensions.drawBuffers; - resources.EXT_shader_texture_lod = 1; - // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. - resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp - resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output - // GLSL ES 3.0 constants - resources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; - resources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; - resources.MinProgramTexelOffset = caps.minProgramTexelOffset; - resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; - - mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, specVersion, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, specVersion, hlslVersion, &resources); - } - } -} - -void ShaderD3D::releaseCompiler() +void ShaderD3D::parseVaryings(ShHandle compiler) { - ShDestruct(mFragmentCompiler); - ShDestruct(mVertexCompiler); - - mFragmentCompiler = NULL; - mVertexCompiler = NULL; - - ShFinalize(); -} - -void ShaderD3D::parseVaryings(void *compiler) -{ - if (!mHlsl.empty()) + if (!mTranslatedSource.empty()) { const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler); ASSERT(varyings); @@ -164,17 +106,19 @@ void ShaderD3D::parseVaryings(void *compiler) mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex])); } - mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos; - mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos; - mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos; - mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos; - mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos; - mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos; - mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos; - mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos; - mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos; - mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; - mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; + mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos; + mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos; + mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos; + mUsesFragCoord = mTranslatedSource.find("GL_USES_FRAG_COORD") != std::string::npos; + mUsesFrontFacing = mTranslatedSource.find("GL_USES_FRONT_FACING") != std::string::npos; + mUsesPointSize = mTranslatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; + mUsesPointCoord = mTranslatedSource.find("GL_USES_POINT_COORD") != std::string::npos; + mUsesDepthRange = mTranslatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; + mUsesFragDepth = mTranslatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; + mUsesDiscardRewriting = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; + mUsesNestedBreak = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; + mUsesDeferredInit = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos; + mRequiresIEEEStrictCompiling = mTranslatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; } } @@ -190,7 +134,8 @@ void ShaderD3D::resetVaryingsRegisterAssignment() void ShaderD3D::uncompile() { // set by compileToHLSL - mHlsl.clear(); + mCompilerOutputType = SH_ESSL_OUTPUT; + mTranslatedSource.clear(); mInfoLog.clear(); mUsesMultipleRenderTargets = false; @@ -205,6 +150,8 @@ void ShaderD3D::uncompile() mShaderVersion = 100; mUsesDiscardRewriting = false; mUsesNestedBreak = false; + mUsesDeferredInit = false; + mRequiresIEEEStrictCompiling = false; mVaryings.clear(); mUniforms.clear(); @@ -214,16 +161,13 @@ void ShaderD3D::uncompile() mDebugInfo.clear(); } -void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::string &source) +void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source) { - // ensure the compiler is loaded - initializeCompiler(data); - int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); std::string sourcePath; #if !defined (ANGLE_ENABLE_WINDOWS_STORE) - if (gl::perfActive()) + if (gl::DebugAnnotationsActive()) { sourcePath = getTempPath(); writeFile(sourcePath.c_str(), source.c_str(), source.length()); @@ -254,14 +198,9 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s mShaderVersion = ShGetShaderVersion(compiler); - if (mShaderVersion == 300 && data.clientVersion < 3) - { - mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; - TRACE("\n%s", mInfoLog.c_str()); - } - else if (result) + if (result) { - mHlsl = ShGetObjectCode(compiler); + mTranslatedSource = ShGetObjectCode(compiler); #ifdef _DEBUG // Prefix hlsl shader with commented out glsl shader @@ -281,8 +220,8 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); } hlslStream << "\n\n"; - hlslStream << mHlsl; - mHlsl = hlslStream.str(); + hlslStream << mTranslatedSource; + mTranslatedSource = hlslStream.str(); #endif mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); @@ -293,10 +232,10 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s if (uniform.staticUse) { - unsigned int index = -1; - bool result = ShGetUniformRegister(compiler, uniform.name, &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); + unsigned int index = static_cast<unsigned int>(-1); + bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index); + UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult); + ASSERT(getUniformRegisterResult); mUniformRegisterMap[uniform.name] = index; } @@ -310,10 +249,10 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s if (interfaceBlock.staticUse) { - unsigned int index = -1; - bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); + unsigned int index = static_cast<unsigned int>(-1); + bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); + UNUSED_ASSERTION_VARIABLE(blockRegisterResult); + ASSERT(blockRegisterResult); mInterfaceBlockRegisterMap[interfaceBlock.name] = index; } @@ -327,24 +266,27 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s } } -D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const +void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const { if (mUsesDiscardRewriting) { // ANGLE issue 486: // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - return ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; + workarounds->skipOptimization = true; } - - if (mUsesNestedBreak) + else if (mUsesNestedBreak) { // ANGLE issue 603: // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence - return ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; + workarounds->useMaxOptimization = true; } - return ANGLE_D3D_WORKAROUND_NONE; + if (mRequiresIEEEStrictCompiling) + { + // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work. + workarounds->enableIEEEStrictness = true; + } } // true if varying x has a higher priority in packing than y @@ -381,62 +323,48 @@ unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) return mInterfaceBlockRegisterMap.find(blockName)->second; } -void *ShaderD3D::getCompiler() +GLenum ShaderD3D::getShaderType() const { - if (mType == GL_VERTEX_SHADER) - { - return mVertexCompiler; - } - else - { - ASSERT(mType == GL_FRAGMENT_SHADER); - return mFragmentCompiler; - } + return mShaderType; } -ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader) +ShShaderOutput ShaderD3D::getCompilerOutputType() const { - void *compiler = NULL; - - switch (shader) - { - case GL_VERTEX_SHADER: compiler = mVertexCompiler; break; - case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break; - default: UNREACHABLE(); return SH_HLSL9_OUTPUT; - } - - return ShGetShaderOutputType(compiler); + return mCompilerOutputType; } -bool ShaderD3D::compile(const gl::Data &data, const std::string &source) +bool ShaderD3D::compile(gl::Compiler *compiler, const std::string &source) { uncompile(); - void *compiler = getCompiler(); + CompilerD3D *compilerD3D = CompilerD3D::makeCompilerD3D(compiler->getImplementation()); + ShHandle compilerHandle = compilerD3D->getCompilerHandle(mShaderType); + + mCompilerOutputType = ShGetShaderOutputType(compilerHandle); - compileToHLSL(data, compiler, source); + compileToHLSL(compilerHandle, source); - if (mType == GL_VERTEX_SHADER) + if (mShaderType == GL_VERTEX_SHADER) { - parseAttributes(compiler); + parseAttributes(compilerHandle); } - parseVaryings(compiler); + parseVaryings(compilerHandle); - if (mType == GL_FRAGMENT_SHADER) + if (mShaderType == GL_FRAGMENT_SHADER) { std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); const std::string &hlsl = getTranslatedSource(); if (!hlsl.empty()) { - mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compiler)); + mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compilerHandle)); FilterInactiveVariables(&mActiveOutputVariables); } } #if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - mDebugInfo += std::string("// ") + GetShaderTypeString(mType) + " SHADER BEGIN\n"; + mDebugInfo += std::string("// ") + GetShaderTypeString(mShaderType) + " SHADER BEGIN\n"; mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n"; mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n"; // Successive steps will append more info @@ -447,7 +375,7 @@ bool ShaderD3D::compile(const gl::Data &data, const std::string &source) return !getTranslatedSource().empty(); } -void ShaderD3D::parseAttributes(void *compiler) +void ShaderD3D::parseAttributes(ShHandle compiler) { const std::string &hlsl = getTranslatedSource(); if (!hlsl.empty()) @@ -457,25 +385,4 @@ void ShaderD3D::parseAttributes(void *compiler) } } -int ShaderD3D::getSemanticIndex(const std::string &attributeName) const -{ - if (!attributeName.empty()) - { - int semanticIndex = 0; - for (size_t attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) - { - const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex]; - - if (attribute.name == attributeName) - { - return semanticIndex; - } - - semanticIndex += gl::VariableRegisterCount(attribute.type); - } - } - - return -1; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h index 3c9aac2c12..d0237b5985 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -6,12 +6,12 @@ // ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. -#ifndef LIBGLESV2_RENDERER_SHADERD3D_H_ -#define LIBGLESV2_RENDERER_SHADERD3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_SHADERD3D_H_ +#define LIBANGLE_RENDERER_D3D_SHADERD3D_H_ -#include "libGLESv2/renderer/ShaderImpl.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/Shader.h" +#include "libANGLE/renderer/ShaderImpl.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/Shader.h" #include <map> @@ -25,15 +25,13 @@ class ShaderD3D : public ShaderImpl friend class DynamicHLSL; public: - ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer); + ShaderD3D(GLenum type); virtual ~ShaderD3D(); static ShaderD3D *makeShaderD3D(ShaderImpl *impl); static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); // ShaderImpl implementation - virtual const std::string &getInfoLog() const { return mInfoLog; } - virtual const std::string &getTranslatedSource() const { return mHlsl; } virtual std::string getDebugInfo() const; // D3D-specific methods @@ -41,36 +39,28 @@ class ShaderD3D : public ShaderImpl void resetVaryingsRegisterAssignment(); unsigned int getUniformRegister(const std::string &uniformName) const; unsigned int getInterfaceBlockRegister(const std::string &blockName) const; - int getSemanticIndex(const std::string &attributeName) const; void appendDebugInfo(const std::string &info) { mDebugInfo += info; } - D3DWorkaroundType getD3DWorkarounds() const; + void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const; int getShaderVersion() const { return mShaderVersion; } bool usesDepthRange() const { return mUsesDepthRange; } bool usesPointSize() const { return mUsesPointSize; } + bool usesDeferredInit() const { return mUsesDeferredInit; } - static void releaseCompiler(); - static ShShaderOutput getCompilerOutputType(GLenum shader); + GLenum getShaderType() const; + ShShaderOutput getCompilerOutputType() const; - virtual bool compile(const gl::Data &data, const std::string &source); + virtual bool compile(gl::Compiler *compiler, const std::string &source); private: - DISALLOW_COPY_AND_ASSIGN(ShaderD3D); + void compileToHLSL(ShHandle compiler, const std::string &source); + void parseVaryings(ShHandle compiler); - void compileToHLSL(const gl::Data &data, void *compiler, const std::string &source); - void parseVaryings(void *compiler); - - void initializeCompiler(const gl::Data &data); - void parseAttributes(void *compiler); - void *getCompiler(); + void parseAttributes(ShHandle compiler); static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y); - static void *mFragmentCompiler; - static void *mVertexCompiler; - - GLenum mType; - RendererD3D *mRenderer; + GLenum mShaderType; int mShaderVersion; @@ -85,9 +75,10 @@ class ShaderD3D : public ShaderImpl bool mUsesFragDepth; bool mUsesDiscardRewriting; bool mUsesNestedBreak; + bool mUsesDeferredInit; + bool mRequiresIEEEStrictCompiling; - std::string mHlsl; - std::string mInfoLog; + ShShaderOutput mCompilerOutputType; std::string mDebugInfo; std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, unsigned int> mInterfaceBlockRegisterMap; @@ -95,4 +86,4 @@ class ShaderD3D : public ShaderImpl } -#endif // LIBGLESV2_RENDERER_SHADERD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp new file mode 100644 index 0000000000..97ffdf5094 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012-2015 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. +// + +// ShaderExecutable.cpp: Implements a class to contain D3D shader executable +// implementation details. + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +#include "common/angleutils.h" + +namespace rx +{ + +ShaderExecutableD3D::ShaderExecutableD3D(const void *function, size_t length) + : mFunctionBuffer(length) +{ + memcpy(mFunctionBuffer.data(), function, length); +} + +ShaderExecutableD3D::~ShaderExecutableD3D() +{ +} + +const uint8_t *ShaderExecutableD3D::getFunction() const +{ + return mFunctionBuffer.data(); +} + +size_t ShaderExecutableD3D::getLength() const +{ + return mFunctionBuffer.size(); +} + +const std::string &ShaderExecutableD3D::getDebugInfo() const +{ + return mDebugInfo; +} + +void ShaderExecutableD3D::appendDebugInfo(const std::string &info) +{ + mDebugInfo += info; +} + + +UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize) +{ +} + +UniformStorageD3D::~UniformStorageD3D() +{ +} + +size_t UniformStorageD3D::size() const +{ + return mSize; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h new file mode 100644 index 0000000000..71b83b7954 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2012-2015 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. +// + +// ShaderExecutable.h: Defines a class to contain D3D shader executable +// implementation details. + +#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ +#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ + +#include "common/debug.h" + +#include <vector> +#include <cstdint> + +namespace rx +{ + +class ShaderExecutableD3D : angle::NonCopyable +{ + public: + ShaderExecutableD3D(const void *function, size_t length); + virtual ~ShaderExecutableD3D(); + + const uint8_t *getFunction() const; + + size_t getLength() const; + + const std::string &getDebugInfo() const; + + void appendDebugInfo(const std::string &info); + + private: + std::vector<uint8_t> mFunctionBuffer; + std::string mDebugInfo; +}; + +class UniformStorageD3D : angle::NonCopyable +{ + public: + UniformStorageD3D(size_t initialSize); + virtual ~UniformStorageD3D(); + + size_t size() const; + + private: + size_t mSize; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp new file mode 100644 index 0000000000..4fde295443 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -0,0 +1,396 @@ +// +// 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. +// + +// SurfaceD3D.cpp: D3D implementation of an EGL surface + +#include "libANGLE/renderer/d3d/SurfaceD3D.h" + +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" + +#include <tchar.h> +#include <EGL/eglext.h> +#include <algorithm> + +namespace rx +{ + +SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle, + EGLint width, EGLint height) +{ + return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, shareHandle, NULL); +} + +SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window, + EGLint fixedSize, EGLint width, EGLint height) +{ + return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast<EGLClientBuffer>(0), window); +} + +SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, EGLint fixedSize, + EGLClientBuffer shareHandle, EGLNativeWindowType window) + : SurfaceImpl(), + mRenderer(renderer), + mDisplay(display), + mFixedSize(fixedSize == EGL_TRUE), + mRenderTargetFormat(config->renderTargetFormat), + mDepthStencilFormat(config->depthStencilFormat), + mSwapChain(nullptr), + mSwapIntervalDirty(true), + mWindowSubclassed(false), + mNativeWindow(window), + mWidth(width), + mHeight(height), + mSwapInterval(1), + mShareHandle(reinterpret_cast<HANDLE*>(shareHandle)) +{ + subclassWindow(); +} + +SurfaceD3D::~SurfaceD3D() +{ + unsubclassWindow(); + releaseSwapChain(); +} + +void SurfaceD3D::releaseSwapChain() +{ + SafeDelete(mSwapChain); +} + +egl::Error SurfaceD3D::initialize() +{ + if (mNativeWindow.getNativeWindow()) + { + if (!mNativeWindow.initialize()) + { + return egl::Error(EGL_BAD_SURFACE); + } + } + + egl::Error error = resetSwapChain(); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::bindTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::releaseTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain() +{ + ASSERT(!mSwapChain); + + int width; + int height; + + if (!mFixedSize) + { + RECT windowRect; + if (!mNativeWindow.getClientRect(&windowRect)) + { + ASSERT(false); + + return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); + } + + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; + } + else + { + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; + } + + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat); + if (!mSwapChain) + { + return egl::Error(EGL_BAD_ALLOC); + } + + egl::Error error = resetSwapChain(width, height); + if (error.isError()) + { + SafeDelete(mSwapChain); + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::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 (status == EGL_CONTEXT_LOST) + { + mDisplay->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapIntervalDirty = false; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return egl::Error(EGL_SUCCESS); + } + + if (x + width > mWidth) + { + width = mWidth - x; + } + + if (y + height > mHeight) + { + height = mHeight - y; + } + + if (width == 0 || height == 0) + { + return egl::Error(EGL_SUCCESS); + } + + EGLint status = mSwapChain->swapRect(x, y, width, height); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + checkForOutOfDateSwapChain(); + + return egl::Error(EGL_SUCCESS); +} + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") +#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") + +static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_SIZE) + { + SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty)); + if(surf) + { + surf->checkForOutOfDateSwapChain(); + } + } + WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); +} +#endif + +void SurfaceD3D::subclassWindow() +{ +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + + DWORD processId; + DWORD threadId = GetWindowThreadProcessId(window, &processId); + if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) + { + return; + } + + SetLastError(0); + LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) + { + mWindowSubclassed = false; + return; + } + + SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); + SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); + mWindowSubclassed = true; +#endif +} + +void SurfaceD3D::unsubclassWindow() +{ + 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(window, kParentWndProc)); + + // Check the windowproc is still SurfaceWindowProc. + // If this assert fails, then it is likely the application has subclassed the + // hwnd as well and did not unsubclass before destroying its EGL context. The + // application should be modified to either subclass before initializing the + // EGL context, or to unsubclass before destroying the EGL context. + if(parentWndFunc) + { + LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); + UNUSED_ASSERTION_VARIABLE(prevWndFunc); + ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); + } + + RemoveProp(window, kSurfaceProperty); + RemoveProp(window, kParentWndProc); +#endif + mWindowSubclassed = false; +} + +bool SurfaceD3D::checkForOutOfDateSwapChain() +{ + RECT client; + int clientWidth = getWidth(); + int clientHeight = getHeight(); + bool sizeDirty = false; + if (!mFixedSize && !mNativeWindow.isIconic()) + { + // 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 (!mNativeWindow.getClientRect(&client)) + { + ASSERT(false); + return false; + } + + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + clientWidth = client.right - client.left; + clientHeight = client.bottom - client.top; + sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + } + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + + if (mSwapIntervalDirty) + { + resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + return wasDirty; +} + +egl::Error SurfaceD3D::swap() +{ + return swapRect(0, 0, mWidth, mHeight); +} + +egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return swapRect(x, y, width, height); +} + +rx::SwapChainD3D *SurfaceD3D::getSwapChain() const +{ + return mSwapChain; +} + +void SurfaceD3D::setSwapInterval(EGLint interval) +{ + if (mSwapInterval == interval) + { + return; + } + + mSwapInterval = interval; + mSwapIntervalDirty = true; +} + +EGLint SurfaceD3D::getWidth() const +{ + return mWidth; +} + +EGLint SurfaceD3D::getHeight() const +{ + return mHeight; +} + +EGLint SurfaceD3D::isPostSubBufferSupported() const +{ + // post sub buffer is always possible on D3D surfaces + return EGL_TRUE; +} + +egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT); + if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + *value = mSwapChain->getShareHandle(); + else if (attribute == EGL_DEVICE_EXT) + *value = mSwapChain->getDevice(); + return egl::Error(EGL_SUCCESS); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h new file mode 100644 index 0000000000..070b7cdbc4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -0,0 +1,92 @@ +// +// 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. +// + +// SurfaceD3D.h: D3D implementation of an EGL surface + +#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_ +#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_ + +#include "libANGLE/renderer/SurfaceImpl.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" + +namespace egl +{ +class Surface; +} + +namespace rx +{ +class SwapChainD3D; +class RendererD3D; + +class SurfaceD3D : public SurfaceImpl +{ + public: + static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, + EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height); + static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, + EGLClientBuffer shareHandle, EGLint width, EGLint height); + ~SurfaceD3D() override; + void releaseSwapChain(); + + egl::Error initialize() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + + // D3D implementations + SwapChainD3D *getSwapChain() const; + + egl::Error resetSwapChain(); + + // Returns true if swapchain changed due to resize or interval update + bool checkForOutOfDateSwapChain(); + + private: + SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, + EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window); + + egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight); + egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight); + + void subclassWindow(); + void unsubclassWindow(); + + RendererD3D *mRenderer; + egl::Display *mDisplay; + + bool mFixedSize; + + GLenum mRenderTargetFormat; + GLenum mDepthStencilFormat; + + SwapChainD3D *mSwapChain; + bool mSwapIntervalDirty; + bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking + + NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. + EGLint mWidth; + EGLint mHeight; + + EGLint mSwapInterval; + + HANDLE mShareHandle; +}; + + +} + +#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h index 1417e0bdf6..da36e52ea7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h @@ -4,18 +4,20 @@ // found in the LICENSE file. // -// SwapChain.h: Defines a back-end specific class that hides the details of the +// SwapChainD3D.h: Defines a back-end specific class that hides the details of the // implementation-specific swapchain. -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN_H_ +#ifndef LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ +#define LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ + +#include <GLES2/gl2.h> +#include <EGL/egl.h> #include "common/angleutils.h" -#include "common/NativeWindow.h" #include "common/platform.h" -#include <GLES2/gl2.h> -#include <EGL/egl.h> +// TODO: move out of D3D11 +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" #if !defined(ANGLE_FORCE_VSYNC_OFF) #define ANGLE_FORCE_VSYNC_OFF 0 @@ -23,26 +25,31 @@ namespace rx { +class RenderTargetD3D; -class SwapChain +class SwapChainD3D : angle::NonCopyable { public: - SwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + SwapChainD3D(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) : mNativeWindow(nativeWindow), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) { } - virtual ~SwapChain() {}; + virtual ~SwapChainD3D() {}; virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; virtual void recreate() = 0; + virtual void *getDevice() { return NULL; } + + virtual RenderTargetD3D *getColorRenderTarget() = 0; + virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0; GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; } GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; } - virtual HANDLE getShareHandle() {return mShareHandle;}; + HANDLE getShareHandle() { return mShareHandle; } protected: rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. @@ -53,4 +60,4 @@ class SwapChain }; } -#endif // LIBGLESV2_RENDERER_SWAPCHAIN_H_ +#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp index 4a67701fdf..78b03f2283 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -6,23 +6,23 @@ // TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/BufferImpl.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" -#include "libGLESv2/renderer/d3d/ImageD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" - -#include "libEGL/Surface.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" #include "common/mathutil.h" #include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Config.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" namespace rx { @@ -30,7 +30,8 @@ namespace rx namespace { -gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixels, const uint8_t **pointerOut) +gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset, const uint8_t **pointerOut) { if (unpack.pixelBuffer.id() != 0) { @@ -40,7 +41,7 @@ gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixel // TODO: this is the only place outside of renderer that asks for a buffers raw data. // This functionality should be moved into renderer and the getData method of BufferImpl removed. - BufferD3D *bufferD3D = BufferD3D::makeBufferD3D(pixelBuffer->getImplementation()); + BufferD3D *bufferD3D = GetImplAs<BufferD3D>(pixelBuffer); ASSERT(bufferD3D); const uint8_t *bufferData = NULL; gl::Error error = bufferD3D->getData(&bufferData); @@ -53,7 +54,13 @@ gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixel } else { - *pointerOut = static_cast<const uint8_t *>(pixels); + *pointerOut = pixels; + } + + // Offset the pointer for 2D array layer (if it's valid) + if (*pointerOut != nullptr) + { + *pointerOut += layerOffset; } return gl::Error(GL_NO_ERROR); @@ -79,40 +86,45 @@ TextureD3D::~TextureD3D() { } -TextureD3D *TextureD3D::makeTextureD3D(TextureImpl *texture) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureD3D*, texture)); - return static_cast<TextureD3D*>(texture); -} - -TextureStorage *TextureD3D::getNativeTexture() +gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage) { // ensure the underlying texture is created - initializeStorage(false); + gl::Error error = initializeStorage(false); + if (error.isError()) + { + return error; + } if (mTexStorage) { - updateStorage(); + error = updateStorage(); + if (error.isError()) + { + return error; + } } - return mTexStorage; + ASSERT(outStorage); + + *outStorage = mTexStorage; + return gl::Error(GL_NO_ERROR); } GLint TextureD3D::getBaseLevelWidth() const { - const Image *baseImage = getBaseLevelImage(); + const ImageD3D *baseImage = getBaseLevelImage(); return (baseImage ? baseImage->getWidth() : 0); } GLint TextureD3D::getBaseLevelHeight() const { - const Image *baseImage = getBaseLevelImage(); + const ImageD3D *baseImage = getBaseLevelImage(); return (baseImage ? baseImage->getHeight() : 0); } GLint TextureD3D::getBaseLevelDepth() const { - const Image *baseImage = getBaseLevelImage(); + const ImageD3D *baseImage = getBaseLevelImage(); return (baseImage ? baseImage->getDepth() : 0); } @@ -121,11 +133,11 @@ GLint TextureD3D::getBaseLevelDepth() const // the base level image for anything except querying texture format and size. GLenum TextureD3D::getBaseLevelInternalFormat() const { - const Image *baseImage = getBaseLevelImage(); + const ImageD3D *baseImage = getBaseLevelImage(); return (baseImage ? baseImage->getInternalFormat() : GL_NONE); } -bool TextureD3D::shouldUseSetData(const Image *image) const +bool TextureD3D::shouldUseSetData(const ImageD3D *image) const { if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload) { @@ -145,9 +157,17 @@ bool TextureD3D::shouldUseSetData(const Image *image) const return (mTexStorage && !internalFormat.compressed); } -gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index) +gl::Error TextureD3D::setImage(const gl::ImageIndex &index, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset) { - Image *image = getImage(index); + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + + ImageD3D *image = getImage(index); ASSERT(image); // No-op @@ -159,7 +179,7 @@ gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); if (error.isError()) { return error; @@ -167,15 +187,14 @@ gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, if (pixelData != NULL) { - gl::Error error(GL_NO_ERROR); - if (shouldUseSetData(image)) { error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData); } else { - error = image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + error = image->loadData(fullImageArea, unpack, type, pixelData); } if (error.isError()) @@ -189,12 +208,12 @@ gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index) +gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) { // CPU readback & copy where direct GPU copy is not supported const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); if (error.isError()) { return error; @@ -202,23 +221,21 @@ gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsi if (pixelData != NULL) { - Image *image = getImage(index); + ImageD3D *image = getImage(index); ASSERT(image); - gl::Box region(xoffset, yoffset, zoffset, width, height, depth); if (shouldUseSetData(image)) { - return mTexStorage->setData(index, image, ®ion, type, unpack, pixelData); + return mTexStorage->setData(index, image, &area, type, unpack, pixelData); } - gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, - type, pixelData); + error = image->loadData(area, unpack, type, pixelData); if (error.isError()) { return error; } - error = commitRegion(index, region); + error = commitRegion(index, area); if (error.isError()) { return error; @@ -230,12 +247,19 @@ gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsi return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image) +gl::Error TextureD3D::setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, + const uint8_t *pixels, ptrdiff_t layerOffset) { + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); if (error.isError()) { return error; @@ -243,7 +267,11 @@ gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLs if (pixelData != NULL) { - gl::Error error = image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixelData); + ImageD3D *image = getImage(index); + ASSERT(image); + + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + error = image->loadCompressedData(fullImageArea, pixelData); if (error.isError()) { return error; @@ -255,11 +283,18 @@ gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLs return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image) +gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset) { + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); if (error.isError()) { return error; @@ -267,7 +302,10 @@ gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zof if (pixelData != NULL) { - gl::Error error = image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixelData); + ImageD3D *image = getImage(index); + ASSERT(image); + + error = image->loadCompressedData(area, pixelData); if (error.isError()) { return error; @@ -284,8 +322,8 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); } -gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) +gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget) { // No-op if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) @@ -333,7 +371,7 @@ TextureStorage *TextureD3D::getStorage() return mTexStorage; } -Image *TextureD3D::getBaseLevelImage() const +ImageD3D *TextureD3D::getBaseLevelImage() const { return getImage(getImageIndex(0, 0)); } @@ -347,6 +385,23 @@ gl::Error TextureD3D::generateMipmaps() return gl::Error(GL_NO_ERROR); // no-op } + if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // Switch to using the mipmapped texture. + TextureStorage *textureStorage = NULL; + gl::Error error = getNativeTexture(&textureStorage); + if (error.isError()) + { + return error; + } + + error = textureStorage->useLevelZeroWorkaroundTexture(false); + if (error.isError()) + { + return error; + } + } + // Set up proper mipmap chain in our Image array. initMipmapsImages(); @@ -365,9 +420,10 @@ gl::Error TextureD3D::generateMipmaps() { gl::ImageIndex srcIndex = getImageIndex(0, layer); - Image *image = getImage(srcIndex); - gl::Rectangle area(0, 0, image->getWidth(), image->getHeight()); - gl::Error error = image->copy(0, 0, 0, area, srcIndex, mTexStorage); + ImageD3D *image = getImage(srcIndex); + gl::Box area(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + gl::Offset offset(0, 0, 0); + gl::Error error = image->copy(offset, area, srcIndex, mTexStorage); if (error.isError()) { return error; @@ -384,7 +440,12 @@ gl::Error TextureD3D::generateMipmaps() } } - bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget()); + // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to zeroMaxLodWorkaround. + // The restriction is because Feature Level 9_3 can't create SRVs on individual levels of the texture. + // As a result, even if the storage is a rendertarget, we can't use the GPU to generate the mipmaps without further work. + // The D3D9 renderer works around this by copying each level of the texture into its own single-layer GPU texture (in Blit9::boxFilter). + // Feature Level 9_3 could do something similar, or it could continue to use CPU-side mipmap generation, or something else. + bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() && !(mRenderer->getWorkarounds().zeroMaxLodWorkaround)); for (GLint layer = 0; layer < layerCount; ++layer) { @@ -416,19 +477,24 @@ gl::Error TextureD3D::generateMipmaps() } } + if (mTexStorage) + { + updateStorage(); + } + return gl::Error(GL_NO_ERROR); } bool TextureD3D::isBaseImageZeroSize() const { - Image *baseImage = getBaseLevelImage(); + ImageD3D *baseImage = getBaseLevelImage(); if (!baseImage || baseImage->getWidth() <= 0) { return true; } - if (!gl::IsCubemapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0) + if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0) { return true; } @@ -487,7 +553,7 @@ gl::Error TextureD3D::ensureRenderTarget() bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const { - Image *image = getImage(index); + ImageD3D *image = getImage(index); bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0))); return (image->isRenderableFormat() && levelsComplete); } @@ -497,9 +563,8 @@ gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &r if (mTexStorage) { ASSERT(isValidIndex(index)); - Image *image = getImage(index); - ImageD3D *imageD3D = ImageD3D::makeImageD3D(image); - gl::Error error = imageD3D->copyToStorage(mTexStorage, index, region); + ImageD3D *image = getImage(index); + gl::Error error = image->copyToStorage(mTexStorage, index, region); if (error.isError()) { return error; @@ -516,7 +581,7 @@ TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer) { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) { - mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + mImageArray[i] = renderer->createImage(); } } @@ -533,14 +598,14 @@ TextureD3D_2D::~TextureD3D_2D() SafeDelete(mTexStorage); } -Image *TextureD3D_2D::getImage(int level, int layer) const +ImageD3D *TextureD3D_2D::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(layer == 0); return mImageArray[level]; } -Image *TextureD3D_2D::getImage(const gl::ImageIndex &index) const +ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const { ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(!index.hasLayer()); @@ -578,30 +643,21 @@ GLenum TextureD3D_2D::getInternalFormat(GLint level) const return GL_NONE; } -GLenum TextureD3D_2D::getActualFormat(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getActualFormat(); - else - return GL_NONE; -} - bool TextureD3D_2D::isDepth(GLint level) const { return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) +gl::Error TextureD3D_2D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(target == GL_TEXTURE_2D && depth == 1); + ASSERT(target == GL_TEXTURE_2D && size.depth == 1); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); bool fastUnpacked = false; - redefineImage(level, sizedInternalFormat, width, height); + redefineImage(level, sizedInternalFormat, size); gl::ImageIndex index = gl::ImageIndex::Make2D(level); @@ -609,7 +665,7 @@ gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLs if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) { // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = NULL; + RenderTargetD3D *destRenderTarget = NULL; gl::Error error = getRenderTarget(index, &destRenderTarget); if (error.isError()) { @@ -632,7 +688,7 @@ gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLs if (!fastUnpacked) { - gl::Error error = TextureD3D::setImage(unpack, type, pixels, index); + gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0); if (error.isError()) { return error; @@ -642,89 +698,80 @@ gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLs return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(target == GL_TEXTURE_2D && depth == 1); + ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height); - - return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]); -} - -gl::Error TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); - - bool fastUnpacked = false; + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } gl::ImageIndex index = gl::ImageIndex::Make2D(level); - gl::Box destArea(xoffset, yoffset, 0, width, height, 1); if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) { - RenderTarget *renderTarget = NULL; + RenderTargetD3D *renderTarget = NULL; gl::Error error = getRenderTarget(index, &renderTarget); if (error.isError()) { return error; } - error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget); - if (error.isError()) - { - return error; - } - - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); + ASSERT(!mImageArray[level]->isDirty()); - fastUnpacked = true; + return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget); } - - if (!fastUnpacked) + else { - return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, - unpack, pixels, index); + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); } +} - return gl::Error(GL_NO_ERROR); + +gl::Error TextureD3D_2D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && size.depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + return TextureD3D::setCompressedImage(gl::ImageIndex::Make2D(level), unpack, pixels, 0); } -gl::Error TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); + ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[level]); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); if (error.isError()) { return error; } - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - gl::Box region(xoffset, yoffset, 0, width, height, 1); - return commitRegion(index, region); + return commitRegion(index, area); } -gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, - gl::Framebuffer *source) +gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); - redefineImage(level, sizedInternalFormat, width, height); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1)); - gl::Rectangle sourceRect(x, y, width, height); gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Offset destOffset(0, 0, 0); - if (!canCreateRenderTargetForImage(index)) + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[level]->copy(0, 0, 0, sourceRect, source); + gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -742,9 +789,9 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GL mImageArray[level]->markClean(); - if (width != 0 && height != 0 && isValidLevel(level)) + if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level)) { - gl::Error error = mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level); + error = mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset, mTexStorage, level); if (error.isError()) { return error; @@ -755,20 +802,21 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GL return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) { - ASSERT(target == GL_TEXTURE_2D && zoffset == 0); + ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0); // can only make our texture storage to a render target if level 0 is defined (with a width & height) and // the current level we're copying to is defined (with appropriate format, width & height) - gl::Rectangle sourceRect(x, y, width, height); gl::ImageIndex index = gl::ImageIndex::Make2D(level); - if (!canCreateRenderTargetForImage(index)) + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[level]->copy(xoffset, yoffset, 0, sourceRect, source); + gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -792,9 +840,9 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, return error; } - error = mRenderer->copyImage2D(source, sourceRect, + error = mRenderer->copyImage2D(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, mTexStorage, level); + destOffset, mTexStorage, level); if (error.isError()) { return error; @@ -805,25 +853,26 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) { - ASSERT(target == GL_TEXTURE_2D && depth == 1); + ASSERT(GL_TEXTURE_2D && size.depth == 1); - for (int level = 0; level < levels; level++) + for (size_t level = 0; level < levels; level++) { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true); + gl::Extents levelSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + 1); + mImageArray[level]->redefine(GL_TEXTURE_2D, internalFormat, levelSize, true); } for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + mImageArray[level]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true); } // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels); + TextureStorage *storage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width, size.height, levels, false); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -832,6 +881,13 @@ gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalf return error; } + error = updateStorage(); + + if (error.isError()) + { + return error; + } + mImmutable = true; return gl::Error(GL_NO_ERROR); @@ -839,16 +895,20 @@ gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalf void TextureD3D_2D::bindTexImage(egl::Surface *surface) { - GLenum internalformat = surface->getFormat(); + GLenum internalformat = surface->getConfig()->renderTargetFormat; - mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true); + gl::Extents size(surface->getWidth(), surface->getHeight(), 1); + mImageArray[0]->redefine(GL_TEXTURE_2D, internalformat, size, true); if (mTexStorage) { SafeDelete(mTexStorage); } - mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain()); + SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface); + ASSERT(surfaceD3D); + + mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain()); mDirtyImages = true; } @@ -862,7 +922,7 @@ void TextureD3D_2D::releaseTexImage() for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + mImageArray[i]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true); } } @@ -872,9 +932,11 @@ void TextureD3D_2D::initMipmapsImages() int levelCount = mipLevels(); for (int level = 1; level < levelCount; level++) { - redefineImage(level, getBaseLevelInternalFormat(), - std::max(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1)); + gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1), + 1); + + redefineImage(level, getBaseLevelInternalFormat(), levelSize); } } @@ -884,7 +946,7 @@ unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index) return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); @@ -916,7 +978,7 @@ bool TextureD3D_2D::isLevelComplete(int level) const return true; } - const Image *baseImage = getBaseLevelImage(); + const ImageD3D *baseImage = getBaseLevelImage(); GLsizei width = baseImage->getWidth(); GLsizei height = baseImage->getHeight(); @@ -1012,8 +1074,20 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + bool hintLevelZeroOnly = false; + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use the mipped texture to begin with. + // Otherwise, it should use the level-zero-only texture. + hintLevelZeroOnly = true; + for (int level = 1; level < levels && hintLevelZeroOnly; level++) + { + hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level)); + } + } + // TODO(geofflang): Determine if the texture creation succeeded - *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels); + *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly); return gl::Error(GL_NO_ERROR); } @@ -1078,22 +1152,24 @@ gl::Error TextureD3D_2D::updateStorageLevel(int level) return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) +void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) { + ASSERT(size.depth == 1); + // If there currently is a corresponding storage texture image, it has these parameters const int storageWidth = std::max(1, getBaseLevelWidth() >> level); const int storageHeight = std::max(1, getBaseLevelHeight() >> level); const GLenum storageFormat = getBaseLevelInternalFormat(); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false); + mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, false); if (mTexStorage) { const int storageLevels = mTexStorage->getLevelCount(); if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || + size.width != storageWidth || + size.height != storageHeight || internalformat != storageFormat) // Discard mismatched storage { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) @@ -1131,7 +1207,7 @@ TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer) { for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) { - mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage()); + mImageArray[i][j] = renderer->createImage(); } } } @@ -1152,17 +1228,17 @@ TextureD3D_Cube::~TextureD3D_Cube() SafeDelete(mTexStorage); } -Image *TextureD3D_Cube::getImage(int level, int layer) const +ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(layer < 6); + ASSERT(layer >= 0 && layer < 6); return mImageArray[layer][level]; } -Image *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const +ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const { ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(index.layerIndex < 6); + ASSERT(index.layerIndex >= 0 && index.layerIndex < 6); return mImageArray[index.layerIndex][index.mipIndex]; } @@ -1185,75 +1261,75 @@ bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; } -gl::Error TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) +gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(depth == 1); + ASSERT(size.depth == 1); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - redefineImage(index.layerIndex, level, sizedInternalFormat, width, height); + redefineImage(index.layerIndex, level, sizedInternalFormat, size); - return TextureD3D::setImage(unpack, type, pixels, index); + return TextureD3D::setImage(index, type, unpack, pixels, 0); } -gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(depth == 1); - - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + ASSERT(area.depth == 1 && area.z == 0); - redefineImage(faceIndex, level, format, width, height); - - return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[faceIndex][level]); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); } -gl::Error TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(depth == 1 && zoffset == 0); + ASSERT(size.depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + + redefineImage(faceIndex, level, internalFormat, size); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index); + return TextureD3D::setCompressedImage(index, unpack, pixels, 0); } -gl::Error TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { - ASSERT(depth == 1 && zoffset == 0); + ASSERT(area.depth == 1 && area.z == 0); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[index.layerIndex][level]); + gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); if (error.isError()) { return error; } - gl::Box region(xoffset, yoffset, 0, width, height, 1); - return commitRegion(index, region); + return commitRegion(index, area); } -gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, - GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_Cube::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) { - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); - redefineImage(faceIndex, level, sizedInternalFormat, width, height); + gl::Extents size(sourceArea.width, sourceArea.height, 1); + redefineImage(faceIndex, level, sizedInternalFormat, size); - gl::Rectangle sourceRect(x, y, width, height); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + gl::Offset destOffset(0, 0, 0); - if (!canCreateRenderTargetForImage(index)) + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source); + gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -1271,11 +1347,11 @@ gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, mImageArray[faceIndex][level]->markClean(); - ASSERT(width == height); + ASSERT(size.width == size.height); - if (width > 0 && isValidFaceLevel(faceIndex, level)) + if (size.width > 0 && isValidFaceLevel(faceIndex, level)) { - error = mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level); + error = mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset, mTexStorage, target, level); if (error.isError()) { return error; @@ -1286,17 +1362,18 @@ gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_Cube::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) { - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); - gl::Rectangle sourceRect(x, y, width, height); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - if (!canCreateRenderTargetForImage(index)) + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error =mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source); + gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -1320,8 +1397,8 @@ gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffse return error; } - error = mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, mTexStorage, target, level); + error = mRenderer->copyImageCube(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, target, level); if (error.isError()) { return error; @@ -1332,17 +1409,17 @@ gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffse return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) { - ASSERT(width == height); - ASSERT(depth == 1); + ASSERT(size.width == size.height); + ASSERT(size.depth == 1); - for (int level = 0; level < levels; level++) + for (size_t level = 0; level < levels; level++) { - GLsizei mipSize = std::max(1, width >> level); + GLsizei mipSize = std::max(1, size.width >> level); for (int faceIndex = 0; faceIndex < 6; faceIndex++) { - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true); + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true); } } @@ -1350,13 +1427,14 @@ gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum interna { for (int faceIndex = 0; faceIndex < 6; faceIndex++) { - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true); + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, GL_NONE, gl::Extents(0, 0, 0), true); } } // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels); + + TextureStorage *storage = mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, levels, false); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -1365,6 +1443,13 @@ gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum interna return error; } + error = updateStorage(); + + if (error.isError()) + { + return error; + } + mImmutable = true; return gl::Error(GL_NO_ERROR); @@ -1417,19 +1502,20 @@ void TextureD3D_Cube::initMipmapsImages() for (int level = 1; level < levelCount; level++) { int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); - redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); + redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), + gl::Extents(faceLevelSize, faceLevelSize, 1)); } } } unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { - ASSERT(gl::IsCubemapTextureTarget(index.type)); + ASSERT(gl::IsCubeMapTextureTarget(index.type)); // ensure the underlying texture is created gl::Error error = ensureRenderTarget(); @@ -1498,8 +1584,23 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); + bool hintLevelZeroOnly = false; + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with. + // Otherwise, it should use the level-zero-only texture. + hintLevelZeroOnly = true; + for (int faceIndex = 0; faceIndex < 6 && hintLevelZeroOnly; faceIndex++) + { + for (int level = 1; level < levels && hintLevelZeroOnly; level++) + { + hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() && isFaceLevelComplete(faceIndex, level)); + } + } + } + // TODO (geofflang): detect if storage creation succeeded - *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels); + *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly); return gl::Error(GL_NO_ERROR); } @@ -1607,7 +1708,7 @@ gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) if (image->isDirty()) { - GLenum faceTarget = gl::TextureCubeMap::layerIndexToTarget(faceIndex); + GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex); gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level); gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1); gl::Error error = commitRegion(index, region); @@ -1620,29 +1721,29 @@ gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) return gl::Error(GL_NO_ERROR); } -void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) +void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size) { // If there currently is a corresponding storage texture image, it has these parameters const int storageWidth = std::max(1, getBaseLevelWidth() >> level); const int storageHeight = std::max(1, getBaseLevelHeight() >> level); const GLenum storageFormat = getBaseLevelInternalFormat(); - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false); + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false); if (mTexStorage) { const int storageLevels = mTexStorage->getLevelCount(); if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || + size.width != storageWidth || + size.height != storageHeight || internalformat != storageFormat) // Discard mismatched storage { - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) + for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++) { - mImageArray[faceIndex][level]->markDirty(); + mImageArray[dirtyFace][dirtyLevel]->markDirty(); } } @@ -1661,12 +1762,12 @@ gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const { // The "layer" of the image index corresponds to the cube face - return gl::ImageIndex::MakeCube(gl::TextureCubeMap::layerIndexToTarget(layer), mip); + return gl::ImageIndex::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip); } bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const { - return (mTexStorage && gl::IsCubemapTextureTarget(index.type) && + return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) && index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); } @@ -1675,7 +1776,7 @@ TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer) { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) { - mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + mImageArray[i] = renderer->createImage(); } } @@ -1692,14 +1793,14 @@ TextureD3D_3D::~TextureD3D_3D() SafeDelete(mTexStorage); } -Image *TextureD3D_3D::getImage(int level, int layer) const +ImageD3D *TextureD3D_3D::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(layer == 0); return mImageArray[level]; } -Image *TextureD3D_3D::getImage(const gl::ImageIndex &index) const +ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const { ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); ASSERT(!index.hasLayer()); @@ -1750,24 +1851,23 @@ bool TextureD3D_3D::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) +gl::Error TextureD3D_3D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - redefineImage(level, sizedInternalFormat, width, height, depth); + redefineImage(level, sizedInternalFormat, size); bool fastUnpacked = false; gl::ImageIndex index = gl::ImageIndex::Make3D(level); // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer - if (isFastUnpackable(unpack, sizedInternalFormat)) + if (isFastUnpackable(unpack, sizedInternalFormat) && !size.empty()) { // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = NULL; + RenderTargetD3D *destRenderTarget = NULL; gl::Error error = getRenderTarget(index, &destRenderTarget); if (error.isError()) { @@ -1790,7 +1890,7 @@ gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLs if (!fastUnpacked) { - gl::Error error = TextureD3D::setImage(unpack, type, pixels, index); + gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0); if (error.isError()) { return error; @@ -1800,96 +1900,77 @@ gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLs return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height,GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height, depth); - - return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]); -} - -gl::Error TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_3D); - - bool fastUnpacked = false; - gl::ImageIndex index = gl::ImageIndex::Make3D(level); // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer if (isFastUnpackable(unpack, getInternalFormat(level))) { - RenderTarget *destRenderTarget = NULL; + RenderTargetD3D *destRenderTarget = NULL; gl::Error error = getRenderTarget(index, &destRenderTarget); if (error.isError()) { return error; } - gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); - error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget); - if (error.isError()) - { - return error; - } - - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); + ASSERT(!mImageArray[level]->isDirty()); - fastUnpacked = true; + return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget); } - - if (!fastUnpacked) + else { - return TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, - unpack, pixels, index); + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); } +} - return gl::Error(GL_NO_ERROR); +gl::Error TextureD3D_3D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + return TextureD3D::setCompressedImage(index, unpack, pixels, 0); } -gl::Error TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, unpack, pixels, mImageArray[level]); + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); if (error.isError()) { return error; } - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - gl::Box region(xoffset, yoffset, zoffset, width, height, depth); - return commitRegion(index, region); + return commitRegion(index, area); } -gl::Error TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, - GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) { UNIMPLEMENTED(); return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented."); } -gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_3D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_3D); - gl::Rectangle sourceRect(x, y, width, height); gl::ImageIndex index = gl::ImageIndex::Make3D(level); if (canCreateRenderTargetForImage(index)) { - gl::Error error = mImageArray[level]->copy(xoffset, yoffset, zoffset, sourceRect, source); + gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -1913,9 +1994,9 @@ gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, return error; } - error = mRenderer->copyImage3D(source, sourceRect, + error = mRenderer->copyImage3D(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, zoffset, mTexStorage, level); + destOffset, mTexStorage, level); if (error.isError()) { return error; @@ -1926,26 +2007,26 @@ gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) { ASSERT(target == GL_TEXTURE_3D); - for (int level = 0; level < levels; level++) + for (size_t level = 0; level < levels; level++) { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - GLsizei levelDepth = std::max(1, depth >> level); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true); + gl::Extents levelSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + std::max(1, size.depth >> level)); + mImageArray[level]->redefine(GL_TEXTURE_3D, internalFormat, levelSize, true); } for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); + mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true); } // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels); + TextureStorage *storage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, size.depth, levels); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -1954,6 +2035,13 @@ gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalf return error; } + error = updateStorage(); + + if (error.isError()) + { + return error; + } + mImmutable = true; return gl::Error(GL_NO_ERROR); @@ -1976,10 +2064,10 @@ void TextureD3D_3D::initMipmapsImages() int levelCount = mipLevels(); for (int level = 1; level < levelCount; level++) { - redefineImage(level, getBaseLevelInternalFormat(), - std::max(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1), - std::max(getBaseLevelDepth() >> level, 1)); + gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1), + std::max(getBaseLevelDepth() >> level, 1)); + redefineImage(level, getBaseLevelInternalFormat(), levelSize); } } @@ -1988,7 +2076,7 @@ unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index) return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { // ensure the underlying texture is created gl::Error error = ensureRenderTarget(); @@ -2031,7 +2119,7 @@ gl::Error TextureD3D_3D::initializeStorage(bool renderTarget) return gl::Error(GL_NO_ERROR); } - bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); TextureStorage *storage = NULL; gl::Error error = createCompleteStorage(createRenderTarget, &storage); @@ -2185,7 +2273,7 @@ gl::Error TextureD3D_3D::updateStorageLevel(int level) return gl::Error(GL_NO_ERROR); } -void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) { // If there currently is a corresponding storage texture image, it has these parameters const int storageWidth = std::max(1, getBaseLevelWidth() >> level); @@ -2193,16 +2281,16 @@ void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei wi const int storageDepth = std::max(1, getBaseLevelDepth() >> level); const GLenum storageFormat = getBaseLevelInternalFormat(); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false); + mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false); if (mTexStorage) { const int storageLevels = mTexStorage->getLevelCount(); if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - depth != storageDepth || + size.width != storageWidth || + size.height != storageHeight || + size.depth != storageDepth || internalformat != storageFormat) // Discard mismatched storage { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) @@ -2253,19 +2341,21 @@ TextureD3D_2DArray::~TextureD3D_2DArray() SafeDelete(mTexStorage); } -Image *TextureD3D_2DArray::getImage(int level, int layer) const +ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(layer < mLayerCounts[level]); - return mImageArray[level][layer]; + ASSERT((layer == 0 && mLayerCounts[level] == 0) || + layer < mLayerCounts[level]); + return (mImageArray[level] ? mImageArray[level][layer] : NULL); } -Image *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const +ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const { ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(index.layerIndex < mLayerCounts[index.mipIndex]); + ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) || + index.layerIndex < mLayerCounts[index.mipIndex]); ASSERT(index.type == GL_TEXTURE_2D_ARRAY); - return mImageArray[index.mipIndex][index.layerIndex]; + return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : NULL); } GLsizei TextureD3D_2DArray::getLayerCount(int level) const @@ -2294,24 +2384,23 @@ bool TextureD3D_2DArray::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) +gl::Error TextureD3D_2DArray::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - redefineImage(level, sizedInternalFormat, width, height, depth); + redefineImage(level, sizedInternalFormat, size); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength); - for (int i = 0; i < depth; i++) + for (int i = 0; i < size.depth; i++) { - const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + const ptrdiff_t layerOffset = (inputDepthPitch * i); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); - gl::Error error = TextureD3D::setImage(unpack, type, layerPixels, index); + gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, layerOffset); if (error.isError()) { return error; @@ -2321,22 +2410,23 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2DArray::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height, depth); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength); - for (int i = 0; i < depth; i++) + for (int i = 0; i < area.depth; i++) { - const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; - gl::Error error = TextureD3D::setCompressedImage(unpack, imageSize, layerPixels, mImageArray[level][i]); + int layer = area.z + i; + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Error error = TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset); if (error.isError()) { return error; @@ -2346,23 +2436,23 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLe return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); - for (int i = 0; i < depth; i++) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0); + + for (int i = 0; i < size.depth; i++) { - int layer = zoffset + i; - const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + const ptrdiff_t layerOffset = (inputDepthPitch * i); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - gl::Error error = TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, - unpack, layerPixels, index); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); + gl::Error error = TextureD3D::setCompressedImage(index, unpack, pixels, layerOffset); if (error.isError()) { return error; @@ -2372,29 +2462,29 @@ gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); - for (int i = 0; i < depth; i++) + for (int i = 0; i < area.depth; i++) { - int layer = zoffset + i; - const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + int layer = area.z + i; + const ptrdiff_t layerOffset = (inputDepthPitch * i); - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, unpack, layerPixels, mImageArray[level][layer]); + gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Error error = TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset); if (error.isError()) { return error; } - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - gl::Box region(xoffset, yoffset, 0, width, height, 1); - error = commitRegion(index, region); + error = commitRegion(index, layerArea); if (error.isError()) { return error; @@ -2404,22 +2494,24 @@ gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLi return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) { UNIMPLEMENTED(); return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented."); } -gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2DArray::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D_ARRAY); - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zoffset); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); if (canCreateRenderTargetForImage(index)) { - gl::Error error = mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, sourceRect, source); + gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0); + gl::Error error = mImageArray[level][destOffset.z]->copy(destLayerOffset, sourceArea, source); if (error.isError()) { return error; @@ -2443,8 +2535,8 @@ gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xof return error; } - error = mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format, - xoffset, yoffset, zoffset, mTexStorage, level); + error = mRenderer->copyImage2DArray(source, sourceArea, gl::GetInternalFormatInfo(getInternalFormat(0)).format, + destOffset, mTexStorage, level); if (error.isError()) { return error; @@ -2454,18 +2546,19 @@ gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xof return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) { ASSERT(target == GL_TEXTURE_2D_ARRAY); deleteImages(); - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); + gl::Extents levelLayerSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + 1); - mLayerCounts[level] = (level < levels ? depth : 0); + mLayerCounts[level] = (level < levels ? size.depth : 0); if (mLayerCounts[level] > 0) { @@ -2474,16 +2567,15 @@ gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum inte for (int layer = 0; layer < mLayerCounts[level]; layer++) { - mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); - mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth, - levelHeight, 1, true); + mImageArray[level][layer] = mRenderer->createImage(); + mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true); } } } // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels); + TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, size.height, size.depth, levels); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -2492,6 +2584,13 @@ gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum inte return error; } + error = updateStorage(); + + if (error.isError()) + { + return error; + } + mImmutable = true; return gl::Error(GL_NO_ERROR); @@ -2512,14 +2611,17 @@ void TextureD3D_2DArray::initMipmapsImages() { int baseWidth = getBaseLevelWidth(); int baseHeight = getBaseLevelHeight(); - int baseDepth = getBaseLevelDepth(); + int baseDepth = getLayerCount(0); GLenum baseFormat = getBaseLevelInternalFormat(); // Purge array levels 1 through q and reset them to represent the generated mipmap levels. int levelCount = mipLevels(); for (int level = 1; level < levelCount; level++) { - redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); + gl::Extents levelLayerSize(std::max(baseWidth >> level, 1), + std::max(baseHeight >> level, 1), + baseDepth); + redefineImage(level, baseFormat, levelLayerSize); } } @@ -2528,7 +2630,7 @@ unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &ind return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { // ensure the underlying texture is created gl::Error error = ensureRenderTarget(); @@ -2560,7 +2662,7 @@ gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget) return gl::Error(GL_NO_ERROR); } - bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); TextureStorage *storage = NULL; gl::Error error = createCompleteStorage(createRenderTarget, &storage); @@ -2730,7 +2832,7 @@ void TextureD3D_2DArray::deleteImages() } } -void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) { // If there currently is a corresponding storage texture image, it has these parameters const int storageWidth = std::max(1, getBaseLevelWidth() >> level); @@ -2744,16 +2846,17 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz } delete[] mImageArray[level]; mImageArray[level] = NULL; - mLayerCounts[level] = depth; + mLayerCounts[level] = size.depth; - if (depth > 0) + if (size.depth > 0) { - mImageArray[level] = new ImageD3D*[depth](); + mImageArray[level] = new ImageD3D*[size.depth](); for (int layer = 0; layer < mLayerCounts[level]; layer++) { - mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); - mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false); + mImageArray[level][layer] = mRenderer->createImage(); + mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat, + gl::Extents(size.width, size.height, 1), false); } } @@ -2762,16 +2865,16 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz const int storageLevels = mTexStorage->getLevelCount(); if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - depth != storageDepth || + size.width != storageWidth || + size.height != storageHeight || + size.depth != storageDepth || internalformat != storageFormat) // Discard mismatched storage { - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) { - for (int layer = 0; layer < mLayerCounts[level]; layer++) + for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++) { - mImageArray[level][layer]->markDirty(); + mImageArray[dirtyLevel][dirtyLayer]->markDirty(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h index 083a6335b9..d94be49a08 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h @@ -6,12 +6,12 @@ // TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. -#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_ -#define LIBGLESV2_RENDERER_TEXTURED3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ +#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ -#include "libGLESv2/renderer/TextureImpl.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" namespace gl { @@ -21,10 +21,10 @@ class Framebuffer; namespace rx { -class Image; +class ImageD3D; class ImageD3D; class RendererD3D; -class RenderTarget; +class RenderTargetD3D; class TextureStorage; class TextureD3D : public TextureImpl @@ -33,14 +33,15 @@ class TextureD3D : public TextureImpl TextureD3D(RendererD3D *renderer); virtual ~TextureD3D(); - static TextureD3D *makeTextureD3D(TextureImpl *texture); - - TextureStorage *getNativeTexture(); + gl::Error getNativeTexture(TextureStorage **outStorage); virtual void setUsage(GLenum usage) { mUsage = usage; } bool hasDirtyImages() const { return mDirtyImages; } void resetDirty() { mDirtyImages = false; } + virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0; + virtual GLsizei getLayerCount(int level) const = 0; + GLint getBaseLevelWidth() const; GLint getBaseLevelHeight() const; GLint getBaseLevelDepth() const; @@ -48,7 +49,7 @@ class TextureD3D : public TextureImpl bool isImmutable() const { return mImmutable; } - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0; // Returns an iterator over all "Images" for this particular Texture. @@ -61,18 +62,21 @@ class TextureD3D : public TextureImpl virtual gl::Error generateMipmaps(); TextureStorage *getStorage(); - Image *getBaseLevelImage() const; + ImageD3D *getBaseLevelImage() const; protected: - gl::Error setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index); - gl::Error subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index); - gl::Error setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image); - gl::Error subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image); + gl::Error setImage(const gl::ImageIndex &index, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset); + gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); + gl::Error setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, + const uint8_t *pixels, ptrdiff_t layerOffset); + gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); - gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); + gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget); GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; int mipLevels() const; @@ -97,13 +101,11 @@ class TextureD3D : public TextureImpl TextureStorage *mTexStorage; private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D); - virtual gl::Error initializeStorage(bool renderTarget) = 0; virtual gl::Error updateStorage() = 0; - bool shouldUseSetData(const Image *image) const; + bool shouldUseSetData(const ImageD3D *image) const; }; class TextureD3D_2D : public TextureD3D @@ -112,28 +114,36 @@ class TextureD3D_2D : public TextureD3D TextureD3D_2D(RendererD3D *renderer); virtual ~TextureD3D_2D(); - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; virtual GLsizei getLayerCount(int level) const; GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; bool isDepth(GLint level) const; - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; @@ -141,8 +151,6 @@ class TextureD3D_2D : public TextureD3D virtual bool isValidIndex(const gl::ImageIndex &index) const; private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); - virtual gl::Error initializeStorage(bool renderTarget); virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); @@ -156,7 +164,7 @@ class TextureD3D_2D : public TextureD3D gl::Error updateStorageLevel(int level); - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; @@ -167,8 +175,8 @@ class TextureD3D_Cube : public TextureD3D TextureD3D_Cube(RendererD3D *renderer); virtual ~TextureD3D_Cube(); - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; virtual GLsizei getLayerCount(int level) const; virtual bool hasDirtyImages() const { return mDirtyImages; } @@ -178,18 +186,27 @@ class TextureD3D_Cube : public TextureD3D GLenum getInternalFormat(GLint level, GLint layer) const; bool isDepth(GLint level, GLint layer) const; - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; @@ -197,8 +214,6 @@ class TextureD3D_Cube : public TextureD3D virtual bool isValidIndex(const gl::ImageIndex &index) const; private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); - virtual gl::Error initializeStorage(bool renderTarget); virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); @@ -212,7 +227,7 @@ class TextureD3D_Cube : public TextureD3D virtual bool isImageComplete(const gl::ImageIndex &index) const; gl::Error updateStorageFaceLevel(int faceIndex, int level); - void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size); ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; @@ -223,8 +238,8 @@ class TextureD3D_3D : public TextureD3D TextureD3D_3D(RendererD3D *renderer); virtual ~TextureD3D_3D(); - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; virtual GLsizei getLayerCount(int level) const; GLsizei getWidth(GLint level) const; @@ -233,18 +248,27 @@ class TextureD3D_3D : public TextureD3D GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; @@ -252,8 +276,6 @@ class TextureD3D_3D : public TextureD3D virtual bool isValidIndex(const gl::ImageIndex &index) const; private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); - virtual gl::Error initializeStorage(bool renderTarget); virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); @@ -266,7 +288,7 @@ class TextureD3D_3D : public TextureD3D virtual bool isImageComplete(const gl::ImageIndex &index) const; gl::Error updateStorageLevel(int level); - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; @@ -277,8 +299,8 @@ class TextureD3D_2DArray : public TextureD3D TextureD3D_2DArray(RendererD3D *renderer); virtual ~TextureD3D_2DArray(); - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; virtual GLsizei getLayerCount(int level) const; GLsizei getWidth(GLint level) const; @@ -286,18 +308,27 @@ class TextureD3D_2DArray : public TextureD3D GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; @@ -305,8 +336,6 @@ class TextureD3D_2DArray : public TextureD3D virtual bool isValidIndex(const gl::ImageIndex &index) const; private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); - virtual gl::Error initializeStorage(bool renderTarget); virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); @@ -320,7 +349,7 @@ class TextureD3D_2DArray : public TextureD3D gl::Error updateStorageLevel(int level); void deleteImages(); - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); // Storing images as an array of single depth textures since D3D11 treats each array level of a // Texture2D object as a separate subresource. Each layer would have to be looped over @@ -332,4 +361,4 @@ class TextureD3D_2DArray : public TextureD3D } -#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_ +#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp index 320b74b8ed..abb83a14d5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp @@ -6,12 +6,12 @@ // TextureStorage.cpp: Shared members of abstract rx::TextureStorage class. -#include "libGLESv2/renderer/d3d/TextureStorage.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Texture.h" #include "common/debug.h" #include "common/mathutil.h" @@ -26,7 +26,7 @@ TextureStorage::TextureStorage() void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride) { - mFirstRenderTargetSerial = RenderTarget::issueSerials(rtSerialsToReserve); + mFirstRenderTargetSerial = RenderTargetD3D::issueSerials(rtSerialsToReserve); mRenderTargetSerialsLayerStride = rtSerialsLayerStride; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h index da92be3c74..ae2d42ca8a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h @@ -6,16 +6,16 @@ // TextureStorage.h: Defines the abstract rx::TextureStorage class. -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ +#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include "common/debug.h" -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include <GLES2/gl2.h> -#include <cstdint> +#include <stdint.h> namespace gl { @@ -26,11 +26,11 @@ struct PixelUnpackState; namespace rx { -class SwapChain; -class RenderTarget; -class Image; +class SwapChainD3D; +class RenderTargetD3D; +class ImageD3D; -class TextureStorage +class TextureStorage : angle::NonCopyable { public: TextureStorage(); @@ -41,26 +41,27 @@ class TextureStorage virtual bool isManaged() const = 0; virtual int getLevelCount() const = 0; - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0; virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0; - virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0; unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; unsigned int getTextureSerial() const; + // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it. + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); } + protected: void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - unsigned int mFirstRenderTargetSerial; unsigned int mRenderTargetSerialsLayerStride; }; } -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp index 11596006d0..5c0bfdcd5b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp @@ -6,7 +6,7 @@ // TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers. -#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h index 7c367aba1d..6b255b4a2b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h @@ -6,11 +6,11 @@ // TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class. -#ifndef LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ -#define LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ +#define LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ -#include "libGLESv2/renderer/TransformFeedbackImpl.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/renderer/TransformFeedbackImpl.h" +#include "libANGLE/angletypes.h" namespace rx { @@ -29,4 +29,4 @@ class TransformFeedbackD3D : public TransformFeedbackImpl } -#endif // LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp index 73f0c79e19..19bd548fce 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp @@ -7,10 +7,10 @@ // VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface // class with derivations, classes that perform graphics API agnostic vertex buffer operations. -#include "libGLESv2/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/VertexAttribute.h" #include "common/mathutil.h" @@ -38,13 +38,14 @@ unsigned int VertexBuffer::getSerial() const return mSerial; } -VertexBufferInterface::VertexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer) +VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic) + : mFactory(factory) { mDynamic = dynamic; mWritePosition = 0; mReservedSpace = 0; - mVertexBuffer = renderer->createVertexBuffer(); + mVertexBuffer = factory->createVertexBuffer(); } VertexBufferInterface::~VertexBufferInterface() @@ -167,7 +168,7 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att const gl::VertexAttribCurrentValueData ¤tValue) const { gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; if (!storage || !storage->supportsDirectBinding()) { @@ -188,7 +189,8 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); alignment = std::min<size_t>(outputElementSize, 4); - requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; + // TODO(jmadill): add VertexFormatCaps + requiresConversion = (mFactory->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; } bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) && @@ -197,7 +199,8 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att return !requiresConversion && isAligned; } -StreamingVertexBufferInterface::StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) +StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize) + : VertexBufferInterface(factory, true) { setBufferSize(initialSize); } @@ -231,7 +234,8 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) return gl::Error(GL_NO_ERROR); } -StaticVertexBufferInterface::StaticVertexBufferInterface(RendererD3D *renderer) : VertexBufferInterface(renderer, false) +StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) + : VertexBufferInterface(factory, false) { } @@ -293,7 +297,7 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt } size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib); - VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; + VertexElement element = { attrib.type, attrib.size, static_cast<GLuint>(ComputeVertexAttributeStride(attrib)), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; mCache.push_back(element); if (outStreamOffset) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h index 4b40818f8e..5cb03fe3a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h @@ -7,11 +7,11 @@ // VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface // class with derivations, classes that perform graphics API agnostic vertex buffer operations. -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_ +#ifndef LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ +#define LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ #include "common/angleutils.h" -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include <GLES2/gl2.h> @@ -26,9 +26,9 @@ struct VertexAttribCurrentValueData; namespace rx { -class RendererD3D; +class BufferFactoryD3D; -class VertexBuffer +class VertexBuffer : angle::NonCopyable { public: VertexBuffer(); @@ -47,20 +47,21 @@ class VertexBuffer unsigned int getSerial() const; + // This may be overridden (e.g. by VertexBuffer11) if necessary. + virtual void hintUnmapResource() { }; + protected: void updateSerial(); private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer); - unsigned int mSerial; static unsigned int mNextSerial; }; -class VertexBufferInterface +class VertexBufferInterface : angle::NonCopyable { public: - VertexBufferInterface(RendererD3D *renderer, bool dynamic); + VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic); virtual ~VertexBufferInterface(); gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); @@ -88,9 +89,7 @@ class VertexBufferInterface gl::Error setBufferSize(unsigned int size); private: - DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); - - RendererD3D *const mRenderer; + BufferFactoryD3D *const mFactory; VertexBuffer* mVertexBuffer; @@ -102,7 +101,7 @@ class VertexBufferInterface class StreamingVertexBufferInterface : public VertexBufferInterface { public: - StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize); + StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize); ~StreamingVertexBufferInterface(); protected: @@ -112,7 +111,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface class StaticVertexBufferInterface : public VertexBufferInterface { public: - explicit StaticVertexBufferInterface(RendererD3D *renderer); + explicit StaticVertexBufferInterface(BufferFactoryD3D *factory); ~StaticVertexBufferInterface(); gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, @@ -141,4 +140,4 @@ class StaticVertexBufferInterface : public VertexBufferInterface } -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_
\ No newline at end of file +#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp index 8d3df31c8b..cb70b9e4ef 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -7,14 +7,15 @@ // VertexDataManager.h: Defines the VertexDataManager, a class that // runs the Buffer translation process. -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/State.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" namespace { @@ -46,13 +47,16 @@ static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int ve // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. if (instanceDrawCount > 0 && attrib.divisor > 0) { - return instanceDrawCount / attrib.divisor; + // When instanceDrawCount is not a multiple attrib.divisor, the division must round up. + // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced vertices. + return (instanceDrawCount + attrib.divisor - 1) / attrib.divisor; } return vertexDrawCount; } -VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer) +VertexDataManager::VertexDataManager(BufferFactoryD3D *factory) + : mFactory(factory) { for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { @@ -65,7 +69,7 @@ VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer mCurrentValueOffsets[i] = 0; } - mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE); + mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE); if (!mStreamingBuffer) { @@ -83,6 +87,35 @@ VertexDataManager::~VertexDataManager() } } +void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes) +{ + mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); + + for (size_t i = 0; i < vertexAttributes.size(); i++) + { + const gl::VertexAttribute &attrib = vertexAttributes[i]; + if (attrib.enabled) + { + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; + StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + + if (staticBuffer) + { + staticBuffer->getVertexBuffer()->hintUnmapResource(); + } + } + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (mCurrentValueBuffer[i] != NULL) + { + mCurrentValueBuffer[i]->getVertexBuffer()->hintUnmapResource(); + } + } +} + gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) { @@ -91,25 +124,25 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } + const gl::VertexArray *vertexArray = state.getVertexArray(); + const std::vector<gl::VertexAttribute> &vertexAttributes = vertexArray->getVertexAttributes(); + // Invalidate static buffers that don't contain matching attributes for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) { - translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1); - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex); - - if (translated[attributeIndex].active && curAttrib.enabled) + translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1); + if (translated[attributeIndex].active && vertexAttributes[attributeIndex].enabled) { - invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex)); + invalidateMatchingStaticData(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex)); } } // Reserve the required space in the buffers for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); - if (translated[i].active && curAttrib.enabled) + if (translated[i].active && vertexAttributes[i].enabled) { - gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances); + gl::Error error = reserveSpaceForAttrib(vertexAttributes[i], state.getVertexAttribCurrentValue(i), count, instances); if (error.isError()) { return error; @@ -120,7 +153,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta // Perform the vertex data translations for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); + const gl::VertexAttribute &curAttrib = vertexAttributes[i]; if (translated[i].active) { if (curAttrib.enabled) @@ -130,6 +163,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta if (error.isError()) { + hintUnmapAllResources(vertexAttributes); return error; } } @@ -137,7 +171,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta { if (!mCurrentValueBuffer[i]) { - mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); } gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], @@ -145,22 +179,26 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta mCurrentValueBuffer[i]); if (error.isError()) { + hintUnmapAllResources(vertexAttributes); return error; } } } } + // Hint to unmap all the resources + hintUnmapAllResources(vertexAttributes); + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); + const gl::VertexAttribute &curAttrib = vertexAttributes[i]; if (translated[i].active && curAttrib.enabled) { gl::Buffer *buffer = curAttrib.buffer.get(); if (buffer) { - BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); } } @@ -176,7 +214,7 @@ void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute & if (buffer) { - BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); if (staticBuffer && @@ -195,7 +233,7 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &at GLsizei instances) const { gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); @@ -239,7 +277,7 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, gl::Buffer *buffer = attrib.buffer.get(); ASSERT(buffer || attrib.pointer); - BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); @@ -247,10 +285,13 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, unsigned int streamOffset = 0; unsigned int outputElementSize = 0; + // Instanced vertices do not apply the 'start' offset + GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start); + if (directStorage) { outputElementSize = ComputeVertexAttributeStride(attrib); - streamOffset = attrib.offset + outputElementSize * start; + streamOffset = attrib.offset + outputElementSize * firstVertexIndex; } else if (staticBuffer) { @@ -266,8 +307,8 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, int totalCount = ElementsInBuffer(attrib, storage->getSize()); int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); - gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, - 0, &streamOffset); + error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, + 0, &streamOffset); if (error.isError()) { return error; @@ -275,7 +316,7 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, } unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; - unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0; + unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0; if (streamOffset + firstElementOffset + startOffset < streamOffset) { return gl::Error(GL_OUT_OF_MEMORY); @@ -292,7 +333,8 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, return error; } - error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset); + error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, firstVertexIndex, + totalCount, instances, &streamOffset); if (error.isError()) { return error; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h index 64ef653221..898ed340b8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -7,16 +7,15 @@ // VertexDataManager.h: Defines the VertexDataManager, a class that // runs the Buffer translation process. -#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ -#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ +#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ +#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ -#include "libGLESv2/Constants.h" -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/Constants.h" +#include "libANGLE/VertexAttribute.h" #include "common/angleutils.h" namespace gl { -class ProgramBinary; class State; struct VertexAttribute; struct VertexAttribCurrentValueData; @@ -25,9 +24,9 @@ struct VertexAttribCurrentValueData; namespace rx { class BufferD3D; +class BufferFactoryD3D; class StreamingVertexBufferInterface; class VertexBuffer; -class RendererD3D; struct TranslatedAttribute { @@ -47,18 +46,16 @@ struct TranslatedAttribute unsigned int divisor; }; -class VertexDataManager +class VertexDataManager : angle::NonCopyable { public: - VertexDataManager(RendererD3D *renderer); + VertexDataManager(BufferFactoryD3D *factory); virtual ~VertexDataManager(); gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); private: - DISALLOW_COPY_AND_ASSIGN(VertexDataManager); - gl::Error reserveSpaceForAttrib(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, GLsizei count, @@ -81,7 +78,9 @@ class VertexDataManager size_t *cachedOffset, StreamingVertexBufferInterface *buffer); - RendererD3D *const mRenderer; + void hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes); + + BufferFactoryD3D *const mFactory; StreamingVertexBufferInterface *mStreamingBuffer; @@ -93,4 +92,4 @@ class VertexDataManager } -#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ +#endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp index aabc9f04e9..b1798454ca 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp @@ -6,7 +6,7 @@ // copyimage.cpp: Defines image copying functions -#include "libGLESv2/renderer/copyimage.h" +#include "libANGLE/renderer/d3d/copyimage.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h index 513eb5cb3d..189654ca39 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h @@ -6,13 +6,13 @@ // copyimage.h: Defines image copying functions -#ifndef LIBGLESV2_RENDERER_COPYIMAGE_H_ -#define LIBGLESV2_RENDERER_COPYIMAGE_H_ +#ifndef LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ +#define LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ #include "common/mathutil.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/angletypes.h" -#include <cstdint> +#include <stdint.h> namespace rx { @@ -32,4 +32,4 @@ void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest); #include "copyimage.inl" -#endif // LIBGLESV2_RENDERER_COPYIMAGE_H_ +#endif // LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl index 0498cf7750..0498cf7750 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp index 06aea9befe..e38b61709f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -6,56 +6,58 @@ // Blit11.cpp: Texture copy utility class. -#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" + +#include <float.h> + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/formatutils.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" namespace rx { @@ -209,7 +211,7 @@ Blit11::Blit11(Renderer11 *renderer) pointSamplerDesc.BorderColor[2] = 0.0f; pointSamplerDesc.BorderColor[3] = 0.0f; pointSamplerDesc.MinLOD = 0.0f; - pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; + pointSamplerDesc.MaxLOD = FLT_MAX; result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); ASSERT(SUCCEEDED(result)); @@ -228,7 +230,7 @@ Blit11::Blit11(Renderer11 *renderer) linearSamplerDesc.BorderColor[2] = 0.0f; linearSamplerDesc.BorderColor[3] = 0.0f; linearSamplerDesc.MinLOD = 0.0f; - linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; + linearSamplerDesc.MaxLOD = FLT_MAX; result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); ASSERT(SUCCEEDED(result)); @@ -290,7 +292,7 @@ Blit11::Blit11(Renderer11 *renderer) ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); - if (!renderer->isLevel9()) + if (renderer->isES3Capable()) { result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); ASSERT(SUCCEEDED(result)); @@ -524,7 +526,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s BlitParameters parameters = { 0 }; parameters.mDestinationFormat = destFormat; parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT); - parameters.m3DBlit = sourceArea.depth > 1; + parameters.m3DBlit = sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D; BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); if (i == mBlitShaderMap.end()) @@ -972,6 +974,7 @@ void Blit11::buildShaderMap() { ID3D11Device *device = mRenderer->getDevice(); + // 2D shaders (OpenGL ES 2+) add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); @@ -981,50 +984,59 @@ void Blit11::buildShaderMap() add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); - - if (mRenderer->isLevel9()) - return; - - add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); - add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); - add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); - add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); - add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); - add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); - add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); - add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); - add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); - add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); - add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); - add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); - add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); - add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); - - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); + // 2D shaders (OpenGL ES 3+) + if (mRenderer->isES3Capable()) + { + add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); + add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); + } + + // 3D shaders (OpenGL ES 3+) + if (mRenderer->isES3Capable()) + { + add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); + add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); + add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); + add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); + add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); + add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); + } + + // Swizzling shaders (OpenGL ES 3+) + if (mRenderer->isES3Capable()) + { + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); + } } void Blit11::clearShaderMap() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h index 821fa9d0cc..d3a8c2c8a3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -6,12 +6,12 @@ // Blit11.cpp: Texture copy utility class. -#ifndef LIBGLESV2_BLIT11_H_ -#define LIBGLESV2_BLIT11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ #include "common/angleutils.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" #include <map> @@ -19,7 +19,7 @@ namespace rx { class Renderer11; -class Blit11 +class Blit11 : angle::NonCopyable { public: explicit Blit11(Renderer11 *renderer); @@ -114,10 +114,8 @@ class Blit11 ID3D11GeometryShader *mQuad3DGS; ID3D11Buffer *mSwizzleCB; - - DISALLOW_COPY_AND_ASSIGN(Blit11); }; } -#endif // LIBGLESV2_BLIT11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index 5aab37938f..d56b0ea7ad 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -6,10 +6,17 @@ // Buffer11.cpp Defines the Buffer11 class. -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" + +#include "common/MemoryBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +#if defined(ANGLE_MINGW32_COMPAT) +typedef enum D3D11_MAP_FLAG { + D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000 +} D3D11_MAP_FLAG; +#endif namespace rx { @@ -67,32 +74,34 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) } -// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points +// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points // - vertex/transform feedback buffers // - index buffers // - pixel unpack buffers // - uniform buffers -class Buffer11::BufferStorage11 +class Buffer11::BufferStorage : angle::NonCopyable { public: - virtual ~BufferStorage11() {} + virtual ~BufferStorage() {} DataRevision getDataRevision() const { return mRevision; } BufferUsage getUsage() const { return mUsage; } size_t getSize() const { return mBufferSize; } - bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); } - void setDataRevision(DataRevision rev) { mRevision = rev; } - virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + virtual bool isMappable() const = 0; + + virtual bool copyFromStorage(BufferStorage *source, size_t sourceOffset, size_t size, size_t destOffset) = 0; virtual gl::Error resize(size_t size, bool preserveData) = 0; - virtual void *map(size_t offset, size_t length, GLbitfield access) = 0; + virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0; virtual void unmap() = 0; + gl::Error setData(const uint8_t *data, size_t offset, size_t size); + protected: - BufferStorage11(Renderer11 *renderer, BufferUsage usage); + BufferStorage(Renderer11 *renderer, BufferUsage usage); Renderer11 *mRenderer; DataRevision mRevision; @@ -102,48 +111,49 @@ class Buffer11::BufferStorage11 // A native buffer storage represents an underlying D3D11 buffer for a particular // type of storage. -class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 +class Buffer11::NativeStorage : public Buffer11::BufferStorage { public: - NativeBuffer11(Renderer11 *renderer, BufferUsage usage); - ~NativeBuffer11(); + NativeStorage(Renderer11 *renderer, BufferUsage usage); + ~NativeStorage() override; - ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; } + bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } - virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset); - virtual gl::Error resize(size_t size, bool preserveData); + ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } - virtual void *map(size_t offset, size_t length, GLbitfield access); - virtual void unmap(); + bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; - gl::Error setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset); + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; private: - ID3D11Buffer *mNativeBuffer; - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); + + ID3D11Buffer *mNativeStorage; }; // Pack storage represents internal storage for pack buffers. We implement pack buffers // as CPU memory, tied to a staging texture, for asynchronous texture readback. -class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 +class Buffer11::PackStorage : public Buffer11::BufferStorage { public: - PackStorage11(Renderer11 *renderer); - ~PackStorage11(); + explicit PackStorage(Renderer11 *renderer); + ~PackStorage() override; + + bool isMappable() const override { return true; } - virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset); - virtual gl::Error resize(size_t size, bool preserveData); + bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; - virtual void *map(size_t offset, size_t length, GLbitfield access); - virtual void unmap(); + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); private: - gl::Error flushQueuedPackCommand(); ID3D11Texture2D *mStagingTexture; @@ -155,14 +165,37 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 bool mDataModified; }; +// System memory storage stores a CPU memory buffer with our buffer data. +// For dynamic data, it's much faster to update the CPU memory buffer than +// it is to update a D3D staging buffer and read it back later. +class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage +{ + public: + explicit SystemMemoryStorage(Renderer11 *renderer); + ~SystemMemoryStorage() override {} + + bool isMappable() const override { return true; } + + bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; + + MemoryBuffer *getSystemCopy() { return &mSystemCopy; } + + protected: + MemoryBuffer mSystemCopy; +}; Buffer11::Buffer11(Renderer11 *renderer) - : BufferD3D(), + : BufferD3D(renderer), mRenderer(renderer), mSize(0), mMappedStorage(NULL), - mResolvedDataRevision(0), - mReadUsageCount(0) + mReadUsageCount(0), + mHasSystemMemoryStorage(false) {} Buffer11::~Buffer11() @@ -197,54 +230,34 @@ gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) gl::Error Buffer11::getData(const uint8_t **outData) { - NativeBuffer11 *stagingBuffer = getStagingBuffer(); + SystemMemoryStorage *systemMemoryStorage = nullptr; + gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); - if (!stagingBuffer) + if (error.isError()) { - // Out-of-memory - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get internal staging buffer."); + *outData = nullptr; + return error; } - if (stagingBuffer->getDataRevision() > mResolvedDataRevision) - { - if (stagingBuffer->getSize() > mResolvedData.size()) - { - if (!mResolvedData.resize(stagingBuffer->getSize())) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer."); - } - } - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result); - } - - memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize()); + mReadUsageCount = 0; - context->Unmap(stagingBuffer->getNativeBuffer(), 0); + ASSERT(systemMemoryStorage->getSize() >= mSize); - mResolvedDataRevision = stagingBuffer->getDataRevision(); - } + *outData = systemMemoryStorage->getSystemCopy()->data(); + return gl::Error(GL_NO_ERROR); +} - mReadUsageCount = 0; +gl::Error Buffer11::getSystemMemoryStorage(SystemMemoryStorage **storageOut) +{ + BufferStorage *memStorageUntyped = getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY); - // Only happens if we initialized the buffer with no data (NULL) - if (mResolvedData.empty()) + if (memStorageUntyped == nullptr) { - if (!mResolvedData.resize(mSize)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer."); - } + // TODO(jmadill): convert all to errors + return gl::Error(GL_OUT_OF_MEMORY); } - ASSERT(mResolvedData.size() >= mSize); - - *outData = mResolvedData.data(); + *storageOut = GetAs<SystemMemoryStorage>(memStorageUntyped); return gl::Error(GL_NO_ERROR); } @@ -254,32 +267,46 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) if (data && size > 0) { - NativeBuffer11 *stagingBuffer = getStagingBuffer(); + // Use system memory storage for dynamic buffers. - if (!stagingBuffer) + BufferStorage *writeBuffer = nullptr; + if (supportsDirectBinding()) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); + writeBuffer = getStagingStorage(); + + if (!writeBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + } } + else + { + SystemMemoryStorage *systemMemoryStorage = nullptr; + gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); + if (error.isError()) + { + return error; + } + + writeBuffer = systemMemoryStorage; + } + + ASSERT(writeBuffer); // Explicitly resize the staging buffer, preserving data if the new data will not // completely fill the buffer - if (stagingBuffer->getSize() < requiredSize) + if (writeBuffer->getSize() < requiredSize) { bool preserveData = (offset > 0); - gl::Error error = stagingBuffer->resize(requiredSize, preserveData); + gl::Error error = writeBuffer->resize(requiredSize, preserveData); if (error.isError()) { return error; } } - gl::Error error = stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset); - if (error.isError()) - { - return error; - } - - stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); + writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size); + writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1); } mSize = std::max(mSize, requiredSize); @@ -293,13 +320,13 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint Buffer11 *sourceBuffer = makeBuffer11(source); ASSERT(sourceBuffer != NULL); - BufferStorage11 *copyDest = getLatestBufferStorage(); + BufferStorage *copyDest = getLatestBufferStorage(); if (!copyDest) { - copyDest = getStagingBuffer(); + copyDest = getStagingStorage(); } - BufferStorage11 *copySource = sourceBuffer->getLatestBufferStorage(); + BufferStorage *copySource = sourceBuffer->getLatestBufferStorage(); if (!copySource || !copyDest) { @@ -310,11 +337,11 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint // pack buffer partner, because other native buffers can't be mapped if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable()) { - copySource = sourceBuffer->getStagingBuffer(); + copySource = sourceBuffer->getStagingStorage(); } else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable()) { - copyDest = getStagingBuffer(); + copyDest = getStagingStorage(); } // D3D11 does not allow overlapped copies until 11.1, and only if the @@ -328,7 +355,7 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint } else { - copySource = getStagingBuffer(); + copySource = getStagingStorage(); } } @@ -345,7 +372,7 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid { ASSERT(!mMappedStorage); - BufferStorage11 *latestStorage = getLatestBufferStorage(); + BufferStorage *latestStorage = getLatestBufferStorage(); if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || latestStorage->getUsage() == BUFFER_USAGE_STAGING)) @@ -357,7 +384,7 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid { // Fall back to using the staging buffer if the latest storage does // not exist or is not CPU-accessible. - mMappedStorage = getStagingBuffer(); + mMappedStorage = getStagingStorage(); } if (!mMappedStorage) @@ -371,13 +398,13 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); } - void *mappedBuffer = mMappedStorage->map(offset, length, access); + uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); if (!mappedBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); } - *mapPtr = mappedBuffer; + *mapPtr = static_cast<GLvoid *>(mappedBuffer); return gl::Error(GL_NO_ERROR); } @@ -391,7 +418,7 @@ gl::Error Buffer11::unmap() void Buffer11::markTransformFeedbackUsage() { - BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + BufferStorage *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); if (transformFeedbackStorage) { @@ -405,25 +432,25 @@ void Buffer11::markBufferUsage() { mReadUsageCount++; + // Free the system memory storage if we decide it isn't being used very often. const unsigned int usageLimit = 5; - if (mReadUsageCount > usageLimit && mResolvedData.size() > 0) + if (mReadUsageCount > usageLimit && mHasSystemMemoryStorage) { - mResolvedData.resize(0); - mResolvedDataRevision = 0; - } -} + auto systemMemoryStorageIt = mBufferStorages.find(BUFFER_USAGE_SYSTEM_MEMORY); + ASSERT(systemMemoryStorageIt != mBufferStorages.end()); -RendererD3D* Buffer11::getRenderer() -{ - return mRenderer; + SafeDelete(systemMemoryStorageIt->second); + mBufferStorages.erase(systemMemoryStorageIt); + mHasSystemMemoryStorage = false; + } } ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) { markBufferUsage(); - BufferStorage11 *bufferStorage = getBufferStorage(usage); + BufferStorage *bufferStorage = getBufferStorage(usage); if (!bufferStorage) { @@ -431,14 +458,14 @@ ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) return NULL; } - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage)); + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, bufferStorage)); - return static_cast<NativeBuffer11*>(bufferStorage)->getNativeBuffer(); + return static_cast<NativeStorage*>(bufferStorage)->getNativeStorage(); } ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) { - BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); + BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); if (!storage) { @@ -446,8 +473,8 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) return NULL; } - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage)); - ID3D11Buffer *buffer = static_cast<NativeBuffer11*>(storage)->getNativeBuffer(); + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, storage)); + ID3D11Buffer *buffer = static_cast<NativeStorage*>(storage)->getNativeStorage(); auto bufferSRVIt = mBufferResourceViews.find(srvFormat); @@ -486,9 +513,8 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) { - PackStorage11 *packStorage = getPackStorage(); - - BufferStorage11 *latestStorage = getLatestBufferStorage(); + PackStorage *packStorage = getPackStorage(); + BufferStorage *latestStorage = getLatestBufferStorage(); if (packStorage) { @@ -503,76 +529,84 @@ gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, return gl::Error(GL_NO_ERROR); } -Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage) +Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) { - BufferStorage11 *directBuffer = NULL; + BufferStorage *newStorage = NULL; auto directBufferIt = mBufferStorages.find(usage); if (directBufferIt != mBufferStorages.end()) { - directBuffer = directBufferIt->second; + newStorage = directBufferIt->second; } - if (!directBuffer) + if (!newStorage) { if (usage == BUFFER_USAGE_PIXEL_PACK) { - directBuffer = new PackStorage11(mRenderer); + newStorage = new PackStorage(mRenderer); + } + else if (usage == BUFFER_USAGE_SYSTEM_MEMORY) + { + newStorage = new SystemMemoryStorage(mRenderer); + mHasSystemMemoryStorage = true; } else { // buffer is not allocated, create it - directBuffer = new NativeBuffer11(mRenderer, usage); + newStorage = new NativeStorage(mRenderer, usage); } - mBufferStorages.insert(std::make_pair(usage, directBuffer)); + mBufferStorages.insert(std::make_pair(usage, newStorage)); } // resize buffer - if (directBuffer->getSize() < mSize) + if (newStorage->getSize() < mSize) { - if (directBuffer->resize(mSize, true).isError()) + if (newStorage->resize(mSize, true).isError()) { // Out of memory error return NULL; } } - BufferStorage11 *latestBuffer = getLatestBufferStorage(); - if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) + BufferStorage *latestBuffer = getLatestBufferStorage(); + if (latestBuffer && latestBuffer->getDataRevision() > newStorage->getDataRevision()) { - // if copying from a pack buffer to a non-staging native buffer, we must first - // copy through the staging buffer, because other native buffers can't be mapped - if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable()) + // Copy through a staging buffer if we're copying from or to a non-staging, mappable + // buffer storage. This is because we can't map a GPU buffer, and copy CPU + // data directly. If we're already using a staging buffer we're fine. + if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING && + newStorage->getUsage() != BUFFER_USAGE_STAGING && + (!latestBuffer->isMappable() || !newStorage->isMappable())) { - NativeBuffer11 *stagingBuffer = getStagingBuffer(); + NativeStorage *stagingBuffer = getStagingStorage(); stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); - directBuffer->setDataRevision(latestBuffer->getDataRevision()); + stagingBuffer->setDataRevision(latestBuffer->getDataRevision()); latestBuffer = stagingBuffer; } // if copyFromStorage returns true, the D3D buffer has been recreated // and we should update our serial - if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) + if (newStorage->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) { updateSerial(); } - directBuffer->setDataRevision(latestBuffer->getDataRevision()); + newStorage->setDataRevision(latestBuffer->getDataRevision()); } - return directBuffer; + return newStorage; } -Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const +Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const { // Even though we iterate over all the direct buffers, it is expected that only // 1 or 2 will be present. - BufferStorage11 *latestStorage = NULL; + BufferStorage *latestStorage = NULL; DataRevision latestRevision = 0; for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) { - BufferStorage11 *storage = it->second; + BufferStorage *storage = it->second; if (!latestStorage || storage->getDataRevision() > latestRevision) { latestStorage = storage; @@ -580,12 +614,22 @@ Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const } } + // resize buffer + if (latestStorage && latestStorage->getSize() < mSize) + { + if (latestStorage->resize(mSize, true).isError()) + { + // Out of memory error + return NULL; + } + } + return latestStorage; } -Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer() +Buffer11::NativeStorage *Buffer11::getStagingStorage() { - BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); + BufferStorage *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); if (!stagingStorage) { @@ -593,13 +637,13 @@ Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer() return NULL; } - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage)); - return static_cast<NativeBuffer11*>(stagingStorage); + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, stagingStorage)); + return static_cast<NativeStorage*>(stagingStorage); } -Buffer11::PackStorage11 *Buffer11::getPackStorage() +Buffer11::PackStorage *Buffer11::getPackStorage() { - BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); + BufferStorage *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); if (!packStorage) { @@ -607,8 +651,8 @@ Buffer11::PackStorage11 *Buffer11::getPackStorage() return NULL; } - ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage)); - return static_cast<PackStorage11*>(packStorage); + ASSERT(HAS_DYNAMIC_TYPE(PackStorage*, packStorage)); + return static_cast<PackStorage*>(packStorage); } bool Buffer11::supportsDirectBinding() const @@ -619,7 +663,7 @@ bool Buffer11::supportsDirectBinding() const return (mStaticVertexBuffer && mStaticIndexBuffer); } -Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage) +Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) : mRenderer(renderer), mUsage(usage), mRevision(0), @@ -627,25 +671,42 @@ Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usa { } -Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage) - : BufferStorage11(renderer, usage), - mNativeBuffer(NULL) +gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size) +{ + ASSERT(isMappable()); + + uint8_t *writePointer = map(offset, size, GL_MAP_WRITE_BIT); + if (!writePointer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); + } + + memcpy(writePointer, data, size); + + unmap(); + + return gl::Error(GL_NO_ERROR); +} + +Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) + : BufferStorage(renderer, usage), + mNativeStorage(NULL) { } -Buffer11::NativeBuffer11::~NativeBuffer11() +Buffer11::NativeStorage::~NativeStorage() { - SafeRelease(mNativeBuffer); + SafeRelease(mNativeStorage); } // Returns true if it recreates the direct buffer -bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, +bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, size_t size, size_t destOffset) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); size_t requiredSize = sourceOffset + size; - bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize; + bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; // (Re)initialize D3D buffer if needed if (createBuffer) @@ -654,29 +715,30 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s resize(source->getSize(), preserveData); } - if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK) + if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK || + source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY) { - ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source)); + ASSERT(source->isMappable()); - void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); + uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); + HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource); UNUSED_ASSERTION_VARIABLE(hr); ASSERT(SUCCEEDED(hr)); - unsigned char *destPointer = static_cast<unsigned char *>(mappedResource.pData) + destOffset; + uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset; // Offset bounds are validated at the API layer ASSERT(sourceOffset + size <= destOffset + mBufferSize); memcpy(destPointer, sourcePointer, size); - context->Unmap(mNativeBuffer, 0); + context->Unmap(mNativeStorage, 0); source->unmap(); } else { - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); D3D11_BOX srcBox; srcBox.left = sourceOffset; @@ -686,16 +748,16 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s srcBox.front = 0; srcBox.back = 1; - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); - ID3D11Buffer *sourceBuffer = static_cast<NativeBuffer11*>(source)->getNativeBuffer(); + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); + ID3D11Buffer *sourceBuffer = static_cast<NativeStorage*>(source)->getNativeStorage(); - context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); + context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); } return createBuffer; } -gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) +gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) { ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -711,7 +773,7 @@ gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result); } - if (mNativeBuffer && preserveData) + if (mNativeStorage && preserveData) { // We don't call resize if the buffer is big enough already. ASSERT(mBufferSize <= size); @@ -724,19 +786,19 @@ gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) srcBox.front = 0; srcBox.back = 1; - context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox); + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); } // No longer need the old buffer - SafeRelease(mNativeBuffer); - mNativeBuffer = newBuffer; + SafeRelease(mNativeStorage); + mNativeStorage = newBuffer; mBufferSize = bufferDesc.ByteWidth; return gl::Error(GL_NO_ERROR); } -void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, +void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize) { bufferDesc->ByteWidth = bufferSize; @@ -754,8 +816,12 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: bufferDesc->Usage = D3D11_USAGE_DEFAULT; bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - if (!renderer->isLevel9()) + + if (renderer->isES3Capable()) + { bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + } + bufferDesc->CPUAccessFlags = 0; break; @@ -782,12 +848,12 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren bufferDesc->ByteWidth = std::min<UINT>(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); break; - default: + default: UNREACHABLE(); } } -void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access) +uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield access) { ASSERT(mUsage == BUFFER_USAGE_STAGING); @@ -796,41 +862,22 @@ void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield acc D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); - HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource); + HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource); UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); - return static_cast<GLubyte*>(mappedResource.pData) + offset; + return static_cast<uint8_t*>(mappedResource.pData) + offset; } -gl::Error Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset) -{ - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result); - } - - uint8_t *offsetBufferPointer = reinterpret_cast<uint8_t *>(mappedResource.pData) + offset; - memcpy(offsetBufferPointer, data, size); - - context->Unmap(mNativeBuffer, 0); - - return gl::Error(GL_NO_ERROR); -} - -void Buffer11::NativeBuffer11::unmap() +void Buffer11::NativeStorage::unmap() { ASSERT(mUsage == BUFFER_USAGE_STAGING); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->Unmap(mNativeBuffer, 0); + context->Unmap(mNativeStorage, 0); } -Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer) - : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK), +Buffer11::PackStorage::PackStorage(Renderer11 *renderer) + : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(NULL), mTextureFormat(DXGI_FORMAT_UNKNOWN), mQueuedPackCommand(NULL), @@ -838,13 +885,13 @@ Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer) { } -Buffer11::PackStorage11::~PackStorage11() +Buffer11::PackStorage::~PackStorage() { SafeRelease(mStagingTexture); SafeDelete(mQueuedPackCommand); } -bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, +bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, size_t size, size_t destOffset) { // We copy through a staging buffer when drawing with a pack buffer, @@ -853,7 +900,7 @@ bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t so return false; } -gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData) +gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData) { if (size != mBufferSize) { @@ -867,7 +914,7 @@ gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData) return gl::Error(GL_NO_ERROR); } -void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access) +uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield access) { ASSERT(offset + length <= getSize()); // TODO: fast path @@ -886,12 +933,12 @@ void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield acce return mMemoryBuffer.data() + offset; } -void Buffer11::PackStorage11::unmap() +void Buffer11::PackStorage::unmap() { // No-op } -gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) { gl::Error error = flushQueuedPackCommand(); if (error.isError()) @@ -963,7 +1010,7 @@ gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT s return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::PackStorage11::flushQueuedPackCommand() +gl::Error Buffer11::PackStorage::flushQueuedPackCommand() { ASSERT(mMemoryBuffer.size() > 0); @@ -980,4 +1027,44 @@ gl::Error Buffer11::PackStorage11::flushQueuedPackCommand() return gl::Error(GL_NO_ERROR); } +Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) + : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) +{} + +bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + ASSERT(source->isMappable()); + const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); + ASSERT(destOffset + size <= mSystemCopy.size()); + memcpy(mSystemCopy.data() + destOffset, sourceData, size); + source->unmap(); + return true; +} + +gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData) +{ + if (mSystemCopy.size() < size) + { + if (!mSystemCopy.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage"); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +uint8_t *Buffer11::SystemMemoryStorage::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size()); + return mSystemCopy.data() + offset; +} + +void Buffer11::SystemMemoryStorage::unmap() +{ + // No-op +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h index 1c06bbf88a..39bafe880e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -6,12 +6,11 @@ // Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. -#ifndef LIBGLESV2_RENDERER_BUFFER11_H_ -#define LIBGLESV2_RENDERER_BUFFER11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" namespace rx { @@ -25,6 +24,7 @@ enum BufferUsage BUFFER_USAGE_PIXEL_UNPACK, BUFFER_USAGE_PIXEL_PACK, BUFFER_USAGE_UNIFORM, + BUFFER_USAGE_SYSTEM_MEMORY, }; struct PackPixelsParams @@ -60,7 +60,6 @@ class Buffer11 : public BufferD3D // BufferD3D implementation virtual size_t getSize() const { return mSize; } virtual bool supportsDirectBinding() const; - RendererD3D *getRenderer() override; // BufferImpl implementation virtual gl::Error setData(const void* data, size_t size, GLenum usage); @@ -72,34 +71,33 @@ class Buffer11 : public BufferD3D virtual void markTransformFeedbackUsage(); private: - DISALLOW_COPY_AND_ASSIGN(Buffer11); - - class BufferStorage11; - class NativeBuffer11; - class PackStorage11; + class BufferStorage; + class NativeStorage; + class PackStorage; + class SystemMemoryStorage; Renderer11 *mRenderer; size_t mSize; - BufferStorage11 *mMappedStorage; + BufferStorage *mMappedStorage; - std::map<BufferUsage, BufferStorage11*> mBufferStorages; + std::map<BufferUsage, BufferStorage*> mBufferStorages; typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair; std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews; - MemoryBuffer mResolvedData; - DataRevision mResolvedDataRevision; unsigned int mReadUsageCount; + bool mHasSystemMemoryStorage; void markBufferUsage(); - NativeBuffer11 *getStagingBuffer(); - PackStorage11 *getPackStorage(); + NativeStorage *getStagingStorage(); + PackStorage *getPackStorage(); + gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut); - BufferStorage11 *getBufferStorage(BufferUsage usage); - BufferStorage11 *getLatestBufferStorage() const; + BufferStorage *getBufferStorage(BufferUsage usage); + BufferStorage *getLatestBufferStorage() const; }; } -#endif // LIBGLESV2_RENDERER_BUFFER11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp index 7185a05506..057c3bed42 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -6,23 +6,28 @@ // Clear11.cpp: Framebuffer clear utility class. -#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" + +#include <algorithm> + +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" // Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" namespace rx { @@ -80,7 +85,7 @@ Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMA Clear11::Clear11(Renderer11 *renderer) : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>), - mVertexBuffer(NULL), mRasterizerState(NULL) + mVertexBuffer(NULL), mRasterizerState(NULL), mSupportsClearView(false) { HRESULT result; ID3D11Device *device = renderer->getDevice(); @@ -104,7 +109,7 @@ Clear11::Clear11(Renderer11 *renderer) rsDesc.DepthBias = 0; rsDesc.DepthBiasClamp = 0.0f; rsDesc.SlopeScaledDepthBias = 0.0f; - rsDesc.DepthClipEnable = renderer->isLevel9(); + rsDesc.DepthClipEnable = TRUE; rsDesc.ScissorEnable = FALSE; rsDesc.MultisampleEnable = FALSE; rsDesc.AntialiasedLineEnable = FALSE; @@ -113,14 +118,29 @@ Clear11::Clear11(Renderer11 *renderer) ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); - mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); - if (mRenderer->isLevel9()) { - memset(&mUintClearShader, 0, sizeof(ClearShader)); - memset(&mIntClearShader, 0, sizeof(ClearShader)); - return; + if (renderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat_FL9); + } + else + { + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); + } + + if (renderer->isES3Capable()) + { + mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); + mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); + } + +#if defined(ANGLE_ENABLE_D3D11_1) + if (renderer->getDeviceContext1IfSupported()) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + mSupportsClearView = (d3d11Options.ClearView != FALSE); } - mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); - mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); +#endif } Clear11::~Clear11() @@ -135,13 +155,16 @@ Clear11::~Clear11() SafeRelease(mFloatClearShader.vertexShader); SafeRelease(mFloatClearShader.pixelShader); - SafeRelease(mUintClearShader.inputLayout); - SafeRelease(mUintClearShader.vertexShader); - SafeRelease(mUintClearShader.pixelShader); + if (mRenderer->isES3Capable()) + { + SafeRelease(mUintClearShader.inputLayout); + SafeRelease(mUintClearShader.vertexShader); + SafeRelease(mUintClearShader.pixelShader); - SafeRelease(mIntClearShader.inputLayout); - SafeRelease(mIntClearShader.vertexShader); - SafeRelease(mIntClearShader.pixelShader); + SafeRelease(mIntClearShader.inputLayout); + SafeRelease(mIntClearShader.vertexShader); + SafeRelease(mIntClearShader.pixelShader); + } for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) { @@ -153,17 +176,28 @@ Clear11::~Clear11() SafeRelease(mRasterizerState); } -gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) +gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) { - // First determine if a scissored clear is needed, this will always require drawing a quad. - // - // Otherwise, iterate over the color buffers which require clearing and determine if they can be - // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: + const auto &colorAttachments = fboData.mColorAttachments; + const auto &drawBufferStates = fboData.mDrawBufferStates; + const auto *depthAttachment = fboData.mDepthAttachment; + const auto *stencilAttachment = fboData.mStencilAttachment; + + ASSERT(colorAttachments.size() == drawBufferStates.size()); + + // Iterate over the color buffers which require clearing and determine if they can be + // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. + // This requires: // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer // render targets as expected but does not work the other way around) // 2) The format of the render target has no color channels that are currently masked out. // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. // + // If these conditions are met, and: + // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView. + // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available. + // Otherwise draw a quad. + // // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView // by checking if the stencil write mask covers the entire stencil. // @@ -171,18 +205,24 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, cons // attribute. gl::Extents framebufferSize; - if (frameBuffer->getFirstColorbuffer() != NULL) + + auto iter = std::find_if(colorAttachments.begin(), colorAttachments.end(), [](const gl::FramebufferAttachment *attachment) { return attachment != nullptr; }); + if (iter != colorAttachments.end()) + { + framebufferSize.width = (*iter)->getWidth(); + framebufferSize.height = (*iter)->getHeight(); + framebufferSize.depth = 1; + } + else if (depthAttachment != nullptr) { - gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); - framebufferSize.width = attachment->getWidth(); - framebufferSize.height = attachment->getHeight(); + framebufferSize.width = depthAttachment->getWidth(); + framebufferSize.height = depthAttachment->getHeight(); framebufferSize.depth = 1; } - else if (frameBuffer->getDepthOrStencilbuffer() != NULL) + else if (stencilAttachment != nullptr) { - gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); - framebufferSize.width = attachment->getWidth(); - framebufferSize.height = attachment->getHeight(); + framebufferSize.width = stencilAttachment->getWidth(); + framebufferSize.height = stencilAttachment->getHeight(); framebufferSize.depth = 1; } else @@ -208,77 +248,96 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, cons RenderTarget11* maskedClearDepthStencil = NULL; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { - if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) + if (clearParams.clearColor[colorAttachment] && + colorAttachments[colorAttachment] != nullptr && + drawBufferStates[colorAttachment] != GL_NONE) { - gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); - if (attachment) + const gl::FramebufferAttachment *attachment = colorAttachments[colorAttachment]; + + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } + return error; + } - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); - if (clearParams.colorClearType == GL_FLOAT && - !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) + if (clearParams.colorClearType == GL_FLOAT && + !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) + { + ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" + "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, + attachment->getInternalFormat()); + } + + if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && + (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && + (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && + (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) + { + // Every channel either does not exist in the render target or is masked out + continue; + } + else if ((!mSupportsClearView && needScissoredClear) || clearParams.colorClearType != GL_FLOAT || + (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable + MaskedRenderTarget maskAndRt; + bool clearColor = clearParams.clearColor[colorAttachment]; + maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); + maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); + maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); + maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); + maskAndRt.renderTarget = renderTarget; + maskedClearRenderTargets.push_back(maskAndRt); + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) { - ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" - "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, - attachment->getInternalFormat()); + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } - if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && - (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && - (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && - (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + + // Check if the actual format has a channel that the internal format does not and set them to the + // default values + const float clearValues[4] = { - // Every channel either does not exist in the render target or is masked out - continue; - } - else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || - (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || - (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || - (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || - (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), + ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + }; + + if (needScissoredClear) { - // A scissored or masked clear is required - MaskedRenderTarget maskAndRt; - bool clearColor = clearParams.clearColor[colorAttachment]; - maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); - maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); - maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); - maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); - maskAndRt.renderTarget = renderTarget; - maskedClearRenderTargets.push_back(maskAndRt); +#if defined(ANGLE_ENABLE_D3D11_1) + // We shouldn't reach here if deviceContext1 is unavailable. + ASSERT(deviceContext1); + + D3D11_RECT rect; + rect.left = clearParams.scissor.x; + rect.right = clearParams.scissor.x + clearParams.scissor.width; + rect.top = clearParams.scissor.y; + rect.bottom = clearParams.scissor.y + clearParams.scissor.height; + + deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); +#endif } else { - // ID3D11DeviceContext::ClearRenderTargetView is possible - - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } - - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - - // Check if the actual format has a channel that the internal format does not and set them to the - // default values - const float clearValues[4] = - { - ((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), - ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - }; - deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } } @@ -287,40 +346,39 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, cons if (clearParams.clearDepth || clearParams.clearStencil) { - gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); - if (attachment) + const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; + ASSERT(attachment != nullptr); + + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } + return error; + } - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); - unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0; - bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0; + bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - if (needScissoredClear || needMaskedStencilClear) + if (needScissoredClear || needMaskedStencilClear) + { + maskedClearDepthStencil = renderTarget; + } + else + { + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) { - maskedClearDepthStencil = renderTarget; + return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); } - else - { - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); - } - UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | - (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); - FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); - UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; + UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; - deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); - } + deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); } } @@ -484,13 +542,13 @@ ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& blendDesc.AlphaToCoverageEnable = FALSE; blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++) { - blendDesc.RenderTarget[i].BlendEnable = FALSE; - blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0], - blendKey.maskChannels[i][1], - blendKey.maskChannels[i][2], - blendKey.maskChannels[i][3]); + blendDesc.RenderTarget[j].BlendEnable = FALSE; + blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[j][0], + blendKey.maskChannels[j][1], + blendKey.maskChannels[j][2], + blendKey.maskChannels[j][3]); } ID3D11Device *device = mRenderer->getDevice(); @@ -508,7 +566,7 @@ ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& } } -ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams) +ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams) { ClearDepthStencilInfo dsKey = { 0 }; dsKey.clearDepth = clearParams.clearDepth; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h index a7e8fea56a..4797ca1aa0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h @@ -6,45 +6,32 @@ // Clear11.h: Framebuffer clear utility class. -#ifndef LIBGLESV2_RENDERER_CLEAR11_H_ -#define LIBGLESV2_RENDERER_CLEAR11_H_ - -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Error.h" +#ifndef LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ #include <map> #include <vector> -namespace gl -{ -class Framebuffer; -} +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" namespace rx { class Renderer11; class RenderTarget11; +struct ClearParameters; -class Clear11 +class Clear11 : angle::NonCopyable { public: explicit Clear11(Renderer11 *renderer); ~Clear11(); // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. - gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer); + gl::Error clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData); private: - Renderer11 *mRenderer; - - struct ClearBlendInfo - { - bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; - }; - typedef bool (*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); - typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap; - ClearBlendStateMap mClearBlendStates; - struct MaskedRenderTarget { bool colorMask[4]; @@ -52,6 +39,7 @@ class Clear11 }; ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts); + ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams); struct ClearShader { @@ -59,13 +47,24 @@ class Clear11 ID3D11VertexShader *vertexShader; ID3D11PixelShader *pixelShader; }; + + template <unsigned int vsSize, unsigned int psSize> + static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]); + + Renderer11 *mRenderer; + + struct ClearBlendInfo + { + bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); + typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap; + ClearBlendStateMap mClearBlendStates; + ClearShader mFloatClearShader; ClearShader mUintClearShader; ClearShader mIntClearShader; - template <unsigned int vsSize, unsigned int psSize> - static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]); - struct ClearDepthStencilInfo { bool clearDepth; @@ -76,12 +75,12 @@ class Clear11 typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap; ClearDepthStencilStateMap mClearDepthStencilStates; - ID3D11DepthStencilState *getDepthStencilState(const gl::ClearParameters &clearParams); - ID3D11Buffer *mVertexBuffer; ID3D11RasterizerState *mRasterizerState; + + bool mSupportsClearView; }; } -#endif // LIBGLESV2_RENDERER_CLEAR11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp new file mode 100644 index 0000000000..f1fe2bb2c7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -0,0 +1,119 @@ +// +// Copyright 2015 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. +// +// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations. +// + +#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +DebugAnnotator11::DebugAnnotator11() + : mInitialized(false), + mD3d11Module(nullptr), + mUserDefinedAnnotation(nullptr) +{ + // D3D11 devices can't be created during DllMain. + // We defer device creation until the object is actually used. +} + +DebugAnnotator11::~DebugAnnotator11() +{ + if (mInitialized) + { +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mUserDefinedAnnotation); +#endif + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + FreeLibrary(mD3d11Module); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + } +} + +void DebugAnnotator11::beginEvent(const std::wstring &eventName) +{ + initializeDevice(); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->BeginEvent(eventName.c_str()); +#endif +} + +void DebugAnnotator11::endEvent() +{ + initializeDevice(); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->EndEvent(); +#endif +} + +void DebugAnnotator11::setMarker(const std::wstring &markerName) +{ + initializeDevice(); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->SetMarker(markerName.c_str()); +#endif +} + +bool DebugAnnotator11::getStatus() +{ + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. + +#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + // 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 != nullptr); + SafeRelease(graphicsAnalysis); + return underCapture; +#endif // _DEBUG && !ANGLE_ENABLE_WINDOWS_STORE + + // Otherwise, we have to return true here. + return true; +} + +void DebugAnnotator11::initializeDevice() +{ + if (!mInitialized) + { +#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 != nullptr); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + + ID3D11Device *device = nullptr; + ID3D11DeviceContext *context = nullptr; + + 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, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context); + ASSERT(SUCCEEDED(hr)); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context); + ASSERT(mUserDefinedAnnotation != nullptr); +#endif + + SafeRelease(device); + SafeRelease(context); + + mInitialized = true; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h new file mode 100644 index 0000000000..3df62b015c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h @@ -0,0 +1,39 @@ +// +// Copyright 2015 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. +// +// DebugAnnotator11.h: D3D11 helpers for adding trace annotations. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ + +#include "common/debug.h" + +struct ID3DUserDefinedAnnotation; + +namespace rx +{ + +class DebugAnnotator11 : public gl::DebugAnnotator +{ + public: + DebugAnnotator11(); + ~DebugAnnotator11() override; + void beginEvent(const std::wstring &eventName) override; + void endEvent() override; + void setMarker(const std::wstring &markerName) override; + bool getStatus() override; + + private: + void initializeDevice(); + + bool mInitialized; + HMODULE mD3d11Module; + ID3DUserDefinedAnnotation *mUserDefinedAnnotation; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp index f44d934056..8552bc2beb 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp @@ -6,9 +6,8 @@ // Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. -#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "common/utilities.h" @@ -99,7 +98,7 @@ gl::Error FenceNV11::finishFence(GLboolean *outFinished) return error; } - Sleep(0); + ScheduleYield(); } return gl::Error(GL_NO_ERROR); @@ -179,8 +178,8 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou while (currentCounter.QuadPart < endCounter && !result) { - Sleep(0); - BOOL success = QueryPerformanceCounter(¤tCounter); + ScheduleYield(); + success = QueryPerformanceCounter(¤tCounter); UNUSED_ASSERTION_VARIABLE(success); ASSERT(success); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h index 1223a53b90..2d87f43e76 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h @@ -6,10 +6,11 @@ // Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. -#ifndef LIBGLESV2_RENDERER_FENCE11_H_ -#define LIBGLESV2_RENDERER_FENCE11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ -#include "libGLESv2/renderer/FenceImpl.h" +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" namespace rx { @@ -26,8 +27,6 @@ class FenceNV11 : public FenceNVImpl gl::Error finishFence(GLboolean *outFinished); private: - DISALLOW_COPY_AND_ASSIGN(FenceNV11); - template<class T> friend gl::Error FenceSetHelper(T *fence); template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); @@ -47,8 +46,6 @@ class FenceSync11 : public FenceSyncImpl gl::Error getStatus(GLint *outResult); private: - DISALLOW_COPY_AND_ASSIGN(FenceSync11); - template<class T> friend gl::Error FenceSetHelper(T *fence); template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); @@ -59,4 +56,4 @@ class FenceSync11 : public FenceSyncImpl } -#endif // LIBGLESV2_RENDERER_FENCE11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp new file mode 100644 index 0000000000..da01f320c0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -0,0 +1,270 @@ +// +// Copyright 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. +// + +// Framebuffer11.cpp: Implements the Framebuffer11 class. + +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" + +namespace rx +{ + +Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer) + : FramebufferD3D(data, renderer), + mRenderer(renderer) +{ + ASSERT(mRenderer != nullptr); +} + +Framebuffer11::~Framebuffer11() +{ +} + +static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachment) +{ + if (attachment && attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + + TextureStorage *texStorage = NULL; + gl::Error error = textureD3D->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + if (texStorage) + { + TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); + ASSERT(texStorage11); + + texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel()); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::invalidateSwizzles() const +{ + for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { + gl::FramebufferAttachment *colorAttachment = *it; + gl::Error error = InvalidateAttachmentSwizzles(colorAttachment); + if (error.isError()) + { + return error; + } + } + + gl::Error error = InvalidateAttachmentSwizzles(mData.mDepthAttachment); + if (error.isError()) + { + return error; + } + + error = InvalidateAttachmentSwizzles(mData.mStencilAttachment); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams) +{ + Clear11 *clearer = mRenderer->getClearer(); + gl::Error error = clearer->clearFramebuffer(clearParams, mData); + if (error.isError()) + { + return error; + } + + error = invalidateSwizzles(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +static gl::Error getRenderTargetResource(const gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, + ID3D11Texture2D **texture2DOut) +{ + ASSERT(colorbuffer); + + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + ASSERT(renderTargetResource); + + *subresourceIndexOut = renderTarget->getSubresourceIndex(); + *texture2DOut = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTargetResource); + + if (!(*texture2DOut)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget"); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +{ + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + const gl::FramebufferAttachment *colorbuffer = mData.getReadAttachment(); + ASSERT(colorbuffer); + + gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); + if (error.isError()) + { + return error; + } + + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != NULL) + { + Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); + PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels)); + + error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + if (error.isError()) + { + SafeRelease(colorBufferTexture); + return error; + } + + packBuffer->getIndexRangeCache()->clear(); + } + else + { + error = mRenderer->readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + if (error.isError()) + { + SafeRelease(colorBufferTexture); + return error; + } + } + + SafeRelease(colorBufferTexture); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) +{ + if (blitRenderTarget) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorbuffer(); + ASSERT(readBuffer); + + RenderTargetD3D *readRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++) + { + if (mData.mColorAttachments[colorAttachment] != nullptr && + mData.mDrawBufferStates[colorAttachment] != GL_NONE) + { + const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[colorAttachment]; + + RenderTargetD3D *drawRenderTarget = NULL; + error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, + filter, scissor, blitRenderTarget, false, false); + if (error.isError()) + { + return error; + } + } + } + } + + if (blitDepth || blitStencil) + { + gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTargetD3D *readRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + ASSERT(drawBuffer); + + RenderTargetD3D *drawRenderTarget = NULL; + error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, filter, scissor, + false, blitDepth, blitStencil); + if (error.isError()) + { + return error; + } + } + + gl::Error error = invalidateSwizzles(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget11 *renderTarget11 = RenderTarget11::makeRenderTarget11(renderTarget); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat()); + return dxgiFormatInfo.internalFormat; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h new file mode 100644 index 0000000000..07fa480fa2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -0,0 +1,45 @@ +// +// Copyright 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. +// + +// Framebuffer11.h: Defines the Framebuffer11 class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ +class Renderer11; + +class Framebuffer11 : public FramebufferD3D +{ + public: + Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer); + virtual ~Framebuffer11(); + + // Invalidate the cached swizzles of all bound texture attachments. + gl::Error invalidateSwizzles() const; + + private: + gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; + + gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, + const gl::PixelPackState &pack, uint8_t *pixels) const override; + + gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) override; + + + GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + + Renderer11 *const mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp index e6f3e90683..956b78b5a6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -7,23 +7,23 @@ // Image11.h: Implements the rx::Image11 class, which acts as the interface to // the actual underlying resources of a Texture -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" #include "common/utilities.h" namespace rx { -Image11::Image11() - : mRenderer(NULL), +Image11::Image11(Renderer11 *renderer) + : mRenderer(renderer), mDXGIFormat(DXGI_FORMAT_UNKNOWN), mStagingTexture(NULL), mStagingSubresource(0), @@ -31,8 +31,10 @@ Image11::Image11() mAssociatedStorage(NULL), mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), mRecoveredFromStorageCount(0) - { + // mRenderer should remain unchanged during the lifetime of the Image11 object. + // This lets us safely use mRenderer (and its Feature Level) in Image11's methods. + mFeatureLevel = renderer->getFeatureLevel(); } Image11::~Image11() @@ -41,7 +43,7 @@ Image11::~Image11() releaseStagingTexture(); } -Image11 *Image11::makeImage11(Image *img) +Image11 *Image11::makeImage11(ImageD3D *img) { ASSERT(HAS_DYNAMIC_TYPE(Image11*, img)); return static_cast<Image11*>(img); @@ -92,7 +94,7 @@ bool Image11::isDirty() const // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage // AND the texture doesn't require init data (i.e. a blank new texture will suffice) // then isDirty should still return false. - if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)) + if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL)) { return false; } @@ -201,10 +203,10 @@ void Image11::disassociateStorage() } } -bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) { - if (mWidth != width || - mHeight != height || + if (mWidth != size.width || + mHeight != size.height || mInternalFormat != internalformat || forceRelease) { @@ -213,19 +215,15 @@ bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalform disassociateStorage(); mRecoveredFromStorageCount = 0; - mRenderer = Renderer11::makeRenderer11(renderer); - - mWidth = width; - mHeight = height; - mDepth = depth; + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; mInternalFormat = internalformat; mTarget = target; // compute the d3d format that will be used - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mFeatureLevel); mDXGIFormat = formatInfo.texFormat; - mActualFormat = dxgiFormatInfo.internalFormat; mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); releaseStagingTexture(); @@ -248,17 +246,16 @@ DXGI_FORMAT Image11::getDXGIFormat() const // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input // into the target pixel rectangle. -gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) +gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel); LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); D3D11_MAPPED_SUBRESOURCE mappedImage; @@ -268,8 +265,8 @@ gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei return error; } - uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); - loadFunction(width, height, depth, + uint8_t *offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch)); + loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); @@ -278,22 +275,21 @@ gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei return gl::Error(GL_NO_ERROR); } -gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) +gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); + GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; - ASSERT(xoffset % outputBlockWidth == 0); - ASSERT(yoffset % outputBlockHeight == 0); + ASSERT(area.x % outputBlockWidth == 0); + ASSERT(area.y % outputBlockHeight == 0); - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel); LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); D3D11_MAPPED_SUBRESOURCE mappedImage; @@ -303,11 +299,11 @@ gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffse return error; } - uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + - (xoffset / outputBlockWidth) * outputPixelSize + - zoffset * mappedImage.DepthPitch); + uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((area.y / outputBlockHeight) * mappedImage.RowPitch + + (area.x / outputBlockWidth) * outputPixelSize + + area.z * mappedImage.DepthPitch); - loadFunction(width, height, depth, + loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); @@ -316,27 +312,23 @@ gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffse return gl::Error(GL_NO_ERROR); } -gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) +gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) { RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source); ASSERT(sourceRenderTarget->getTexture()); + ID3D11Resource *resource = sourceRenderTarget->getTexture(); UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex(); - ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(sourceRenderTarget->getTexture()); - - if (!sourceTexture2D) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source RenderTarget."); - } - gl::Error error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex); + gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); + gl::Error error = copy(destOffset, sourceBox, resource, subresourceIndex); - SafeRelease(sourceTexture2D); + SafeRelease(resource); return error; } -gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) +gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) { TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source); @@ -348,26 +340,52 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R return error; } - ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); + error = copy(destOffset, sourceArea, resource, subresourceIndex); - if (!sourceTexture2D) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source TextureStorage."); - } - - error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex); - - SafeRelease(sourceTexture2D); + SafeRelease(resource); return error; } -gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource) +gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource) { - D3D11_TEXTURE2D_DESC textureDesc; - source->GetDesc(&textureDesc); + D3D11_RESOURCE_DIMENSION dim; + source->GetType(&dim); + + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + gl::Extents extents; + UINT sampleCount = 0; + + ID3D11Texture2D *source2D = NULL; - if (textureDesc.Format == mDXGIFormat) + if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + D3D11_TEXTURE2D_DESC textureDesc2D; + source2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(source); + ASSERT(source2D); + source2D->GetDesc(&textureDesc2D); + + format = textureDesc2D.Format; + extents = gl::Extents(textureDesc2D.Width, textureDesc2D.Height, 1); + sampleCount = textureDesc2D.SampleDesc.Count; + } + else if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D) + { + D3D11_TEXTURE3D_DESC textureDesc3D; + ID3D11Texture3D *source3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(source); + ASSERT(source3D); + source3D->GetDesc(&textureDesc3D); + + format = textureDesc3D.Format; + extents = gl::Extents(textureDesc3D.Width, textureDesc3D.Height, textureDesc3D.Depth); + sampleCount = 1; + } + else + { + UNREACHABLE(); + } + + if (format == mDXGIFormat) { // No conversion needed-- use copyback fastpath ID3D11Resource *stagingTexture = NULL; @@ -383,15 +401,18 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R UINT subresourceAfterResolve = sourceSubResource; - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) + ID3D11Resource *srcTex = NULL; + + bool needResolve = (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D && sampleCount > 1); + + if (needResolve) { D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; + resolveDesc.Width = extents.width; + resolveDesc.Height = extents.height; resolveDesc.MipLevels = 1; resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; + resolveDesc.Format = format; resolveDesc.SampleDesc.Count = 1; resolveDesc.SampleDesc.Quality = 0; resolveDesc.Usage = D3D11_USAGE_DEFAULT; @@ -399,13 +420,15 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R resolveDesc.CPUAccessFlags = 0; resolveDesc.MiscFlags = 0; - HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); + ID3D11Texture2D *srcTex2D = NULL; + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D); if (FAILED(result)) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); } + srcTex = srcTex2D; - deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format); + deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, format); subresourceAfterResolve = 0; } else @@ -418,12 +441,13 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R srcBox.right = sourceArea.x + sourceArea.width; srcBox.top = sourceArea.y; srcBox.bottom = sourceArea.y + sourceArea.height; - srcBox.front = 0; - srcBox.back = 1; + srcBox.front = sourceArea.z; + srcBox.back = sourceArea.z + sourceArea.depth; - deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox); + deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, destOffset.y, + destOffset.z, srcTex, subresourceAfterResolve, &srcBox); - if (textureDesc.SampleDesc.Count > 1) + if (needResolve) { SafeRelease(srcTex); } @@ -439,12 +463,18 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R } // determine the offset coordinate into the destination buffer - GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset; - uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; + uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch; const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + // Currently in ANGLE, the source data may only need to be converted if the source is the current framebuffer + // and OpenGL ES framebuffers must be 2D textures therefore we should not need to convert 3D textures between different formats. + ASSERT(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D); + ASSERT(sourceArea.z == 0 && sourceArea.depth == 1); + gl::Rectangle sourceRect(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height); + error = mRenderer->readTextureData(source2D, sourceSubResource, sourceRect, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); unmap(); @@ -513,11 +543,11 @@ gl::Error Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) + if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL) { std::vector<D3D11_SUBRESOURCE_DATA> initialData; std::vector< std::vector<BYTE> > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, + d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, mDepth, lodOffset + 1, &initialData, &textureData); result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); @@ -553,11 +583,11 @@ gl::Error Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) + if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL) { std::vector<D3D11_SUBRESOURCE_DATA> initialData; std::vector< std::vector<BYTE> > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, + d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, 1, lodOffset + 1, &initialData, &textureData); result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h index a936e6d7b2..5734f73b15 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h @@ -7,11 +7,11 @@ // Image11.h: Defines the rx::Image11 class, which acts as the interface to // the actual underlying resources of a Texture -#ifndef LIBGLESV2_RENDERER_IMAGE11_H_ -#define LIBGLESV2_RENDERER_IMAGE11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ -#include "libGLESv2/renderer/d3d/ImageD3D.h" -#include "libGLESv2/ImageIndex.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/ImageIndex.h" #include "common/debug.h" @@ -28,10 +28,10 @@ class TextureStorage11; class Image11 : public ImageD3D { public: - Image11(); + Image11(Renderer11 *renderer); virtual ~Image11(); - static Image11 *makeImage11(Image *img); + static Image11 *makeImage11(ImageD3D *img); static gl::Error generateMipmap(Image11 *dest, Image11 *src); @@ -39,17 +39,15 @@ class Image11 : public ImageD3D virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); - bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override; + bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; DXGI_FORMAT getDXGIFormat() const; - virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input); - virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input); + virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source); + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source); gl::Error recoverFromAssociatedStorage(); @@ -61,16 +59,15 @@ class Image11 : public ImageD3D void unmap(); private: - DISALLOW_COPY_AND_ASSIGN(Image11); - gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box ®ion); - gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource); + gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource); gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); gl::Error createStagingTexture(); void releaseStagingTexture(); Renderer11 *mRenderer; + D3D_FEATURE_LEVEL mFeatureLevel; DXGI_FORMAT mDXGIFormat; ID3D11Resource *mStagingTexture; @@ -84,4 +81,4 @@ class Image11 : public ImageD3D } -#endif // LIBGLESV2_RENDERER_IMAGE11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp index 9a61182ee9..99c199f2b9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -6,8 +6,8 @@ // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. -#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h index 3351df5ec1..eadd03eb76 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h @@ -6,10 +6,10 @@ // IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ -#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" namespace rx { @@ -38,8 +38,6 @@ class IndexBuffer11 : public IndexBuffer ID3D11Buffer *getBuffer() const; private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); - Renderer11 *const mRenderer; ID3D11Buffer *mBuffer; @@ -50,4 +48,4 @@ class IndexBuffer11 : public IndexBuffer } -#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_
\ No newline at end of file +#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp new file mode 100644 index 0000000000..242c09d6ce --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -0,0 +1,430 @@ +// +// Copyright (c) 2012 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. +// + +// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" + +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +{ + for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; + + if (translatedAttributes[attributeIndex].active) + { + inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, + translatedAttribute.currentValueType); + } + } +} + +const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; + +InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) +{ + mCounter = 0; + mDevice = NULL; + mDeviceContext = NULL; + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = NULL; + mCurrentVertexStrides[i] = static_cast<UINT>(-1); + mCurrentVertexOffsets[i] = static_cast<UINT>(-1); + } + mPointSpriteVertexBuffer = NULL; + mPointSpriteIndexBuffer = NULL; +} + +InputLayoutCache::~InputLayoutCache() +{ + clear(); +} + +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) +{ + clear(); + mDevice = device; + mDeviceContext = context; + mFeatureLevel = device->GetFeatureLevel(); +} + +void InputLayoutCache::clear() +{ + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + SafeRelease(i->second.inputLayout); + } + mInputLayoutMap.clear(); + SafeRelease(mPointSpriteVertexBuffer); + SafeRelease(mPointSpriteIndexBuffer); + markDirty(); +} + +void InputLayoutCache::markDirty() +{ + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = NULL; + mCurrentVertexStrides[i] = static_cast<UINT>(-1); + mCurrentVertexOffsets[i] = static_cast<UINT>(-1); + } +} + +gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + GLenum mode, gl::Program *program) +{ + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); + + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; + programD3D->sortAttributesByLayout(attributes, sortedSemanticIndices); + bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); + + if (!mDevice || !mDeviceContext) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized."); + } + + InputLayoutKey ilKey = { 0 }; + + static const char* semanticName = "TEXCOORD"; + + unsigned int firstIndexedElement = gl::MAX_VERTEX_ATTRIBS; + unsigned int firstInstancedElement = gl::MAX_VERTEX_ATTRIBS; + unsigned int nextAvailableInputSlot = 0; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + // If rendering points and instanced pointsprite emulation is being used, the inputClass is required to be configured as per instance data + inputClass = instancedPointSpritesActive ? D3D11_INPUT_PER_INSTANCE_DATA : inputClass; + + gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel); + + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLint attributeSize; + program->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + + ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; + ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; + ilKey.elements[ilKey.elementCount].desc.InputSlot = i; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = instancedPointSpritesActive ? 1 : attributes[i].divisor; + + if (inputClass == D3D11_INPUT_PER_VERTEX_DATA && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS) + { + firstIndexedElement = ilKey.elementCount; + } + else if (inputClass == D3D11_INPUT_PER_INSTANCE_DATA && firstInstancedElement == gl::MAX_VERTEX_ATTRIBS) + { + firstInstancedElement = ilKey.elementCount; + } + + ilKey.elementCount++; + nextAvailableInputSlot = i + 1; + } + } + + // Instanced PointSprite emulation requires additional entries in the + // inputlayout to support the vertices that make up the pointsprite quad. + // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the input layout must match the shader + if (programUsesInstancedPointSprites) + { + ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITEPOSITION"; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0; + ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32B32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0; + + // The new elements are D3D11_INPUT_PER_VERTEX_DATA data so the indexed element + // tracking must be applied. This ensures that the instancing specific + // buffer swapping logic continues to work. + if (firstIndexedElement == gl::MAX_VERTEX_ATTRIBS) + { + firstIndexedElement = ilKey.elementCount; + } + + ilKey.elementCount++; + + ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITETEXCOORD"; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0; + ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = sizeof(float) * 3; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0; + + ilKey.elementCount++; + } + + // On 9_3, we must ensure that slot 0 contains non-instanced data. + // If slot 0 currently contains instanced data then we swap it with a non-instanced element. + // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3 doesn't support OpenGL ES 3.0. + // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced simultaneously, so a non-instanced element must exist. + ASSERT(!(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS)); + bool moveFirstIndexedIntoSlotZero = mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstInstancedElement == 0 && firstIndexedElement != gl::MAX_VERTEX_ATTRIBS; + + if (moveFirstIndexedIntoSlotZero) + { + ilKey.elements[firstInstancedElement].desc.InputSlot = ilKey.elements[firstIndexedElement].desc.InputSlot; + ilKey.elements[firstIndexedElement].desc.InputSlot = 0; + + // Instanced PointSprite emulation uses multiple layout entries across a single vertex buffer. + // If an index swap is performed, we need to ensure that all elements get the proper InputSlot. + if (programUsesInstancedPointSprites) + { + ilKey.elements[firstIndexedElement + 1].desc.InputSlot = 0; + } + } + + ID3D11InputLayout *inputLayout = NULL; + + InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); + if (keyIter != mInputLayoutMap.end()) + { + inputLayout = keyIter->second.inputLayout; + keyIter->second.lastUsedTime = mCounter++; + } + else + { + gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; + GetInputLayout(attributes, shaderInputLayout); + + ShaderExecutableD3D *shader = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *shader11 = ShaderExecutable11::makeShaderExecutable11(shader); + + D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; + for (unsigned int j = 0; j < ilKey.elementCount; ++j) + { + descs[j] = ilKey.elements[j].desc; + } + + HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); + } + + if (mInputLayoutMap.size() >= kMaxInputLayouts) + { + TRACE("Overflowed the limit of %u input layouts, removing the least recently used " + "to make room.", kMaxInputLayouts); + + InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.inputLayout); + mInputLayoutMap.erase(leastRecentlyUsed); + } + + InputLayoutCounterPair inputCounterPair; + inputCounterPair.inputLayout = inputLayout; + inputCounterPair.lastUsedTime = mCounter++; + + mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + bool dirtyBuffers = false; + size_t minDiff = gl::MAX_VERTEX_ATTRIBS; + size_t maxDiff = 0; + unsigned int nextAvailableIndex = 0; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + ID3D11Buffer *buffer = NULL; + + if (attributes[i].active) + { + VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); + Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; + + buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) + : vertexBuffer->getBuffer(); + } + + UINT vertexStride = attributes[i].stride; + UINT vertexOffset = attributes[i].offset; + + if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || + vertexOffset != mCurrentVertexOffsets[i]) + { + dirtyBuffers = true; + minDiff = std::min(minDiff, static_cast<size_t>(i)); + maxDiff = std::max(maxDiff, static_cast<size_t>(i)); + + mCurrentBuffers[i] = buffer; + mCurrentVertexStrides[i] = vertexStride; + mCurrentVertexOffsets[i] = vertexOffset; + + // If a non null ID3D11Buffer is being assigned to mCurrentBuffers, + // then the next available index needs to be tracked to ensure + // that any instanced pointsprite emulation buffers will be properly packed. + if (buffer) + { + nextAvailableIndex = i + 1; + } + } + } + + // Instanced PointSprite emulation requires two additional ID3D11Buffers. + // A vertex buffer needs to be created and added to the list of current buffers, + // strides and offsets collections. This buffer contains the vertices for a single + // PointSprite quad. + // An index buffer also needs to be created and applied because rendering instanced + // data on D3D11 FL9_3 requires DrawIndexedInstanced() to be used. + if (instancedPointSpritesActive) + { + HRESULT result = S_OK; + const UINT pointSpriteVertexStride = sizeof(float) * 5; + + if (!mPointSpriteVertexBuffer) + { + static const float pointSpriteVertices[] = + { + // Position // TexCoord + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + }; + + D3D11_SUBRESOURCE_DATA vertexBufferData = { pointSpriteVertices, 0, 0 }; + D3D11_BUFFER_DESC vertexBufferDesc; + vertexBufferDesc.ByteWidth = sizeof(pointSpriteVertices); + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexBufferDesc.CPUAccessFlags = 0; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result); + } + } + + mCurrentBuffers[nextAvailableIndex] = mPointSpriteVertexBuffer; + mCurrentVertexStrides[nextAvailableIndex] = pointSpriteVertexStride; + mCurrentVertexOffsets[nextAvailableIndex] = 0; + + if (!mPointSpriteIndexBuffer) + { + // Create an index buffer and set it for pointsprite rendering + static const unsigned short pointSpriteIndices[] = + { + 0, 1, 2, 3, 4, 5, + }; + + D3D11_SUBRESOURCE_DATA indexBufferData = { pointSpriteIndices, 0, 0 }; + D3D11_BUFFER_DESC indexBufferDesc; + indexBufferDesc.ByteWidth = sizeof(pointSpriteIndices); + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + indexBufferDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer); + if (FAILED(result)) + { + SafeRelease(mPointSpriteVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result); + } + } + + // The index buffer is applied here because Instanced PointSprite emulation uses + // the a non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer() + // on the renderer will not be called and setting this buffer here ensures that the rendering + // path will contain the correct index buffers. + mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + } + + if (moveFirstIndexedIntoSlotZero) + { + // In this case, we swapped the slots of the first instanced element and the first indexed element, to ensure + // that the first slot contains non-instanced data (required by Feature Level 9_3). + // We must also swap the corresponding buffers sent to IASetVertexBuffers so that the correct data is sent to each slot. + std::swap(mCurrentBuffers[firstIndexedElement], mCurrentBuffers[firstInstancedElement]); + std::swap(mCurrentVertexStrides[firstIndexedElement], mCurrentVertexStrides[firstInstancedElement]); + std::swap(mCurrentVertexOffsets[firstIndexedElement], mCurrentVertexOffsets[firstInstancedElement]); + } + + if (dirtyBuffers) + { + ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); + mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, + mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); + } + + return gl::Error(GL_NO_ERROR); +} + +std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) +{ + static const unsigned int seed = 0xDEADBEEF; + + std::size_t hash = 0; + MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); + return hash; +} + +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +{ + if (a.elementCount != b.elementCount) + { + return false; + } + + return std::equal(a.begin(), a.end(), b.begin()); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h index cc71ac3f6f..2c94c57595 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -7,11 +7,11 @@ // InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches // D3D11 input layouts. -#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ -#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ -#include "libGLESv2/Constants.h" -#include "libGLESv2/Error.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" #include "common/angleutils.h" #include <GLES2/gl2.h> @@ -21,14 +21,14 @@ namespace gl { -class ProgramBinary; +class Program; } namespace rx { struct TranslatedAttribute; -class InputLayoutCache +class InputLayoutCache : angle::NonCopyable { public: InputLayoutCache(); @@ -39,11 +39,9 @@ class InputLayoutCache void markDirty(); gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary); + GLenum mode, gl::Program *program); private: - DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); - struct InputLayoutElement { D3D11_INPUT_ELEMENT_DESC desc; @@ -77,6 +75,9 @@ class InputLayoutCache UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + ID3D11Buffer *mPointSpriteVertexBuffer; + ID3D11Buffer *mPointSpriteIndexBuffer; + static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); @@ -94,8 +95,9 @@ class InputLayoutCache ID3D11Device *mDevice; ID3D11DeviceContext *mDeviceContext; + D3D_FEATURE_LEVEL mFeatureLevel; }; } -#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h index c4a0e42bcc..81b9ea748d 100644 --- a/src/3rdparty/angle/src/common/NativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h @@ -9,13 +9,14 @@ // It is used for HWND (Desktop Windows) and IInspectable objects //(Windows Store Applications). -#ifndef COMMON_NATIVEWINDOW_H_ -#define COMMON_NATIVEWINDOW_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ -#include <EGL/eglplatform.h> #include "common/debug.h" #include "common/platform.h" +#include <EGL/eglplatform.h> + // DXGISwapChain and DXGIFactory are typedef'd to specific required // types. The HWND NativeWindow implementation requires IDXGISwapChain // and IDXGIFactory and the Windows Store NativeWindow @@ -47,28 +48,26 @@ namespace rx class NativeWindow { -public: - explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); + public: + enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 }; + explicit NativeWindow(EGLNativeWindowType window); bool initialize(); bool getClientRect(LPRECT rect); bool isIconic(); - -# if defined(ANGLE_ENABLE_D3D11) - typedef ID3D11Device Device; -#else - typedef IDirect3DDevice9 Device; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + RotationFlags rotationFlags() const; #endif - HRESULT createSwapChain(Device* device, DXGIFactory* factory, + static bool isValidNativeWindow(EGLNativeWindowType window); + + 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; @@ -76,7 +75,6 @@ public: }; -bool IsValidEGLNativeWindowType(EGLNativeWindowType window); } -#endif // COMMON_NATIVEWINDOW_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp index 6a3d3475ee..5fd5237d90 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -9,24 +9,24 @@ // Used to implement pixel transfers from unpack and to pack buffers. // -#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Context.h" +#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" // Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" namespace rx { @@ -133,13 +133,10 @@ gl::Error PixelTransfer11::loadResources() return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); } - if (!mRenderer->isLevel9()) + mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); + if (!mBufferToTextureGS) { - mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); - if (!mBufferToTextureGS) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); - } + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); } gl::Error error = buildShaderMap(); @@ -167,17 +164,18 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment); unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); - parametersOut->FirstPixelOffset = offset; - parametersOut->PixelsPerRow = static_cast<unsigned int>(destArea.width); + parametersOut->FirstPixelOffset = offset / bytesPerPixel; + parametersOut->PixelsPerRow = static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width); parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height); parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; parametersOut->PositionOffset[1] = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; parametersOut->PositionScale[0] = 2.0f / static_cast<float>(destSize.width); parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height); + parametersOut->FirstSlice = destArea.z; } -gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, +gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { gl::Error error = loadResources(); @@ -202,9 +200,9 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac // The SRV must be in the proper read format, which may be different from the destination format // EG: for half float data, we can load full precision floats with implicit conversion GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; - GLenum sourceFormat = gl::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat; + GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); - const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat); + const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getFeatureLevel()); DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h index 29552140bb..1672121ec7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h @@ -8,10 +8,10 @@ // Buffer-to-Texture and Texture-to-Buffer data transfers. // Used to implement pixel unpack and pixel pack buffers in ES3. -#ifndef LIBGLESV2_PIXELTRANSFER11_H_ -#define LIBGLESV2_PIXELTRANSFER11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include "common/platform.h" @@ -32,7 +32,7 @@ struct PixelUnpackState; namespace rx { class Renderer11; -class RenderTarget; +class RenderTargetD3D; class PixelTransfer11 { @@ -45,7 +45,7 @@ class PixelTransfer11 // destRenderTarget: individual slice/layer of a target texture // destinationFormat/sourcePixelsType: determines shaders + shader parameters // destArea: the sub-section of destRenderTarget to copy to - gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); private: @@ -60,6 +60,7 @@ class PixelTransfer11 float PositionScale[2]; int TexLocationOffset[2]; int TexLocationScale[2]; + unsigned int FirstSlice; }; static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, @@ -85,4 +86,4 @@ class PixelTransfer11 } -#endif // LIBGLESV2_PIXELTRANSFER11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp index 17ab1f8ab3..4979ff51a9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -6,14 +6,20 @@ // Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. -#include "libGLESv2/renderer/d3d/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d11/Query11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "common/utilities.h" #include <GLES2/gl2ext.h> +#if defined(ANGLE_MINGW32_COMPAT) +typedef struct D3D11_QUERY_DATA_SO_STATISTICS { + UINT64 NumPrimitivesWritten; + UINT64 PrimitivesStorageNeeded; +} D3D11_QUERY_DATA_SO_STATISTICS; +#endif + namespace rx { @@ -73,7 +79,7 @@ gl::Error Query11::getResult(GLuint *params) if (!mQueryFinished) { - Sleep(0); + ScheduleYield(); } } @@ -145,8 +151,9 @@ gl::Error Query11::testQuery() break; } - if (!mQueryFinished && mRenderer->testDeviceLost(true)) + if (!mQueryFinished && mRenderer->testDeviceLost()) { + mRenderer->notifyDeviceLost(); return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h index f9ff467873..bd53fed250 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h @@ -6,10 +6,10 @@ // Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. -#ifndef LIBGLESV2_RENDERER_QUERY11_H_ -#define LIBGLESV2_RENDERER_QUERY11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ -#include "libGLESv2/renderer/QueryImpl.h" +#include "libANGLE/renderer/QueryImpl.h" namespace rx { @@ -27,8 +27,6 @@ class Query11 : public QueryImpl virtual gl::Error isResultAvailable(GLuint *available); private: - DISALLOW_COPY_AND_ASSIGN(Query11); - gl::Error testQuery(); GLuint mResult; @@ -41,4 +39,4 @@ class Query11 : public QueryImpl } -#endif // LIBGLESV2_RENDERER_QUERY11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp index ab4f60bd98..4990e6bc6e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -7,14 +7,16 @@ // RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render // state objects. -#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" -#include "common/debug.h" +#include <float.h> +#include "common/debug.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "third_party/murmurhash/MurmurHash3.h" namespace rx @@ -92,7 +94,8 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co bool mrt = false; - const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(mRenderer->getWorkarounds()); + const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); BlendStateKey key = { 0 }; key.blendState = blendState; @@ -422,6 +425,16 @@ gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState samplerDesc.MinLOD = samplerState.minLod; samplerDesc.MaxLOD = samplerState.maxLod; + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX. + // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves. + ASSERT(samplerState.maxLod >= 999.9f); + + // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this. + samplerDesc.MaxLOD = FLT_MAX; + } + ID3D11SamplerState *dx11SamplerState = NULL; HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); if (FAILED(result) || !dx11SamplerState) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h index dfd1d84265..0099b94a04 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -7,11 +7,11 @@ // RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render // state objects. -#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ -#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" #include "common/angleutils.h" #include <unordered_map> @@ -25,7 +25,7 @@ namespace rx { class Renderer11; -class RenderStateCache +class RenderStateCache : angle::NonCopyable { public: RenderStateCache(Renderer11 *renderer); @@ -40,8 +40,6 @@ class RenderStateCache gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); private: - DISALLOW_COPY_AND_ASSIGN(RenderStateCache); - Renderer11 *mRenderer; unsigned long long mCounter; @@ -110,4 +108,4 @@ class RenderStateCache } -#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
\ No newline at end of file +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp index aff3453492..ecd9e13c90 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp @@ -7,12 +7,11 @@ // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers // retained by Renderbuffers. -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" namespace rx { @@ -177,24 +176,19 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) +RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTargetD3D *target) { ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target)); return static_cast<RenderTarget11*>(target); } -void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) -{ - // Currently a no-op -} - TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) : mWidth(width), mHeight(height), mDepth(depth), mInternalFormat(internalFormat), - mActualFormat(internalFormat), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), mSamples(samples), mSubresourceIndex(0), mTexture(resource), @@ -223,9 +217,7 @@ TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11 D3D11_RENDER_TARGET_VIEW_DESC desc; mRenderTarget->GetDesc(&desc); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); - mActualFormat = dxgiFormatInfo.internalFormat; + mDXGIFormat = desc.Format; } } @@ -235,7 +227,7 @@ TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11 mHeight(height), mDepth(depth), mInternalFormat(internalFormat), - mActualFormat(internalFormat), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), mSamples(samples), mSubresourceIndex(0), mTexture(resource), @@ -264,9 +256,7 @@ TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11 D3D11_DEPTH_STENCIL_VIEW_DESC desc; mDepthStencil->GetDesc(&desc); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); - mActualFormat = dxgiFormatInfo.internalFormat; + mDXGIFormat = desc.Format; } } @@ -318,11 +308,6 @@ GLenum TextureRenderTarget11::getInternalFormat() const return mInternalFormat; } -GLenum TextureRenderTarget11::getActualFormat() const -{ - return mActualFormat; -} - GLsizei TextureRenderTarget11::getSamples() const { return mSamples; @@ -333,9 +318,14 @@ unsigned int TextureRenderTarget11::getSubresourceIndex() const return mSubresourceIndex; } +DXGI_FORMAT TextureRenderTarget11::getDXGIFormat() const +{ + return mDXGIFormat; +} -SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth) +SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth) : mSwapChain(swapChain), + mRenderer(renderer), mDepth(depth) { ASSERT(mSwapChain); @@ -365,11 +355,6 @@ GLenum SurfaceRenderTarget11::getInternalFormat() const return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); } -GLenum SurfaceRenderTarget11::getActualFormat() const -{ - return d3d11::GetDXGIFormatInfo(d3d11::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat; -} - GLsizei SurfaceRenderTarget11::getSamples() const { // Our EGL surfaces do not support multisampling. @@ -401,4 +386,9 @@ unsigned int SurfaceRenderTarget11::getSubresourceIndex() const return 0; } +DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const +{ + return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getFeatureLevel()).texFormat; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h index c7babdda3f..4472a56175 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h @@ -7,24 +7,23 @@ // RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers // retained by Renderbuffers. -#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ -#include "libGLESv2/renderer/RenderTarget.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" namespace rx { class SwapChain11; +class Renderer11; -class RenderTarget11 : public RenderTarget +class RenderTarget11 : public RenderTargetD3D { public: RenderTarget11() { } virtual ~RenderTarget11() { } - static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - - void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override; + static RenderTarget11 *makeRenderTarget11(RenderTargetD3D *renderTarget); virtual ID3D11Resource *getTexture() const = 0; virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; @@ -33,8 +32,10 @@ class RenderTarget11 : public RenderTarget virtual unsigned int getSubresourceIndex() const = 0; + virtual DXGI_FORMAT getDXGIFormat() const = 0; + private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget11); + D3D_FEATURE_LEVEL mFeatureLevel; }; class TextureRenderTarget11 : public RenderTarget11 @@ -51,7 +52,6 @@ class TextureRenderTarget11 : public RenderTarget11 GLsizei getHeight() const override; GLsizei getDepth() const override; GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; GLsizei getSamples() const override; ID3D11Resource *getTexture() const override; @@ -61,14 +61,14 @@ class TextureRenderTarget11 : public RenderTarget11 unsigned int getSubresourceIndex() const override; - private: - DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget11); + DXGI_FORMAT getDXGIFormat() const override; + private: GLsizei mWidth; GLsizei mHeight; GLsizei mDepth; GLenum mInternalFormat; - GLenum mActualFormat; + DXGI_FORMAT mDXGIFormat; GLsizei mSamples; unsigned int mSubresourceIndex; @@ -81,14 +81,13 @@ class TextureRenderTarget11 : public RenderTarget11 class SurfaceRenderTarget11 : public RenderTarget11 { public: - SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth); + SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth); virtual ~SurfaceRenderTarget11(); GLsizei getWidth() const override; GLsizei getHeight() const override; GLsizei getDepth() const override; GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; GLsizei getSamples() const override; ID3D11Resource *getTexture() const override; @@ -98,13 +97,14 @@ class SurfaceRenderTarget11 : public RenderTarget11 unsigned int getSubresourceIndex() const override; - private: - DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget11); + DXGI_FORMAT getDXGIFormat() const override; + private: SwapChain11 *mSwapChain; + Renderer11 *mRenderer; bool mDepth; }; } -#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 777308e6cc..5291a3a086 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -6,46 +6,49 @@ // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. -#include "libGLESv2/main.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/State.h" -#include "libGLESv2/renderer/d3d/ProgramD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" -#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" -#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" -#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" - -#include "libEGL/Display.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "common/utilities.h" #include "common/tls.h" - -#include <EGL/eglext.h> +#include "libANGLE/Buffer.h" +#include "libANGLE/Display.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libANGLE/renderer/d3d/d3d11/Query11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/Trim11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include <sstream> +#include <EGL/eglext.h> // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. @@ -59,46 +62,174 @@ #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 #endif +#ifndef __d3d11sdklayers_h__ +#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 + namespace rx { namespace { -static const DXGI_FORMAT RenderTargetFormats[] = - { - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM - }; - -static const DXGI_FORMAT DepthStencilFormats[] = - { - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT, - DXGI_FORMAT_D16_UNORM - }; enum { MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; +// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state. +static const uintptr_t DirtyPointer = static_cast<uintptr_t>(-1); + +static bool ImageIndexConflictsWithSRV(const gl::ImageIndex *index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) +{ + unsigned mipLevel = index->mipIndex; + unsigned layerIndex = index->layerIndex; + GLenum type = index->type; + + switch (desc.ViewDimension) + { + case D3D11_SRV_DIMENSION_TEXTURE2D: + { + unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; + maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip; + + unsigned mipMin = index->mipIndex; + unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex; + + return type == GL_TEXTURE_2D && RangeUI(mipMin, mipMax).intersects(RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip)); + } + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + { + unsigned maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; + maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip; + + unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize; + + // Cube maps can be mapped to Texture2DArray SRVs + return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) && + desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip && + desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice; + } + + case D3D11_SRV_DIMENSION_TEXTURECUBE: + { + unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; + maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip; + + return gl::IsCubeMapTextureTarget(type) && + desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + } + + case D3D11_SRV_DIMENSION_TEXTURE3D: + { + unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; + maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip; + + return type == GL_TEXTURE_3D && + desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + } + default: + // We only handle the cases corresponding to valid image indexes + UNIMPLEMENTED(); + } + + return false; +} + // Does *not* increment the resource ref count!! -ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv) +ID3D11Resource *GetViewResource(ID3D11View *view) { ID3D11Resource *resource = NULL; - ASSERT(srv); - srv->GetResource(&resource); + ASSERT(view); + view->GetResource(&resource); resource->Release(); return resource; } +void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants) +{ + // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange). + ASSERT(offset % 256 == 0); + + // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must be a multiple of 16 constants. + *outFirstConstant = offset / 16; + + // The GL size is not required to be aligned to a 256 bytes boundary. + // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes. + *outNumConstants = rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16; + + // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size of the buffer. + // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1 + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx } -Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes) +} + +Renderer11::Renderer11(egl::Display *display) : RendererD3D(display), - mDc(hDc), mStateCache(this) { + // Initialize global annotator + gl::InitializeDebugAnnotations(&mAnnotator); + mVertexDataManager = NULL; mIndexDataManager = NULL; @@ -110,15 +241,18 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg mClear = NULL; + mTrim = NULL; + mSyncQuery = NULL; + mSupportsConstantBufferOffsets = false; + mD3d11Module = NULL; mDxgiModule = NULL; - mDeviceLost = false; - mDevice = NULL; mDeviceContext = NULL; + mDeviceContext1 = NULL; mDxgiAdapter = NULL; mDxgiFactory = NULL; @@ -127,9 +261,12 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg mAppliedVertexShader = NULL; mAppliedGeometryShader = NULL; - mCurPointGeometryShader = NULL; mAppliedPixelShader = NULL; + mAppliedNumXFBBindings = static_cast<size_t>(-1); + + const auto &attributes = mDisplay->getAttributeMap(); + EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); @@ -153,31 +290,45 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg } } -#if !defined(ANGLE_ENABLE_D3D9) +#if defined(ANGLE_ENABLE_WINDOWS_STORE) if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) +#else + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) +#endif { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); - } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); - } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); - } + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); } -#endif - mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP - : D3D_DRIVER_TYPE_HARDWARE; + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + switch (requestedDeviceType) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + mDriverType = D3D_DRIVER_TYPE_HARDWARE; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + mDriverType = D3D_DRIVER_TYPE_WARP; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mDriverType = D3D_DRIVER_TYPE_REFERENCE; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDriverType = D3D_DRIVER_TYPE_NULL; + break; + + default: + UNREACHABLE(); + } } Renderer11::~Renderer11() { release(); + + gl::UninitializeDebugAnnotations(); } Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) @@ -190,11 +341,13 @@ Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) #define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) #endif -EGLint Renderer11::initialize() +egl::Error Renderer11::initialize() { if (!mCompiler.initialize()) { - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_COMPILER_ERROR, + "Failed to initialize compiler."); } #if !defined(ANGLE_ENABLE_WINDOWS_STORE) @@ -203,8 +356,9 @@ EGLint Renderer11::initialize() if (mD3d11Module == NULL || mDxgiModule == NULL) { - ERR("Could not load D3D11 or DXGI library - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_MISSING_DEP, + "Could not load D3D11 or DXGI library."); } // create the D3D11 device @@ -213,8 +367,9 @@ EGLint Renderer11::initialize() if (D3D11CreateDevice == NULL) { - ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_MISSING_DEP, + "Could not retrieve D3D11CreateDevice address."); } #endif @@ -250,29 +405,29 @@ EGLint Renderer11::initialize() &mFeatureLevel, &mDeviceContext); + if (result == E_INVALIDARG) + { + // Cleanup done by destructor through glDestroyRenderer + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_CREATEDEVICE_INVALIDARG, + "Could not create D3D11 device."); + } + if (!mDevice || FAILED(result)) { - ERR("Could not create D3D11 device - aborting!\n"); - return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer + // Cleanup done by destructor through glDestroyRenderer + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_CREATEDEVICE_ERROR, + "Could not create D3D11 device."); } } #if !defined(ANGLE_ENABLE_WINDOWS_STORE) - static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); - if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) - { - ID3D10Multithread *multithread; - result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread)); - ASSERT(SUCCEEDED(result)); - result = multithread->SetMultithreadProtected(true); - ASSERT(SUCCEEDED(result)); - multithread->Release(); - } #if !ANGLE_SKIP_DXGI_1_2_CHECK // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. // The easiest way to check is to query for a IDXGIDevice2. bool requireDXGI1_2 = false; - HWND hwnd = WindowFromDC(mDc); + HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); if (hwnd) { DWORD currentProcessId = GetCurrentProcessId(); @@ -291,34 +446,72 @@ EGLint Renderer11::initialize() result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); if (FAILED(result)) { - ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_INCOMPATIBLE_DXGI, + "DXGI 1.2 required to present to HWNDs owned by another process."); } SafeRelease(dxgiDevice2); } #endif #endif + // Cast the DeviceContext to a DeviceContext1. + // This could fail on Windows 7 without the Platform Update. + // Don't error in this case- just don't use mDeviceContext1. +#if defined(ANGLE_ENABLE_D3D11_1) + mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext); +#endif + IDXGIDevice *dxgiDevice = NULL; result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); if (FAILED(result)) { - ERR("Could not query DXGI device - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not query DXGI device."); } result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); if (FAILED(result)) { - ERR("Could not retrieve DXGI adapter - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not retrieve DXGI adapter"); } SafeRelease(dxgiDevice); - mDxgiAdapter->GetDesc(&mAdapterDescription); +#if defined(ANGLE_ENABLE_D3D11_1) + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter); + + // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string. + // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values. + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL) + { + DXGI_ADAPTER_DESC2 adapterDesc2 = {0}; + dxgiAdapter2->GetDesc2(&adapterDesc2); + + // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC). + memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description)); + mAdapterDescription.VendorId = adapterDesc2.VendorId; + mAdapterDescription.DeviceId = adapterDesc2.DeviceId; + mAdapterDescription.SubSysId = adapterDesc2.SubSysId; + mAdapterDescription.Revision = adapterDesc2.Revision; + mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory; + mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory; + mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; + mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; + } + else + { + mDxgiAdapter->GetDesc(&mAdapterDescription); + } + + SafeRelease(dxgiAdapter2); +#endif + memset(mDescription, 0, sizeof(mDescription)); wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); @@ -326,14 +519,15 @@ EGLint Renderer11::initialize() if (!mDxgiFactory || FAILED(result)) { - ERR("Could not create DXGI factory - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not create DXGI factory."); } // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) ID3D11InfoQueue *infoQueue; - result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); + result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); if (SUCCEEDED(result)) { @@ -353,7 +547,7 @@ EGLint Renderer11::initialize() initializeDevice(); - return EGL_SUCCESS; + return egl::Error(EGL_SUCCESS); } // do any one-time device initialization @@ -366,7 +560,7 @@ void Renderer11::initializeDevice() ASSERT(!mVertexDataManager && !mIndexDataManager); mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this); + mIndexDataManager = new IndexDataManager(this, getRendererClass()); ASSERT(!mBlit); mBlit = new Blit11(this); @@ -374,11 +568,32 @@ void Renderer11::initializeDevice() ASSERT(!mClear); mClear = new Clear11(this); + const auto &attributes = mDisplay->getAttributeMap(); + // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application + // automatically when an application is suspended by the OS. This feature is currently + // only supported for Windows Store applications. + EGLint enableAutoTrim = attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE); + + if (enableAutoTrim == EGL_TRUE) + { + ASSERT(!mTrim); + mTrim = new Trim11(this); + } + ASSERT(!mPixelTransfer); mPixelTransfer = new PixelTransfer11(this); const gl::Caps &rendererCaps = getRendererCaps(); +#if defined(ANGLE_ENABLE_D3D11_1) + if (getDeviceContext1IfSupported()) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + mSupportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE); + } +#endif + mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); @@ -391,96 +606,139 @@ void Renderer11::initializeDevice() markAllStateDirty(); } -int Renderer11::generateConfigs(ConfigDesc **configDescList) +egl::ConfigSet Renderer11::generateConfigs() const { - unsigned int numRenderFormats = ArraySize(RenderTargetFormats); - unsigned int numDepthFormats = ArraySize(DepthStencilFormats); - (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; - int numConfigs = 0; + static const GLenum colorBufferFormats[] = + { + GL_BGRA8_EXT, + GL_RGBA8_OES, + }; - for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + static const GLenum depthStencilBufferFormats[] = { - const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]); - const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); - if (renderTargetFormatCaps.renderable) + GL_NONE, + GL_DEPTH24_STENCIL8_OES, + GL_DEPTH_COMPONENT16, + }; + + const gl::Caps &rendererCaps = getRendererCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + + egl::ConfigSet configs; + for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) + { + GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; + const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + if (colorBufferFormatCaps.renderable) { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) { - const d3d11::DXGIFormat &depthStencilFormatInfo = d3d11::GetDXGIFormatInfo(DepthStencilFormats[depthStencilIndex]); - const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); - if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == DXGI_FORMAT_UNKNOWN) + GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex]; + const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE) { - ConfigDesc newConfig; - newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; - newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast - newConfig.es3Capable = true; - - (*configDescList)[numConfigs++] = newConfig; + const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + config.configID = static_cast<EGLint>(configs.size() + 1); + // Can only support a conformant ES2 with feature level greater than 10.0. + config.conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) : EGL_NONE; + config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE; + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = 4; + config.minSwapInterval = 0; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + // Can't support ES3 at all without feature level 10.0 + config.renderableType = EGL_OPENGL_ES2_BIT | ((mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + + configs.add(config); } } } } - return numConfigs; + ASSERT(configs.size() > 0); + return configs; } -void Renderer11::deleteConfigs(ConfigDesc *configDescList) +gl::Error Renderer11::flush() { - delete [] (configDescList); + mDeviceContext->Flush(); + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::sync(bool block) +gl::Error Renderer11::finish() { - if (block) + HRESULT result; + + if (!mSyncQuery) { - HRESULT result; + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; - if (!mSyncQuery) + result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); - } + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); } + } - mDeviceContext->End(mSyncQuery); - mDeviceContext->Flush(); + mDeviceContext->End(mSyncQuery); + mDeviceContext->Flush(); - do + do + { + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + if (FAILED(result)) { - result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); - } + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } - // Keep polling, but allow other threads to do something useful first - Sleep(0); + // Keep polling, but allow other threads to do something useful first + ScheduleYield(); - if (testDeviceLost(true)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync."); - } + if (testDeviceLost()) + { + mDisplay->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync."); } - while (result == S_FALSE); - } - else - { - mDeviceContext->Flush(); } + while (result == S_FALSE); return gl::Error(GL_NO_ERROR); } -SwapChain *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) { return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); } @@ -489,17 +747,23 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture) { if (texture) { - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); ASSERT(textureD3D); - TextureStorage *texStorage = textureD3D->getNativeTexture(); + TextureStorage *texStorage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + if (texStorage) { TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed, - texture->getSamplerState().swizzleGreen, - texture->getSamplerState().swizzleBlue, - texture->getSamplerState().swizzleAlpha); + error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed, + texture->getSamplerState().swizzleGreen, + texture->getSamplerState().swizzleBlue, + texture->getSamplerState().swizzleAlpha); if (error.isError()) { return error; @@ -513,9 +777,20 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture) gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam) { // Make sure to add the level offset for our tiny compressed texture workaround - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); gl::SamplerState samplerStateInternal = samplerStateParam; - samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel(); + + TextureStorage *storage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&storage); + if (error.isError()) + { + return error; + } + + // Storage should exist, texture should be complete + ASSERT(storage); + + samplerStateInternal.baseLevel += storage->getTopLevel(); if (type == gl::SAMPLER_PIXEL) { @@ -524,7 +799,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) { ID3D11SamplerState *dxSamplerState = NULL; - gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); + error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); if (error.isError()) { return error; @@ -545,7 +820,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) { ID3D11SamplerState *dxSamplerState = NULL; - gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); + error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); if (error.isError()) { return error; @@ -570,9 +845,17 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t if (texture) { - TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); - TextureStorage *texStorage = textureImpl->getNativeTexture(); - ASSERT(texStorage != NULL); + TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture); + + TextureStorage *texStorage = nullptr; + gl::Error error = textureImpl->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + // Texture should be complete and have a storage + ASSERT(texStorage); TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); @@ -580,7 +863,7 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t gl::SamplerState samplerState = texture->getSamplerState(); samplerState.baseLevel += storage11->getTopLevel(); - gl::Error error = storage11->getSRV(samplerState, &textureSRV); + error = storage11->getSRV(samplerState, &textureSRV); if (error.isError()) { return error; @@ -601,11 +884,23 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) +gl::Error Renderer11::setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) { - for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxVertexUniformBlocks; uniformBufferIndex++) { - const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex]; + GLint binding = vertexUniformBuffers[uniformBufferIndex]; + + if (binding == -1) + { + continue; + } + + gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding); + GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding); + if (uniformBuffer) { Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); @@ -616,18 +911,46 @@ gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[] return gl::Error(GL_OUT_OF_MEMORY); } - if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial()) + if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() || + mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) { - mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer); +#if defined(ANGLE_ENABLE_D3D11_1) + if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + { + UINT firstConstant = 0, numConstants = 0; + CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); + mDeviceContext1->VSSetConstantBuffers1(getReservedVertexUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer, &firstConstant, &numConstants); + } + else +#endif + { + ASSERT(uniformBufferOffset == 0); + mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + } + mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); + mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset; + mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize; } } } - for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxFragmentUniformBlocks; uniformBufferIndex++) { - const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex]; + GLint binding = fragmentUniformBuffers[uniformBufferIndex]; + + if (binding == -1) + { + continue; + } + + gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding); + GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding); + if (uniformBuffer) { Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); @@ -638,11 +961,29 @@ gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[] return gl::Error(GL_OUT_OF_MEMORY); } - if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial()) + if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() || + mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) { - mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer); +#if defined(ANGLE_ENABLE_D3D11_1) + if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + { + UINT firstConstant = 0, numConstants = 0; + CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); + mDeviceContext1->PSSetConstantBuffers1(getReservedFragmentUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer, &firstConstant, &numConstants); + } + else +#endif + { + ASSERT(uniformBufferOffset == 0); + mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + } + mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); + mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset; + mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize; } } } @@ -739,8 +1080,8 @@ gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthSte // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops - META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF); - META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF); + static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); + static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); @@ -799,33 +1140,67 @@ void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z actualZFar = 1.0f; } - const gl::Caps& caps = getRendererCaps(); - - // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = gl::clamp(actualViewport.x, -static_cast<int>(caps.maxViewportWidth), static_cast<int>(caps.maxViewportWidth)); - dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast<int>(caps.maxViewportHeight), static_cast<int>(caps.maxViewportHeight)); - dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(caps.maxViewportWidth - dxViewport.TopLeftX)); - dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(caps.maxViewportHeight - dxViewport.TopLeftY)); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || actualZNear != mCurNear || actualZFar != mCurFar; if (viewportChanged) { + const gl::Caps& caps = getRendererCaps(); + + int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth); + int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight); + int dxMinViewportBoundsX = -dxMaxViewportBoundsX; + int dxMinViewportBoundsY = -dxMaxViewportBoundsY; + + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. + dxMaxViewportBoundsX = mRenderTargetDesc.width; + dxMaxViewportBoundsY = mRenderTargetDesc.height; + dxMinViewportBoundsX = 0; + dxMinViewportBoundsY = 0; + } + + int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); + int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); + int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); + dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY); + dxViewport.Width = static_cast<float>(dxViewportWidth); + dxViewport.Height = static_cast<float>(dxViewportHeight); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + mDeviceContext->RSSetViewports(1, &dxViewport); mCurViewport = actualViewport; mCurNear = actualZNear; mCurFar = actualZFar; + // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer). + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mVertexConstants.viewAdjust[0] = static_cast<float>((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width; + mVertexConstants.viewAdjust[1] = static_cast<float>((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height; + mVertexConstants.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width; + mVertexConstants.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height; + } + mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + // Instanced pointsprite emulation requires ViewCoords to be defined in the + // the vertex shader. + mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0]; + mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1]; + mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2]; + mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3]; + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; @@ -841,7 +1216,7 @@ void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z mForceSetViewport = false; } -bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) +bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) { D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; @@ -862,6 +1237,14 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) return false; } + // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader, + // GL_POINTS mode is expected to render pointsprites. + // Instanced PointSprite emulation requires that the topology to be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST. + if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation) + { + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + } + if (primitiveTopology != mCurrentPrimitiveTopology) { mDeviceContext->IASetPrimitiveTopology(primitiveTopology); @@ -871,15 +1254,15 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) return count >= minCount; } -void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource) +void Renderer11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, const gl::ImageIndex *index) { - std::vector<ID3D11ShaderResourceView *> ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) { - ID3D11ShaderResourceView *srv = currentSRVs[resourceIndex]; + auto &record = currentSRVs[resourceIndex]; - if (srv && GetSRVResource(srv) == resource) + if (record.srv && record.resource == resource && ImageIndexConflictsWithSRV(index, record.desc)) { setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL); } @@ -892,12 +1275,12 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) // Also extract the render target dimensions and view unsigned int renderTargetWidth = 0; unsigned int renderTargetHeight = 0; - GLenum renderTargetFormat = 0; - unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; + DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; bool missingColorRenderTarget = true; - const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(getWorkarounds()); + const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(getWorkarounds()); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { @@ -915,8 +1298,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) return gl::Error(GL_NO_ERROR); } - renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer); - // Extract the render target dimensions and view RenderTarget11 *renderTarget = NULL; gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); @@ -931,36 +1312,29 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) if (missingColorRenderTarget) { - renderTargetWidth = colorbuffer->getWidth(); - renderTargetHeight = colorbuffer->getHeight(); - renderTargetFormat = colorbuffer->getActualFormat(); + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + renderTargetFormat = renderTarget->getDXGIFormat(); missingColorRenderTarget = false; } -#if !defined(NDEBUG) // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - unsetSRVsWithResource(gl::SAMPLER_VERTEX, renderTargetResource); - unsetSRVsWithResource(gl::SAMPLER_PIXEL, renderTargetResource); -#endif + if (colorbuffer->type() == GL_TEXTURE) + { + uintptr_t rtResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment])); + const gl::ImageIndex *index = colorbuffer->getTextureImageIndex(); + ASSERT(index); + // The index doesn't need to be corrected for the small compressed texture workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); + } } } - // Get the depth stencil render buffter and serials - gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (depthStencil) - { - depthbufferSerial = GetAttachmentSerial(depthStencil); - } - else if (framebuffer->getStencilbuffer()) - { - depthStencil = framebuffer->getStencilbuffer(); - stencilbufferSerial = GetAttachmentSerial(depthStencil); - } - + // Get the depth stencil buffers ID3D11DepthStencilView* framebufferDSV = NULL; + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); if (depthStencil) { RenderTarget11 *depthStencilRenderTarget = NULL; @@ -979,17 +1353,28 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) // the depth stencil if (missingColorRenderTarget) { - renderTargetWidth = depthStencil->getWidth(); - renderTargetHeight = depthStencil->getHeight(); - renderTargetFormat = depthStencil->getActualFormat(); + renderTargetWidth = depthStencilRenderTarget->getWidth(); + renderTargetHeight = depthStencilRenderTarget->getHeight(); + renderTargetFormat = depthStencilRenderTarget->getDXGIFormat(); + } + + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (depthStencil->type() == GL_TEXTURE) + { + uintptr_t depthStencilResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV)); + const gl::ImageIndex *index = depthStencil->getTextureImageIndex(); + ASSERT(index); + // The index doesn't need to be corrected for the small compressed texture workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); } } // Apply the render target and depth stencil if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || - memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || - depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial) + memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 || + reinterpret_cast<uintptr_t>(framebufferDSV) != mAppliedDSV) { mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); @@ -1005,22 +1390,26 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) mForceSetRasterState = true; } - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++) { - mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; + mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(framebufferRTVs[rtIndex]); } - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; + mAppliedDSV = reinterpret_cast<uintptr_t>(framebufferDSV); mRenderTargetDescInitialized = true; mDepthStencilInitialized = true; } - invalidateFramebufferSwizzles(framebuffer); + const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); + gl::Error error = framebuffer11->invalidateSwizzles(); + if (error.isError()) + { + return error; + } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); @@ -1029,7 +1418,7 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLs return error; } - return mInputLayoutCache.applyVertexBuffers(attributes, state.getCurrentProgramBinary()); + return mInputLayoutCache.applyVertexBuffers(attributes, mode, state.getProgram()); } gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) @@ -1066,31 +1455,36 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen return gl::Error(GL_NO_ERROR); } -void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) +void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) { - size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange(); - ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); - + size_t numXFBBindings = 0; bool requiresUpdate = false; - for (size_t i = 0; i < numXFBBindings; i++) + + if (state.isTransformFeedbackActiveUnpaused()) { - gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); - GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); - ID3D11Buffer *d3dBuffer = NULL; - if (curXFBBuffer) - { - Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); - d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - } + numXFBBindings = state.getTransformFeedbackBufferIndexRange(); + ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); - // TODO: mAppliedTFBuffers and friends should also be kept in a vector. - if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) + for (size_t i = 0; i < numXFBBindings; i++) { - requiresUpdate = true; + gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); + GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); + ID3D11Buffer *d3dBuffer = NULL; + if (curXFBBuffer) + { + Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + } + + // TODO: mAppliedTFBuffers and friends should also be kept in a vector. + if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) + { + requiresUpdate = true; + } } } - if (requiresUpdate) + if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) { for (size_t i = 0; i < numXFBBindings; ++i) { @@ -1102,7 +1496,7 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer && mAppliedTFOffsets[i] != curXFBOffset) ? + mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ? static_cast<UINT>(curXFBOffset) : -1; mAppliedTFBuffers[i] = d3dBuffer; } @@ -1114,13 +1508,16 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) mAppliedTFOffsets[i] = curXFBOffset; } + mAppliedNumXFBBindings = numXFBBindings; + mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets); } } -gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) { - if (mode == GL_POINTS && transformFeedbackActive) + bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation; + if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused()) { // Since point sprites are generated with a geometry shader, too many vertices will // be written if transform feedback is active. To work around this, draw only the points @@ -1138,19 +1535,38 @@ gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, mDeviceContext->Draw(count, 0); } - mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0); - mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram()); - if (instances > 0) + rx::ShaderExecutableD3D *pixelExe = NULL; + gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe); + if (error.isError()) { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + return error; } - else + + // Skip this step if we're doing rasterizer discard. + if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize) { - mDeviceContext->Draw(count, 0); - } + ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); + ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0); + // Retrieve the point sprite geometry shader + rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); + ID3D11GeometryShader *geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); + mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); + ASSERT(geometryShader); + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + } return gl::Error(GL_NO_ERROR); } @@ -1169,7 +1585,17 @@ gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, } else { - mDeviceContext->Draw(count, 0); + // If gl_PointSize is used and GL_POINTS is specified, then it is expected to render pointsprites. + // If instanced pointsprite emulation is being used the topology is expexted to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced must be used. + if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + { + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } return gl::Error(GL_NO_ERROR); } } @@ -1198,90 +1624,13 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons return gl::Error(GL_NO_ERROR); } } -template<typename T> -static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast<const GLubyte*>(indices)[i]; - } - data[count] = static_cast<const GLubyte*>(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast<const GLushort*>(indices)[i]; - } - data[count] = static_cast<const GLushort*>(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast<const GLuint*>(indices)[i]; - } - data[count] = static_cast<const GLuint*>(indices)[0]; - break; - default: UNREACHABLE(); - } -} - -template<typename T> -static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0]; - data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1]; - data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast<const GLushort*>(indices)[0]; - data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1]; - data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast<const GLuint*>(indices)[0]; - data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1]; - data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } -} gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) { // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); intptr_t offset = reinterpret_cast<intptr_t>(indices); const uint8_t *bufferData = NULL; @@ -1294,13 +1643,10 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind indices = bufferData + offset; } - // TODO: some level 9 hardware supports 32-bit indices; test and store support instead - const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); if (error.isError()) { SafeDelete(mLineLoopIB); @@ -1311,8 +1657,7 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind // Checked by Renderer11::applyPrimitiveType ASSERT(count >= 0); - int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); - if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / indexTypeSize)) + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); } @@ -1332,12 +1677,42 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind return error; } - if (indexType == GL_UNSIGNED_SHORT) - fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory)); - else - fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory)); + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); unsigned int indexBufferOffset = offset; + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLubyte*>(indices)[i]; + } + data[count] = static_cast<const GLubyte*>(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLushort*>(indices)[i]; + } + data[count] = static_cast<const GLushort*>(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast<const GLuint*>(indices)[i]; + } + data[count] = static_cast<const GLuint*>(indices)[0]; + break; + default: UNREACHABLE(); + } + error = mLineLoopIB->unmapBuffer(); if (error.isError()) { @@ -1366,7 +1741,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); intptr_t offset = reinterpret_cast<intptr_t>(indices); const uint8_t *bufferData = NULL; @@ -1379,12 +1754,10 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * indices = bufferData + offset; } - const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - if (!mTriangleFanIB) { mTriangleFanIB = new StreamingIndexBufferInterface(this); - gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); + gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); if (error.isError()) { SafeDelete(mTriangleFanIB); @@ -1397,14 +1770,13 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * const unsigned int numTris = count - 2; - int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); - if (numTris > (std::numeric_limits<unsigned int>::max() / (indexTypeSize * 3))) + if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3))) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); } - const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize; - gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType); + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); if (error.isError()) { return error; @@ -1418,13 +1790,46 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } - if (indexType == GL_UNSIGNED_SHORT) - fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory)); - else - fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory)); - + unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory); unsigned int indexBufferOffset = offset; + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0]; + data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1]; + data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast<const GLushort*>(indices)[0]; + data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1]; + data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast<const GLuint*>(indices)[0]; + data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1]; + data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } + error = mTriangleFanIB->unmapBuffer(); if (error.isError()) { @@ -1455,26 +1860,26 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, +gl::Error Renderer11::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive) { - ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); - ShaderExecutable *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe); + ShaderExecutableD3D *vertexExe = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); if (error.isError()) { return error; } - ShaderExecutable *pixelExe = NULL; + ShaderExecutableD3D *pixelExe = NULL; error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); if (error.isError()) { return error; } - ShaderExecutable *geometryExe = programD3D->getGeometryExecutable(); + ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); @@ -1497,33 +1902,24 @@ gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::V bool dirtyUniforms = false; - if (vertexShader != mAppliedVertexShader) + if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader) { mDeviceContext->VSSetShader(vertexShader, NULL, 0); - mAppliedVertexShader = vertexShader; + mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader); dirtyUniforms = true; } - if (geometryShader != mAppliedGeometryShader) + if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader) { mDeviceContext->GSSetShader(geometryShader, NULL, 0); - mAppliedGeometryShader = geometryShader; + mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader); dirtyUniforms = true; } - if (geometryExe && mCurRasterState.pointDrawMode) - { - mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); - } - else - { - mCurPointGeometryShader = NULL; - } - - if (pixelShader != mAppliedPixelShader) + if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader) { mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mAppliedPixelShader = pixelShader; + mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader); dirtyUniforms = true; } @@ -1560,7 +1956,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto } } - const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(&program); + const ProgramD3D *programD3D = GetAs<ProgramD3D>(&program); const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage()); const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage()); ASSERT(vertexUniformStorage); @@ -1682,40 +2078,36 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); } - // needed for the point sprite geometry shader - if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary + if (programD3D->usesGeometryShader()) { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) -{ - gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer); - if (error.isError()) - { - return error; + // needed for the point sprite geometry shader + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } } - invalidateFramebufferSwizzles(frameBuffer); - return gl::Error(GL_NO_ERROR); } void Renderer11::markAllStateDirty() { - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) { - mAppliedRenderTargetSerials[rtIndex] = 0; + mAppliedRTVs[rtIndex] = DirtyPointer; } - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; + mAppliedDSV = DirtyPointer; mDepthStencilInitialized = false; mRenderTargetDescInitialized = false; + // We reset the current SRV data because it might not be in sync with D3D's state + // anymore. For example when a currently used SRV is used as an RTV, D3D silently + // remove it from its state. + memset(mCurVertexSRVs.data(), 0, sizeof(SRVRecord) * mCurVertexSRVs.size()); + memset(mCurPixelSRVs.data(), 0, sizeof(SRVRecord) * mCurPixelSRVs.size()); + ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size()); for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) { @@ -1738,10 +2130,11 @@ void Renderer11::markAllStateDirty() mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; mAppliedIBOffset = 0; - mAppliedVertexShader = NULL; - mAppliedGeometryShader = NULL; - mCurPointGeometryShader = NULL; - mAppliedPixelShader = NULL; + mAppliedVertexShader = DirtyPointer; + mAppliedGeometryShader = DirtyPointer; + mAppliedPixelShader = DirtyPointer; + + mAppliedNumXFBBindings = static_cast<size_t>(-1); for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) { @@ -1756,8 +2149,12 @@ void Renderer11::markAllStateDirty() for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) { - mCurrentConstantBufferVS[i] = -1; - mCurrentConstantBufferPS[i] = -1; + mCurrentConstantBufferVS[i] = static_cast<unsigned int>(-1); + mCurrentConstantBufferVSOffset[i] = 0; + mCurrentConstantBufferVSSize[i] = 0; + mCurrentConstantBufferPS[i] = static_cast<unsigned int>(-1); + mCurrentConstantBufferPSOffset[i] = 0; + mCurrentConstantBufferPSSize[i] = 0; } mCurrentVertexConstantBuffer = NULL; @@ -1778,6 +2175,7 @@ void Renderer11::releaseDeviceResources() SafeDelete(mTriangleFanIB); SafeDelete(mBlit); SafeDelete(mClear); + SafeDelete(mTrim); SafeDelete(mPixelTransfer); SafeRelease(mDriverConstantBufferVS); @@ -1785,19 +2183,8 @@ void Renderer11::releaseDeviceResources() SafeRelease(mSyncQuery); } -void Renderer11::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer11::isDeviceLost() -{ - return mDeviceLost; -} - // set notify to true to broadcast a message to all contexts of the device loss -bool Renderer11::testDeviceLost(bool notify) +bool Renderer11::testDeviceLost() { bool isLost = false; @@ -1819,10 +2206,6 @@ bool Renderer11::testDeviceLost(bool notify) // Note that we don't want to clear the device loss status here // -- this needs to be done by resetDevice mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } } return isLost; @@ -1872,12 +2255,15 @@ void Renderer11::release() { RendererD3D::cleanup(); - releaseShaderCompiler(); releaseDeviceResources(); SafeRelease(mDxgiFactory); SafeRelease(mDxgiAdapter); +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mDeviceContext1); +#endif + if (mDeviceContext) { mDeviceContext->ClearState(); @@ -1906,11 +2292,11 @@ bool Renderer11::resetDevice() { // recreate everything release(); - EGLint result = initialize(); + egl::Error result = initialize(); - if (result != EGL_SUCCESS) + if (result.isError()) { - ERR("Could not reinitialize D3D11 device: %08X", result); + ERR("Could not reinitialize D3D11 device: %08X", result.getCode()); return false; } @@ -1919,9 +2305,9 @@ bool Renderer11::resetDevice() return true; } -DWORD Renderer11::getAdapterVendor() const +VendorID Renderer11::getVendorId() const { - return mAdapterDescription.VendorId; + return static_cast<VendorID>(mAdapterDescription.VendorId); } std::string Renderer11::getRendererDescription() const @@ -1931,8 +2317,8 @@ std::string Renderer11::getRendererDescription() const rendererString << mDescription; rendererString << " Direct3D11"; - rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); - rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); return rendererString.str(); } @@ -1941,7 +2327,7 @@ GUID Renderer11::getAdapterIdentifier() const { // Use the adapter LUID as our adapter ID // This number is local to a machine is only guaranteed to be unique between restarts - META_ASSERT(sizeof(LUID) <= sizeof(GUID)); + static_assert(sizeof(LUID) <= sizeof(GUID), "Size of GUID must be at least as large as LUID."); GUID adapterId = {0}; memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); return adapterId; @@ -1974,7 +2360,8 @@ bool Renderer11::getShareHandleSupport() const // We only currently support share handles with BGRA surfaces, because // chrome needs BGRA. Once chrome fixes this, we should always support them. // PIX doesn't seem to support using share handles, so disable them. - return getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive(); + // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains. + return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive();// && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); Qt: we don't care about the 9_3 limitation } bool Renderer11::getPostSubBufferSupport() const @@ -1989,10 +2376,8 @@ int Renderer11::getMajorShaderModel() const { case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MAJOR_VERSION; // 4 default: UNREACHABLE(); return 0; } } @@ -2003,26 +2388,26 @@ int Renderer11::getMinorShaderModel() const { case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MINOR_VERSION; // 0 default: UNREACHABLE(); return 0; } } -int Renderer11::getMinSwapInterval() const +std::string Renderer11::getShaderModelSuffix() const { - return 0; -} - -int Renderer11::getMaxSwapInterval() const -{ - return 4; + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return ""; + case D3D_FEATURE_LEVEL_10_1: return ""; + case D3D_FEATURE_LEVEL_10_0: return ""; + case D3D_FEATURE_LEVEL_9_3: return "_level_9_3"; + default: UNREACHABLE(); return ""; + } } -gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) +gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); @@ -2042,7 +2427,7 @@ gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectan ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::Make2D(level); - RenderTarget *destRenderTarget = NULL; + RenderTargetD3D *destRenderTarget = NULL; error = storage11->getRenderTarget(index, &destRenderTarget); if (error.isError()) { @@ -2056,7 +2441,7 @@ gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectan gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); // Use nearest filtering because source and destination are the same size for the direct @@ -2072,8 +2457,8 @@ gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectan return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) +gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); @@ -2093,7 +2478,7 @@ gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rect ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - RenderTarget *destRenderTarget = NULL; + RenderTargetD3D *destRenderTarget = NULL; error = storage11->getRenderTarget(index, &destRenderTarget); if (error.isError()) { @@ -2107,7 +2492,7 @@ gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rect gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); // Use nearest filtering because source and destination are the same size for the direct @@ -2123,8 +2508,8 @@ gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rect return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); @@ -2143,8 +2528,8 @@ gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectan TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); ASSERT(storage11); - gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset); - RenderTarget *destRenderTarget = NULL; + gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); + RenderTargetD3D *destRenderTarget = NULL; error = storage11->getRenderTarget(index, &destRenderTarget); if (error.isError()) { @@ -2158,7 +2543,7 @@ gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectan gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); // Use nearest filtering because source and destination are the same size for the direct @@ -2174,8 +2559,8 @@ gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectan return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); @@ -2194,8 +2579,8 @@ gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::R TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); ASSERT(storage11); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset); - RenderTarget *destRenderTarget = NULL; + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + RenderTargetD3D *destRenderTarget = NULL; error = storage11->getRenderTarget(index, &destRenderTarget); if (error.isError()) { @@ -2209,7 +2594,7 @@ gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::R gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); // Use nearest filtering because source and destination are the same size for the direct @@ -2230,6 +2615,7 @@ void Renderer11::unapplyRenderTargets() setOneTimeRenderTarget(NULL); } +// When finished with this rendertarget, markAllStateDirty must be called. void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) { ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; @@ -2239,22 +2625,16 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL); // Do not preserve the serial for this one-time-use render target - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) { - mAppliedRenderTargetSerials[rtIndex] = 0; + mAppliedRTVs[rtIndex] = DirtyPointer; } + mAppliedDSV = DirtyPointer; } -gl::Error Renderer11::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - *outRT = new SurfaceRenderTarget11(swapChain11, depth); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) +gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) { - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mFeatureLevel); const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); GLuint supportedSamples = textureCaps.getNearestSamples(samples); @@ -2386,24 +2766,34 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G return gl::Error(GL_NO_ERROR); } -ShaderImpl *Renderer11::createShader(const gl::Data &data, GLenum type) +FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::Framebuffer::Data &data) { - return new ShaderD3D(data, type, this); + return createFramebuffer(data); } -ProgramImpl *Renderer11::createProgram() +FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data) { - return new ProgramD3D(this); + return new Framebuffer11(data, this); } -void Renderer11::releaseShaderCompiler() +CompilerImpl *Renderer11::createCompiler(const gl::Data &data) { - ShaderD3D::releaseCompiler(); + return new CompilerD3D(data, SH_HLSL11_OUTPUT); +} + +ShaderImpl *Renderer11::createShader(GLenum type) +{ + return new ShaderD3D(type); +} + +ProgramImpl *Renderer11::createProgram() +{ + return new ProgramD3D(this); } gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable) + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) { switch (type) { @@ -2490,8 +2880,8 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable) + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) { const char *profileType = NULL; switch (type) @@ -2510,51 +2900,11 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin return gl::Error(GL_INVALID_OPERATION); } - unsigned int profileMajorVersion = 0; - unsigned int profileMinorVersion = 0; - const char *profileSuffix = NULL; - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - profileMajorVersion = 5; - profileMinorVersion = 0; - break; - case D3D_FEATURE_LEVEL_10_1: - profileMajorVersion = 4; - profileMinorVersion = 1; - break; - case D3D_FEATURE_LEVEL_10_0: - profileMajorVersion = 4; - profileMinorVersion = 0; - break; - case D3D_FEATURE_LEVEL_9_3: - profileMajorVersion = 4; - profileMinorVersion = 0; - profileSuffix = "_level_9_3"; - break; - case D3D_FEATURE_LEVEL_9_2: - profileMajorVersion = 4; - profileMinorVersion = 0; - profileSuffix = "_level_9_2"; - break; - case D3D_FEATURE_LEVEL_9_1: - profileMajorVersion = 4; - profileMinorVersion = 0; - profileSuffix = "_level_9_1"; - break; - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); - if (profileSuffix) - profile += profileSuffix; + std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), getMinorShaderModel(), getShaderModelSuffix().c_str()); UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; - if (gl::perfActive()) + if (gl::DebugAnnotationsActive()) { #ifndef NDEBUG flags = D3DCOMPILE_SKIP_OPTIMIZATION; @@ -2563,6 +2913,9 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin flags |= D3DCOMPILE_DEBUG; } + if (workarounds.enableIEEEStrictness) + flags |= D3DCOMPILE_IEEE_STRICTNESS; + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. // Try the default flags first and if compilation fails, try some alternatives. std::vector<CompileConfig> configs; @@ -2605,7 +2958,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin return gl::Error(GL_NO_ERROR); } -UniformStorage *Renderer11::createUniformStorage(size_t storageSize) +UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize) { return new UniformStorage11(this, storageSize); } @@ -2655,7 +3008,7 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const ASSERT(getRendererExtensions().pixelBufferObject); const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mFeatureLevel); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); // sRGB formats do not work with D3D11 buffer SRVs @@ -2665,7 +3018,7 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const } // We cannot support direct copies to non-color-renderable formats - if (d3d11FormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN) { return false; } @@ -2685,196 +3038,39 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const return true; } -gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, +gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); } -gl::Error Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut) - +ImageD3D *Renderer11::createImage() { - ASSERT(colorbuffer); - - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - ASSERT(renderTargetResource); - - *subresourceIndexOut = renderTarget->getSubresourceIndex(); - *texture2DOut = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTargetResource); - - if (!(*texture2DOut)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget"); - } - - return gl::Error(GL_NO_ERROR); + return new Image11(this); } -gl::Error Renderer11::blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, - const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) -{ - if (blitRenderTarget) - { - gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); - ASSERT(readBuffer); - - RenderTarget *readRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(readRenderTarget); - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (drawTarget->isEnabledColorAttachment(colorAttachment)) - { - gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); - ASSERT(drawBuffer); - - RenderTarget *drawRenderTarget = NULL; - error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(drawRenderTarget); - - error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget, - false, false); - if (error.isError()) - { - return error; - } - } - } - } - - if (blitDepth || blitStencil) - { - gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); - ASSERT(readBuffer); - - RenderTarget *readRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(readRenderTarget); - - gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); - ASSERT(drawBuffer); - - RenderTarget *drawRenderTarget = NULL; - error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(drawRenderTarget); - - error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false, - blitDepth, blitStencil); - if (error.isError()) - { - return error; - } - } - - invalidateFramebufferSwizzles(drawTarget); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) -{ - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); - - gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); - if (error.isError()) - { - return error; - } - - gl::Rectangle area; - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - gl::Buffer *packBuffer = pack.pixelBuffer.get(); - if (packBuffer != NULL) - { - Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); - PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels)); - - error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); - if (error.isError()) - { - SafeRelease(colorBufferTexture); - return error; - } - - packBuffer->getIndexRangeCache()->clear(); - } - else - { - error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); - if (error.isError()) - { - SafeRelease(colorBufferTexture); - return error; - } - } - - SafeRelease(colorBufferTexture); - - return gl::Error(GL_NO_ERROR); -} - -Image *Renderer11::createImage() -{ - return new Image11(); -} - -gl::Error Renderer11::generateMipmap(Image *dest, Image *src) +gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src) { Image11 *dest11 = Image11::makeImage11(dest); Image11 *src11 = Image11::makeImage11(src); return Image11::generateMipmap(dest11, src11); } -TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) +TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) { SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); return new TextureStorage11_2D(this, swapChain11); } -TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) { - return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels); + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly); } -TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) { - return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels); + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); } TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) @@ -2908,13 +3104,6 @@ RenderbufferImpl *Renderer11::createRenderbuffer() return renderbuffer; } -RenderbufferImpl *Renderer11::createRenderbuffer(SwapChain *swapChain, bool depth) -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - renderbuffer->setStorage(swapChain, depth); - return renderbuffer; -} - gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { @@ -3057,8 +3246,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type); - const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(params.format, params.type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); + GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); if (fastCopyFunc) { @@ -3076,10 +3265,14 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP } else { + ColorReadFunction colorReadFunction = sourceDXGIFormatInfo.colorReadFunction; + ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type); + uint8_t temp[16]; // Maximum size of any Color<T> type used. - META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) && - sizeof(temp) >= sizeof(gl::ColorUI) && - sizeof(temp) >= sizeof(gl::ColorI)); + static_assert(sizeof(temp) >= sizeof(gl::ColorF) && + sizeof(temp) >= sizeof(gl::ColorUI) && + sizeof(temp) >= sizeof(gl::ColorI), + "Unexpected size of gl::Color struct."); for (int y = 0; y < params.area.height; y++) { @@ -3090,8 +3283,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP // readFunc and writeFunc will be using the same type of color, CopyTexImage // will not allow the copy otherwise. - sourceDXGIFormatInfo.colorReadFunction(src, temp); - destFormatTypeInfo.colorWriteFunction(temp, dest); + colorReadFunction(src, temp); + colorWriteFunction(temp, dest); } } } @@ -3102,8 +3295,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, +gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, bool colorBlit, bool depthBlit, bool stencilBlit) { // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, @@ -3187,12 +3380,12 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat()); - bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); + bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit); gl::Error result(GL_NO_ERROR); - if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && + if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && (!(depthBlit || stencilBlit) || wholeBufferCopy)) { @@ -3276,6 +3469,11 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const return result; } +bool Renderer11::isES3Capable() const +{ + return (d3d11_gl::GetMaximumClientVersion(mFeatureLevel) > 2); +}; + ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) { D3D11_TEXTURE2D_DESC textureDesc; @@ -3314,50 +3512,6 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, } } -void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) -{ - ASSERT(attachment->isTexture()); - gl::Texture *texture = attachment->getTexture(); - - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - TextureStorage *texStorage = textureD3D->getNativeTexture(); - if (texStorage) - { - TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); - if (!texStorage11) - { - ERR("texture storage pointer unexpectedly null."); - return; - } - - texStorage11->invalidateSwizzleCacheLevel(mipLevel); - } -} - -void Renderer11::invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer) -{ - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment); - if (attachment && attachment->isTexture()) - { - invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel()); - } - } - - gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer(); - if (depthAttachment && depthAttachment->isTexture()) - { - invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel()); - } - - gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer(); - if (stencilAttachment && stencilAttachment->isTexture()) - { - invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel()); - } -} - bool Renderer11::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; @@ -3380,31 +3534,32 @@ bool Renderer11::getLUID(LUID *adapterLuid) const VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { - return d3d11::GetVertexFormatInfo(vertexFormat).conversionType; + return d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).conversionType; } GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const { - return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat).nativeFormat).componentType; + return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).nativeFormat).componentType; } void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const { - d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions); + d3d11_gl::GenerateCaps(mDevice, mDeviceContext, outCaps, outTextureCaps, outExtensions); } Workarounds Renderer11::generateWorkarounds() const { - return d3d11::GenerateWorkarounds(); + return d3d11::GenerateWorkarounds(mFeatureLevel); } void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) { - std::vector<ID3D11ShaderResourceView *> ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size()); + auto &record = currentSRVs[resourceSlot]; - if (currentSRVs[resourceSlot] != srv) + if (record.srv != reinterpret_cast<uintptr_t>(srv)) { if (shaderType == gl::SAMPLER_VERTEX) { @@ -3415,8 +3570,16 @@ void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv); } - currentSRVs[resourceSlot] = srv; + record.srv = reinterpret_cast<uintptr_t>(srv); + if (srv) + { + record.resource = reinterpret_cast<uintptr_t>(GetViewResource(srv)); + srv->GetDesc(&record.desc); + } + else + { + record.resource = 0; + } } } - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h index d44bd2fd30..cc7d6c237b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -6,24 +6,26 @@ // Renderer11.h: Defines a back-end specific class for the D3D11 renderer. -#ifndef LIBGLESV2_RENDERER_RENDERER11_H_ -#define LIBGLESV2_RENDERER_RENDERER11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ #include "common/angleutils.h" -#include "libGLESv2/angletypes.h" #include "common/mathutil.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" - -#include "libEGL/AttributeMap.h" +struct ID3D11DeviceContext1; namespace gl { class FramebufferAttachment; +struct ImageIndex; } namespace rx @@ -36,6 +38,7 @@ class Blit11; class Clear11; class PixelTransfer11; class RenderTarget11; +class Trim11; struct PackPixelsParams; enum @@ -44,29 +47,51 @@ enum MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 }; +// Possible reasons RendererD3D initialize can fail +enum D3D11InitError +{ + // The renderer loaded successfully + D3D11_INIT_SUCCESS = 0, + // Failed to load the ANGLE & D3D compiler libraries + D3D11_INIT_COMPILER_ERROR, + // Failed to load a necessary DLL (non-compiler) + D3D11_INIT_MISSING_DEP, + // CreateDevice returned E_INVALIDARG + D3D11_INIT_CREATEDEVICE_INVALIDARG, + // CreateDevice failed with an error other than invalid arg + D3D11_INIT_CREATEDEVICE_ERROR, + // DXGI 1.2 required but not found + D3D11_INIT_INCOMPATIBLE_DXGI, + // Other initialization error + D3D11_INIT_OTHER_ERROR, + NUM_D3D11_INIT_ERRORS +}; + class Renderer11 : public RendererD3D { public: - Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes); + explicit Renderer11(egl::Display *display); virtual ~Renderer11(); static Renderer11 *makeRenderer11(Renderer *renderer); - virtual EGLint initialize(); + egl::Error initialize() override; virtual bool resetDevice(); - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); + egl::ConfigSet generateConfigs() const override; - virtual gl::Error sync(bool block); + gl::Error flush() override; + gl::Error finish() override; - virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual gl::Error generateSwizzle(gl::Texture *texture); virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); + gl::Error setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) override; virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, @@ -78,31 +103,27 @@ class Renderer11 : public RendererD3D virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport); - virtual bool applyPrimitiveType(GLenum mode, GLsizei count); + virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize); gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive); virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray); - virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances); + virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances); virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - virtual void applyTransformFeedbackBuffers(const gl::State &state); + void applyTransformFeedbackBuffers(const gl::State &state) override; - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); + gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override; virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override; - virtual void markAllStateDirty(); // lost device - void notifyDeviceLost() override; - bool isDeviceLost() override; - bool testDeviceLost(bool notify) override; + bool testDeviceLost() override; bool testDeviceResettable() override; - DWORD getAdapterVendor() const override; + VendorID getVendorId() const override; std::string getRendererDescription() const override; GUID getAdapterIdentifier() const override; @@ -114,50 +135,47 @@ class Renderer11 : public RendererD3D virtual bool getPostSubBufferSupport() const; virtual int getMajorShaderModel() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; + int getMinorShaderModel() const override; + std::string getShaderModelSuffix() const override; // Pixel operations - virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - - gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) override; - - virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); // RenderTarget creation - virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT); - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT); + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + + // Framebuffer creation + FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; + FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; // Shader creation - virtual ShaderImpl *createShader(const gl::Data &data, GLenum type); + virtual CompilerImpl *createCompiler(const gl::Data &data); + virtual ShaderImpl *createShader(GLenum type); virtual ProgramImpl *createProgram(); // Shader operations - void releaseShaderCompiler() override; virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable); + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable); - virtual UniformStorage *createUniformStorage(size_t storageSize); + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable); + virtual UniformStorageD3D *createUniformStorage(size_t storageSize); // Image operations - virtual Image *createImage(); - gl::Error generateMipmap(Image *dest, Image *source) override; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); + virtual ImageD3D *createImage(); + gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); @@ -166,7 +184,6 @@ class Renderer11 : public RendererD3D // Renderbuffer creation virtual RenderbufferImpl *createRenderbuffer(); - virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth); // Buffer creation virtual BufferImpl *createBuffer(); @@ -187,23 +204,22 @@ class Renderer11 : public RendererD3D // D3D11-renderer specific methods ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }; DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } Blit11 *getBlitter() { return mBlit; } + Clear11 *getClearer() { return mClear; } // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); - gl::Error getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut); - void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); - virtual bool getLUID(LUID *adapterLuid) const; + bool getLUID(LUID *adapterLuid) const override; virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; @@ -212,48 +228,51 @@ class Renderer11 : public RendererD3D void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv); - private: - DISALLOW_COPY_AND_ASSIGN(Renderer11); + gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit); + bool isES3Capable() const; + D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; }; + + RendererClass getRendererClass() const override { return RENDERER_D3D11; } + + private: void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; Workarounds generateWorkarounds() const override; gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); - gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, - bool colorBlit, bool depthBlit, bool stencilBlit); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); - void unsetSRVsWithResource(gl::SamplerType shaderType, const ID3D11Resource *resource); - - static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel); - static void invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer); + void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex *index); HMODULE mD3d11Module; HMODULE mDxgiModule; - EGLNativeDisplayType mDc; std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels; D3D_DRIVER_TYPE mDriverType; HLSLCompiler mCompiler; - bool mDeviceLost; - void initializeDevice(); void releaseDeviceResources(); - int getMinorShaderModel() const; void release(); RenderStateCache mStateCache; // current render target states - unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; + uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + uintptr_t mAppliedDSV; bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; - RenderTarget::Desc mRenderTargetDesc; + + struct RenderTargetDesc + { + size_t width; + size_t height; + DXGI_FORMAT format; + }; + RenderTargetDesc mRenderTargetDesc; // Currently applied sampler states std::vector<bool> mForceSetVertexSamplerStates; @@ -263,8 +282,14 @@ class Renderer11 : public RendererD3D std::vector<gl::SamplerState> mCurPixelSamplerStates; // Currently applied textures - std::vector<ID3D11ShaderResourceView*> mCurVertexSRVs; - std::vector<ID3D11ShaderResourceView*> mCurPixelSRVs; + struct SRVRecord + { + uintptr_t srv; + uintptr_t resource; + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + }; + std::vector<SRVRecord> mCurVertexSRVs; + std::vector<SRVRecord> mCurPixelSRVs; // Currently applied blend state bool mForceSetBlendState; @@ -302,6 +327,7 @@ class Renderer11 : public RendererD3D unsigned int mAppliedIBOffset; // Currently applied transform feedback buffers + size_t mAppliedNumXFBBindings; ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers // in use for streamout GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified @@ -312,22 +338,25 @@ class Renderer11 : public RendererD3D // to different append behavior // Currently applied shaders - ID3D11VertexShader *mAppliedVertexShader; - ID3D11GeometryShader *mAppliedGeometryShader; - ID3D11GeometryShader *mCurPointGeometryShader; - ID3D11PixelShader *mAppliedPixelShader; + uintptr_t mAppliedVertexShader; + uintptr_t mAppliedGeometryShader; + uintptr_t mAppliedPixelShader; dx_VertexConstants mVertexConstants; dx_VertexConstants mAppliedVertexConstants; ID3D11Buffer *mDriverConstantBufferVS; ID3D11Buffer *mCurrentVertexConstantBuffer; unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; dx_PixelConstants mPixelConstants; dx_PixelConstants mAppliedPixelConstants; ID3D11Buffer *mDriverConstantBufferPS; ID3D11Buffer *mCurrentPixelConstantBuffer; - unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; ID3D11Buffer *mCurrentGeometryConstantBuffer; @@ -346,17 +375,26 @@ class Renderer11 : public RendererD3D // Masked clear resources Clear11 *mClear; + // Perform trim for D3D resources + Trim11 *mTrim; + // Sync query ID3D11Query *mSyncQuery; + // Constant buffer offset support + bool mSupportsConstantBufferOffsets; + ID3D11Device *mDevice; D3D_FEATURE_LEVEL mFeatureLevel; ID3D11DeviceContext *mDeviceContext; + ID3D11DeviceContext1 *mDeviceContext1; IDXGIAdapter *mDxgiAdapter; DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; DXGIFactory *mDxgiFactory; + + DebugAnnotator11 mAnnotator; }; } -#endif // LIBGLESV2_RENDERER_RENDERER11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp index 52f34887fb..7e64c3183d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -7,14 +7,14 @@ // ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" namespace rx { ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) - : ShaderExecutable(function, length) + : ShaderExecutableD3D(function, length) { mPixelExecutable = executable; mVertexExecutable = NULL; @@ -23,7 +23,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D } ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) - : ShaderExecutable(function, length) + : ShaderExecutableD3D(function, length) { mVertexExecutable = executable; mPixelExecutable = NULL; @@ -32,7 +32,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D } ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) - : ShaderExecutable(function, length) + : ShaderExecutableD3D(function, length) { mGeometryExecutable = executable; mVertexExecutable = NULL; @@ -48,7 +48,7 @@ ShaderExecutable11::~ShaderExecutable11() SafeRelease(mStreamOutExecutable); } -ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) +ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutableD3D *executable) { ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); return static_cast<ShaderExecutable11*>(executable); @@ -75,7 +75,7 @@ ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const } UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) - : UniformStorage(initialSize), + : UniformStorageD3D(initialSize), mConstantBuffer(NULL) { ID3D11Device *d3d11Device = renderer->getDevice(); @@ -101,7 +101,7 @@ UniformStorage11::~UniformStorage11() SafeRelease(mConstantBuffer); } -const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorage *uniformStorage) +const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorageD3D *uniformStorage) { ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage)); return static_cast<const UniformStorage11*>(uniformStorage); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h index 74a1e03915..02558ee4dc 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -7,17 +7,17 @@ // ShaderExecutable11.h: Defines a D3D11-specific class to contain shader // executable implementation details. -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ -#include "libGLESv2/renderer/ShaderExecutable.h" +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" namespace rx { class Renderer11; class UniformStorage11; -class ShaderExecutable11 : public ShaderExecutable +class ShaderExecutable11 : public ShaderExecutableD3D { public: ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); @@ -26,7 +26,7 @@ class ShaderExecutable11 : public ShaderExecutable virtual ~ShaderExecutable11(); - static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable); + static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutableD3D *executable); ID3D11PixelShader *getPixelShader() const; ID3D11VertexShader *getVertexShader() const; @@ -34,21 +34,19 @@ class ShaderExecutable11 : public ShaderExecutable ID3D11GeometryShader *getStreamOutShader() const; private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); - ID3D11PixelShader *mPixelExecutable; ID3D11VertexShader *mVertexExecutable; ID3D11GeometryShader *mGeometryExecutable; ID3D11GeometryShader *mStreamOutExecutable; }; -class UniformStorage11 : public UniformStorage +class UniformStorage11 : public UniformStorageD3D { public: UniformStorage11(Renderer11 *renderer, size_t initialSize); virtual ~UniformStorage11(); - static const UniformStorage11 *makeUniformStorage11(const UniformStorage *uniformStorage); + static const UniformStorage11 *makeUniformStorage11(const UniformStorageD3D *uniformStorage); ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } @@ -58,4 +56,4 @@ class UniformStorage11 : public UniformStorage } -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index 52c8a81633..298f3ccbd2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -6,17 +6,17 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/features.h" // Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" -#include "common/features.h" -#include "common/NativeWindow.h" namespace rx { @@ -24,7 +24,9 @@ namespace rx SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) : mRenderer(renderer), - SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat) + SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + mColorRenderTarget(this, renderer, false), + mDepthStencilRenderTarget(this, renderer, true) { mSwapChain = NULL; mBackBufferTexture = NULL; @@ -42,8 +44,6 @@ SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE mPassThroughPS = NULL; mWidth = -1; mHeight = -1; - mRotateL = false; - mRotateR = false; mSwapInterval = 0; mAppCreatedShareHandle = mShareHandle != NULL; mPassThroughResourcesInit = false; @@ -94,11 +94,10 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(device != NULL); // D3D11 does not allow zero size textures - ASSERT(backbufferWidth != 0); - ASSERT(backbufferHeight != 0); + ASSERT(backbufferWidth >= 1); + ASSERT(backbufferHeight >= 1); // Preserve the render target content -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { @@ -106,11 +105,10 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } const int previousWidth = mWidth; const int previousHeight = mHeight; -#endif releaseOffscreenTexture(); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); // If the app passed in a share handle, open the resource // See EGL_ANGLE_d3d_share_handle_client_buffer @@ -140,8 +138,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); - if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) || - offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) || + if (offscreenTextureDesc.Width != (UINT)backbufferWidth || + offscreenTextureDesc.Height != (UINT)backbufferHeight || offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1) @@ -156,8 +154,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - offscreenTextureDesc.Width = abs(backbufferWidth); - offscreenTextureDesc.Height = abs(backbufferHeight); +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + const int textureLength = std::max(backbufferWidth, backbufferHeight); + offscreenTextureDesc.Width = textureLength; + offscreenTextureDesc.Height = textureLength; +#else + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; +#endif offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; @@ -226,26 +230,38 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; offscreenSRVDesc.Texture2D.MostDetailedMip = 0; - offscreenSRVDesc.Texture2D.MipLevels = -1; + offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); - const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat); + const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getFeatureLevel()); if (mDepthBufferFormat != GL_NONE) { D3D11_TEXTURE2D_DESC depthStencilTextureDesc; - depthStencilTextureDesc.Width = abs(backbufferWidth); - depthStencilTextureDesc.Height = abs(backbufferHeight); +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + const int textureLength = std::max(backbufferWidth, backbufferHeight); + depthStencilTextureDesc.Width = textureLength; + depthStencilTextureDesc.Height = textureLength; +#else + depthStencilTextureDesc.Width = backbufferWidth; + depthStencilTextureDesc.Height = backbufferHeight; +#endif depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; depthStencilTextureDesc.MipLevels = 1; depthStencilTextureDesc.ArraySize = 1; depthStencilTextureDesc.SampleDesc.Count = 1; depthStencilTextureDesc.SampleDesc.Quality = 0; depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; - depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + + if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + depthStencilTextureDesc.CPUAccessFlags = 0; depthStencilTextureDesc.MiscFlags = 0; @@ -276,21 +292,23 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); - D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; - depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; - depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; - depthStencilSRVDesc.Texture2D.MipLevels = -1; - - result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); + if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; + depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; + depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); + + result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); + } } mWidth = backbufferWidth; mHeight = backbufferHeight; -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) if (previousOffscreenTexture != NULL) { D3D11_BOX sourceBox = {0}; @@ -312,7 +330,6 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei swapRect(0, 0, mWidth, mHeight); } } -#endif return EGL_SUCCESS; } @@ -326,31 +343,23 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_BAD_ACCESS; } - // Windows Phone works around the rotation limitation by using negative values for the swap chain size -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape - mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape - backbufferWidth = abs(backbufferWidth); - backbufferHeight = abs(backbufferHeight); -#endif - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth == 0 || backbufferHeight == 0) + if (backbufferWidth < 1 || backbufferHeight < 1) { return EGL_SUCCESS; } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) // Can only call resize if we have already created our swap buffer and resources ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); // Resize swap chain DXGI_SWAP_CHAIN_DESC desc; mSwapChain->GetDesc(&desc); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); if (FAILED(result)) @@ -381,9 +390,14 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) { d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); } -#endif return resetOffscreenTexture(backbufferWidth, backbufferHeight); +#else + // Do nothing on Windows Phone apart from updating the internal buffer/width height + mWidth = backbufferWidth; + mHeight = backbufferHeight; + return EGL_SUCCESS; +#endif } EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) @@ -417,7 +431,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mNativeWindow.getNativeWindow()) { - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), backbufferFormatInfo.texFormat, @@ -528,20 +542,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // Create a quad in homogeneous coordinates - float x1 = (x / float(mWidth)) * 2.0f - 1.0f; - float y1 = (y / float(mHeight)) * 2.0f - 1.0f; - float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; - float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - const bool rotateL = mRotateL; - const bool rotateR = mRotateR; - // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); @@ -552,10 +552,37 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); + // Create a quad in homogeneous coordinates + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + const float dim = std::max(mWidth, mHeight); + float u1 = x / dim; + float v1 = y / dim; + float u2 = (x + width) / dim; + float v2 = (y + height) / dim; + + const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags(); + const bool rotateL = flags == NativeWindow::RotateLeft; + const bool rotateR = flags == NativeWindow::RotateRight; d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2); +#else + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); +#endif deviceContext->Unmap(mQuadVB, 0); @@ -583,11 +610,15 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) // Set the viewport D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0.0f; - viewport.TopLeftY = 0.0f; - const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR); - viewport.Width = FLOAT(invertViewport ? mHeight : mWidth); - viewport.Height = FLOAT(invertViewport ? mWidth : mHeight); + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + viewport.Width = (rotateL || rotateR) ? mHeight : mWidth; + viewport.Height = (rotateL || rotateR) ? mWidth : mHeight; +#else + viewport.Width = mWidth; + viewport.Height = mHeight; +#endif viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); @@ -661,7 +692,7 @@ ID3D11Texture2D *SwapChain11::getDepthStencilTexture() return mDepthStencilTexture; } -SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) +SwapChain11 *SwapChain11::makeSwapChain11(SwapChainD3D *swapChain) { ASSERT(HAS_DYNAMIC_TYPE(SwapChain11*, swapChain)); return static_cast<SwapChain11*>(swapChain); @@ -672,4 +703,9 @@ void SwapChain11::recreate() // possibly should use this method instead of reset } +void *rx::SwapChain11::getDevice() +{ + return mRenderer->getDevice(); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h index 77509edcd3..48c808a261 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h @@ -6,17 +6,18 @@ // SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ #include "common/angleutils.h" -#include "libGLESv2/renderer/SwapChain.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" namespace rx { class Renderer11; -class SwapChain11 : public SwapChain +class SwapChain11 : public SwapChainD3D { public: SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, @@ -28,6 +29,9 @@ class SwapChain11 : public SwapChain virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); virtual void recreate(); + RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } + RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + virtual ID3D11Texture2D *getOffscreenTexture(); virtual ID3D11RenderTargetView *getRenderTarget(); virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); @@ -39,11 +43,11 @@ class SwapChain11 : public SwapChain EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } - static SwapChain11 *makeSwapChain11(SwapChain *swapChain); + virtual void *getDevice(); - private: - DISALLOW_COPY_AND_ASSIGN(SwapChain11); + static SwapChain11 *makeSwapChain11(SwapChainD3D *swapChain); + private: void release(); void initPassThroughResources(); void releaseOffscreenTexture(); @@ -52,8 +56,6 @@ class SwapChain11 : public SwapChain Renderer11 *mRenderer; EGLint mHeight; EGLint mWidth; - bool mRotateL; - bool mRotateR; bool mAppCreatedShareHandle; unsigned int mSwapInterval; bool mPassThroughResourcesInit; @@ -76,7 +78,10 @@ class SwapChain11 : public SwapChain ID3D11InputLayout *mPassThroughIL; ID3D11VertexShader *mPassThroughVS; ID3D11PixelShader *mPassThroughPS; + + SurfaceRenderTarget11 mColorRenderTarget; + SurfaceRenderTarget11 mDepthStencilRenderTarget; }; } -#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp index 74af27e8b3..103e90fed3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -7,23 +7,22 @@ // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include <tuple> -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/main.h" -#include "libGLESv2/ImageIndex.h" - +#include "common/MemoryBuffer.h" #include "common/utilities.h" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace rx { @@ -102,11 +101,11 @@ TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage return static_cast<TextureStorage11*>(storage); } -DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget) +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget) { UINT bindFlags = 0; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel); if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; @@ -176,11 +175,27 @@ gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11S { bool swizzleRequired = samplerState.swizzleRequired(); bool mipmapping = gl::IsMipmapFiltered(samplerState); - unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1; + unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel + 1) : 1; // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(!swizzleRequired); + ASSERT(mipLevels == 1 || mipLevels == mMipLevels); + } + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // We must ensure that the level zero texture is in sync with mipped texture. + gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); + if (error.isError()) + { + return error; + } + } + if (swizzleRequired) { verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); @@ -329,7 +344,19 @@ gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, u copyArea.depth == texSize.depth; ID3D11Resource *dstTexture = NULL; - gl::Error error = getResource(&dstTexture); + gl::Error error(GL_NO_ERROR); + + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should + // update the mipmapped texture, even if mapmaps are currently disabled. + if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + error = getMippedResource(&dstTexture); + } + else + { + error = getResource(&dstTexture); + } + if (error.isError()) { return error; @@ -351,8 +378,6 @@ gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, u } else { - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - D3D11_BOX srcBox; srcBox.left = copyArea.x; srcBox.top = copyArea.y; @@ -375,7 +400,19 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, uns ASSERT(dstTexture); ID3D11Resource *srcTexture = NULL; - gl::Error error = getResource(&srcTexture); + gl::Error error(GL_NO_ERROR); + + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should + // update the mipmapped texture, even if mapmaps are currently disabled. + if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + error = getMippedResource(&srcTexture); + } + else + { + error = getResource(&srcTexture); + } + if (error.isError()) { return error; @@ -386,8 +423,28 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, uns unsigned int srcSubresource = getSubresourceIndex(index); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL. + D3D11_BOX srcBox; + D3D11_BOX *pSrcBox = NULL; + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the source box + // is specified. This is okay, since we don't perform CopySubresourceRegion on depth/stencil + // textures on 9_3. + ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).depthBits == 0); + ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).stencilBits == 0); + srcBox.left = region.x; + srcBox.right = region.x + region.width; + srcBox.top = region.y; + srcBox.bottom = region.y + region.height; + srcBox.front = region.z; + srcBox.back = region.z + region.depth; + pSrcBox = &srcBox; + } + context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z, - srcTexture, srcSubresource, NULL); + srcTexture, srcSubresource, pSrcBox); return gl::Error(GL_NO_ERROR); } @@ -398,14 +455,14 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co invalidateSwizzleCacheLevel(destIndex.mipIndex); - RenderTarget *source = NULL; + RenderTargetD3D *source = NULL; gl::Error error = getRenderTarget(sourceIndex, &source); if (error.isError()) { return error; } - RenderTarget *dest = NULL; + RenderTargetD3D *dest = NULL; error = getRenderTarget(destIndex, &dest); if (error.isError()) { @@ -462,9 +519,11 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, +gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData) { + ASSERT(!image->isDirty()); + ID3D11Resource *resource = NULL; gl::Error error = getResource(&resource); if (error.isError()) @@ -477,7 +536,8 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat()); - bool fullUpdate = (destBox == NULL || *destBox == gl::Box(0, 0, 0, mTextureWidth, mTextureHeight, mTextureDepth)); + gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), getLevelDepth(index.mipIndex)); + bool fullUpdate = (destBox == NULL || *destBox == levelBox); ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate); // TODO(jmadill): Handle compressed formats @@ -489,10 +549,10 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c int width = destBox ? destBox->width : static_cast<int>(image->getWidth()); int height = destBox ? destBox->height : static_cast<int>(image->getHeight()); int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth()); - UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment); - UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment); + UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength); + UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength); - const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat()); + const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getFeatureLevel()); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); size_t outputPixelSize = dxgiFormatInfo.pixelBytes; @@ -500,17 +560,19 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c UINT bufferRowPitch = outputPixelSize * width; UINT bufferDepthPitch = bufferRowPitch * height; - MemoryBuffer conversionBuffer; - if (!conversionBuffer.resize(bufferDepthPitch * depth)) + size_t neededSize = bufferDepthPitch * depth; + MemoryBuffer *conversionBuffer = NULL; + error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + return error; } // TODO: fast path LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type); loadFunction(width, height, depth, pixelData, srcRowPitch, srcDepthPitch, - conversionBuffer.data(), bufferRowPitch, bufferDepthPitch); + conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); @@ -523,17 +585,17 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c destD3DBox.right = destBox->x + destBox->width; destD3DBox.top = destBox->y; destD3DBox.bottom = destBox->y + destBox->height; - destD3DBox.front = 0; - destD3DBox.back = 1; + destD3DBox.front = destBox->z; + destD3DBox.back = destBox->z + destBox->depth; immediateContext->UpdateSubresource(resource, destSubresource, - &destD3DBox, conversionBuffer.data(), + &destD3DBox, conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); } else { immediateContext->UpdateSubresource(resource, destSubresource, - NULL, conversionBuffer.data(), + NULL, conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); } @@ -543,7 +605,10 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), mTexture(swapchain->getOffscreenTexture()), - mSwizzleTexture(NULL) + mSwizzleTexture(NULL), + mLevelZeroTexture(NULL), + mLevelZeroRenderTarget(NULL), + mUseLevelZeroTexture(false) { mTexture->AddRef(); @@ -575,7 +640,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap mRenderTargetFormat = rtvDesc.Format; const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getFeatureLevel()); mSwizzleTextureFormat = formatInfo.swizzleTexFormat; mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; @@ -585,10 +650,13 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap initializeSerials(1, 1); } -TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)), +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)), mTexture(NULL), - mSwizzleTexture(NULL) + mSwizzleTexture(NULL), + mLevelZeroTexture(NULL), + mLevelZeroRenderTarget(NULL), + mUseLevelZeroTexture(false) { for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { @@ -599,7 +667,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalfo mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -614,6 +682,13 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalfo mTextureHeight = height; mTextureDepth = 1; + if (hintLevelZeroOnly && levels > 1) + { + //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + mUseLevelZeroTexture = true; + } + initializeSerials(getLevelCount(), 1); } @@ -641,6 +716,9 @@ TextureStorage11_2D::~TextureStorage11_2D() SafeRelease(mTexture); SafeRelease(mSwizzleTexture); + SafeRelease(mLevelZeroTexture); + SafeDelete(mLevelZeroRenderTarget); + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { SafeDelete(mRenderTarget[i]); @@ -654,6 +732,120 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage return static_cast<TextureStorage11_2D*>(storage); } +gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(destStorage); + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. + if (mTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mTexture); + } + + if (mLevelZeroTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mLevelZeroTexture); + } + } + else + { + ID3D11Resource *sourceResouce = NULL; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + } + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +{ + if (useLevelZeroTexture && mMipLevels > 1) + { + if (!mUseLevelZeroTexture && mTexture) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + // Pull data back from the mipped texture if necessary. + ASSERT(mLevelZeroTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, NULL); + } + + mUseLevelZeroTexture = true; + } + else + { + if (mUseLevelZeroTexture && mLevelZeroTexture) + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + // Pull data back from the level zero texture if necessary. + ASSERT(mTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, NULL); + } + + mUseLevelZeroTexture = false; + } + + return gl::Error(GL_NO_ERROR); +} + void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index) { GLint level = index.mipIndex; @@ -733,18 +925,63 @@ gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &inde gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) { + if (mUseLevelZeroTexture && mMipLevels > 1) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + *outResource = mLevelZeroTexture; + return gl::Error(GL_NO_ERROR); + } + else + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) +{ + // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false; + ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + // if the width or height is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation - if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) { - ASSERT(mMipLevels > 0); + ASSERT(mipLevels > 0); ID3D11Device *device = mRenderer->getDevice(); D3D11_TEXTURE2D_DESC desc; desc.Width = mTextureWidth; // Compressed texture size constraints? desc.Height = mTextureHeight; - desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels; + desc.MipLevels = mipLevels; desc.ArraySize = 1; desc.Format = mTextureFormat; desc.SampleDesc.Count = 1; @@ -754,7 +991,7 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) desc.CPUAccessFlags = 0; desc.MiscFlags = 0; - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); // this can happen from windows TDR if (d3d11::isDeviceLostError(result)) @@ -769,17 +1006,23 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) } } - *outResource = mTexture; return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); int level = index.mipIndex; ASSERT(level >= 0 && level < getLevelCount()); + // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of the GLES 2.0 spec, page 113 of version 2.0.25). + // Other parts of TextureStorage11_2D could create RTVs on non-zero levels of the texture (e.g. generateMipmap). + // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the individual levels of the texture, + // so methods like generateMipmap can't do anything useful with non-zero-level RTVs. + // Therefore if level > 0 on 9_3 then there's almost certainly something wrong. + ASSERT(!(mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3 && level > 0)); + if (!mRenderTarget[level]) { ID3D11Resource *texture = NULL; @@ -796,6 +1039,37 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend return error; } + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + ASSERT(SUCCEEDED(result)); + + mLevelZeroRenderTarget = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelZeroRenderTarget; + return gl::Error(GL_NO_ERROR); + } + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) { ID3D11Device *device = mRenderer->getDevice(); @@ -863,10 +1137,32 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM srvDesc.Format = format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11Resource *srvTexture = texture; + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(mTopLevel == 0); + ASSERT(baseLevel == 0); + // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture. + + if (mipLevels == 1 && mMipLevels > 1) + { + // We must use a SRV on the level-zero-only texture. + ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture); + srvTexture = mLevelZeroTexture; + } + else + { + ASSERT(mipLevels == static_cast<int>(mMipLevels)); + ASSERT(mTexture != NULL && texture == mTexture); + srvTexture = mTexture; + } + } ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); if (FAILED(result)) @@ -945,8 +1241,8 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render return gl::Error(GL_NO_ERROR); } -TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) +TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -961,9 +1257,17 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum intern } } + mLevelZeroTexture = NULL; + mUseLevelZeroTexture = false; + + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + mLevelZeroRenderTarget[face] = NULL; + } + mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -981,6 +1285,13 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum intern mTextureHeight = size; mTextureDepth = 1; + if (hintLevelZeroOnly && levels > 1) + { + //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + mUseLevelZeroTexture = true; + } + initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); } @@ -1006,6 +1317,12 @@ TextureStorage11_Cube::~TextureStorage11_Cube() SafeRelease(mTexture); SafeRelease(mSwizzleTexture); + SafeRelease(mLevelZeroTexture); + + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + SafeDelete(mLevelZeroRenderTarget[face]); + } for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { @@ -1023,6 +1340,147 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS return static_cast<TextureStorage11_Cube*>(storage); } +UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const +{ + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0) + { + UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(0, arraySlice, 1); + ASSERT(subresource != std::numeric_limits<UINT>::max()); + return subresource; + } + else + { + UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); + ASSERT(subresource != std::numeric_limits<UINT>::max()); + return subresource; + } +} + +gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(destStorage); + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. + if (mTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mTexture); + } + + if (mLevelZeroTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mLevelZeroTexture); + } + } + else + { + ID3D11Resource *sourceResouce = NULL; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + } + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +{ + if (useLevelZeroTexture && mMipLevels > 1) + { + if (!mUseLevelZeroTexture && mTexture) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + // Pull data back from the mipped texture if necessary. + ASSERT(mLevelZeroTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + for (int face = 0; face < 6; face++) + { + context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), 0, 0, 0, mTexture, face * mMipLevels, NULL); + } + } + + mUseLevelZeroTexture = true; + } + else + { + if (mUseLevelZeroTexture && mLevelZeroTexture) + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + // Pull data back from the level zero texture if necessary. + ASSERT(mTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + for (int face = 0; face < 6; face++) + { + context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), 0, 0, 0, mLevelZeroTexture, face, NULL); + } + } + + mUseLevelZeroTexture = false; + } + + return gl::Error(GL_NO_ERROR); +} + void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index) { GLint level = index.mipIndex; @@ -1121,9 +1579,54 @@ gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &in gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) { + if (mUseLevelZeroTexture && mMipLevels > 1) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + *outResource = mLevelZeroTexture; + return gl::Error(GL_NO_ERROR); + } + else + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels) +{ + // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false; + ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation - if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) { ASSERT(mMipLevels > 0); @@ -1132,7 +1635,7 @@ gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) D3D11_TEXTURE2D_DESC desc; desc.Width = mTextureWidth; desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; + desc.MipLevels = mipLevels; desc.ArraySize = CUBE_FACE_COUNT; desc.Format = mTextureFormat; desc.SampleDesc.Count = 1; @@ -1142,7 +1645,7 @@ gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) desc.CPUAccessFlags = 0; desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); // this can happen from windows TDR if (d3d11::isDeviceLostError(result)) @@ -1157,11 +1660,10 @@ gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) } } - *outResource = mTexture; return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { int faceIndex = index.layerIndex; int level = index.mipIndex; @@ -1181,14 +1683,53 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re return error; } + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget[faceIndex]) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + ASSERT(SUCCEEDED(result)); + + mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelZeroRenderTarget[faceIndex]; + return gl::Error(GL_NO_ERROR); + } + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; srvDesc.Texture2DArray.MipLevels = 1; srvDesc.Texture2DArray.FirstArraySlice = faceIndex; srvDesc.Texture2DArray.ArraySize = 1; + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + } + ID3D11ShaderResourceView *srv; result = device->CreateShaderResourceView(texture, &srvDesc, &srv); @@ -1285,8 +1826,30 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; } + ID3D11Resource *srvTexture = texture; + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(mTopLevel == 0); + ASSERT(baseLevel == 0); + // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture. + + if (mipLevels == 1 && mMipLevels > 1) + { + // We must use a SRV on the level-zero-only texture. + ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture); + srvTexture = mLevelZeroTexture; + } + else + { + ASSERT(mipLevels == static_cast<int>(mMipLevels)); + ASSERT(mTexture != NULL && texture == mTexture); + srvTexture = mTexture; + } + } + ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); if (FAILED(result)) @@ -1369,7 +1932,7 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11Rend TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -1383,7 +1946,7 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalfo mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -1582,7 +2145,7 @@ gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORM return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { int mipLevel = index.mipIndex; ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); @@ -1614,7 +2177,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = -1; + rtvDesc.Texture3D.WSize = static_cast<UINT>(-1); ID3D11RenderTargetView *rtv; HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); @@ -1738,7 +2301,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = -1; + rtvDesc.Texture3D.WSize = static_cast<UINT>(-1); HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); @@ -1755,7 +2318,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -1767,7 +2330,7 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -1791,13 +2354,16 @@ TextureStorage11_2DArray::~TextureStorage11_2DArray() { for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) { - bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) + if (i->second) { - // We must let the Images recover their data before we delete it from the TextureStorage. - i->second->recoverFromAssociatedStorage(); + bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + i->second->recoverFromAssociatedStorage(); + } } } mAssociatedImages.clear(); @@ -1875,8 +2441,6 @@ gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex LevelLayerKey key(level, layerTarget); - ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end()); - if (mAssociatedImages.find(key) != mAssociatedImages.end()) { if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) @@ -1966,7 +2530,7 @@ gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(index.hasLayer()); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h index 930300a63d..456e2660f9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -7,12 +7,12 @@ // TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ -#include "libGLESv2/Texture.h" -#include "libGLESv2/Error.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" #include <map> @@ -23,7 +23,7 @@ struct ImageIndex; namespace rx { -class RenderTarget; +class RenderTargetD3D; class RenderTarget11; class Renderer11; class SwapChain11; @@ -36,13 +36,13 @@ class TextureStorage11 : public TextureStorage static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget); + static DWORD GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget); UINT getBindFlags() const; virtual gl::Error getResource(ID3D11Resource **outResource) = 0; virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); @@ -50,7 +50,7 @@ class TextureStorage11 : public TextureStorage virtual bool isRenderTarget() const; virtual bool isManaged() const; virtual int getLevelCount() const; - UINT getSubresourceIndex(const gl::ImageIndex &index) const; + virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); void invalidateSwizzleCacheLevel(int mipLevel); @@ -68,7 +68,7 @@ class TextureStorage11 : public TextureStorage virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0; virtual gl::Error copyToStorage(TextureStorage *destStorage); - virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData); protected: @@ -77,6 +77,9 @@ class TextureStorage11 : public TextureStorage int getLevelHeight(int mipLevel) const; int getLevelDepth(int mipLevel) const; + // Some classes (e.g. TextureStorage11_2D) will override getMippedResource. + virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); } + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV); @@ -118,8 +121,6 @@ class TextureStorage11 : public TextureStorage SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11); - const UINT mBindFlags; struct SRVKey @@ -142,32 +143,51 @@ class TextureStorage11_2D : public TextureStorage11 { public: TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); - TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false); virtual ~TextureStorage11_2D(); static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getMippedResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::Error copyToStorage(TextureStorage *destStorage); virtual void associateImage(Image11* image, const gl::ImageIndex &index); virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + protected: virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); + gl::Error ensureTextureExists(int mipLevels); + private: virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, ID3D11ShaderResourceView **outSRV) const; ID3D11Texture2D *mTexture; RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + // These are members related to the zero max-LOD workaround. + // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero). + // These members are used to work around this limitation. + // Usually only mTexture XOR mLevelZeroTexture will exist. + // For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture. + // However, in some scenarios, both textures have to be created. This incurs additional memory overhead. + // One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture. + // A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap + // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory. + ID3D11Texture2D *mLevelZeroTexture; + RenderTarget11 *mLevelZeroRenderTarget; + bool mUseLevelZeroTexture; + + // Swizzle-related variables ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; @@ -177,26 +197,33 @@ class TextureStorage11_2D : public TextureStorage11 class TextureStorage11_Cube : public TextureStorage11 { public: - TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual ~TextureStorage11_Cube(); static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); + virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getMippedResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::Error copyToStorage(TextureStorage *destStorage); virtual void associateImage(Image11* image, const gl::ImageIndex &index); virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + protected: virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); + gl::Error ensureTextureExists(int mipLevels); + private: virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, ID3D11ShaderResourceView **outSRV) const; @@ -205,6 +232,11 @@ class TextureStorage11_Cube : public TextureStorage11 ID3D11Texture2D *mTexture; RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description. + ID3D11Texture2D *mLevelZeroTexture; + RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT]; + bool mUseLevelZeroTexture; + ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; @@ -223,7 +255,7 @@ class TextureStorage11_3D : public TextureStorage11 virtual gl::Error getResource(ID3D11Resource **outResource); // Handles both layer and non-layer RTs - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual void associateImage(Image11* image, const gl::ImageIndex &index); virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); @@ -235,8 +267,6 @@ class TextureStorage11_3D : public TextureStorage11 virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D); - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, ID3D11ShaderResourceView **outSRV) const; @@ -263,7 +293,7 @@ class TextureStorage11_2DArray : public TextureStorage11 static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual void associateImage(Image11* image, const gl::ImageIndex &index); virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); @@ -275,8 +305,6 @@ class TextureStorage11_2DArray : public TextureStorage11 virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray); - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, ID3D11ShaderResourceView **outSRV) const; @@ -295,4 +323,4 @@ class TextureStorage11_2DArray : public TextureStorage11 } -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp new file mode 100644 index 0000000000..213ce31817 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp @@ -0,0 +1,95 @@ +// +// 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. +// + +// Trim11.cpp: Trim support utility class. + +#include "libANGLE/renderer/d3d/d3d11/Trim11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#if defined (ANGLE_ENABLE_WINDOWS_STORE) +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::ApplicationModel; +using namespace ABI::Windows::ApplicationModel::Core; +#endif + +namespace rx +{ + +Trim11::Trim11(rx::Renderer11 *renderer) + : mRenderer(renderer) +{ + bool result = true; + result = registerForRendererTrimRequest(); + ASSERT(result); +} + +Trim11::~Trim11() +{ + unregisterForRendererTrimRequest(); +} + +void Trim11::trim() +{ + if (!mRenderer) + { + return; + } + +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + ID3D11Device* device = mRenderer->getDevice(); + // IDXGIDevice3 is only supported on Windows 8.1 and Windows Phone 8.1 and above. + IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device); + if (dxgiDevice3) + { + dxgiDevice3->Trim(); + } + SafeRelease(dxgiDevice3); +#endif +} + +bool Trim11::registerForRendererTrimRequest() +{ +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + ICoreApplication* coreApplication = nullptr; + HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication); + if (SUCCEEDED(result)) + { + auto suspendHandler = Callback<IEventHandler<SuspendingEventArgs*>>( + [this](IInspectable*, ISuspendingEventArgs*) -> HRESULT + { + trim(); + return S_OK; + }); + result = coreApplication->add_Suspending(suspendHandler.Get(), &mApplicationSuspendedEventToken); + } + SafeRelease(coreApplication); + + if (FAILED(result)) + { + return false; + } +#endif + return true; +} + +void Trim11::unregisterForRendererTrimRequest() +{ +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + if (mApplicationSuspendedEventToken.value != 0) + { + ICoreApplication* coreApplication = nullptr; + if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication))) + { + coreApplication->remove_Suspending(mApplicationSuspendedEventToken); + } + mApplicationSuspendedEventToken.value = 0; + SafeRelease(coreApplication); + } +#endif +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h new file mode 100644 index 0000000000..f232ad7e8e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h @@ -0,0 +1,43 @@ +// +// 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. +// + +// Trim11.h: Trim support utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef void* EventRegistrationToken; +#else +#include <EventToken.h> +#endif + +namespace rx +{ +class Renderer11; + +class Trim11 : angle::NonCopyable +{ + public: + explicit Trim11(Renderer11 *renderer); + ~Trim11(); + + private: + Renderer11 *mRenderer; + EventRegistrationToken mApplicationSuspendedEventToken; + + void trim(); + bool registerForRendererTrimRequest(); + void unregisterForRendererTrimRequest(); +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h index 70bc3bb26f..78aad7d106 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -6,11 +6,11 @@ // VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. -#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_ -#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ -#include "libGLESv2/renderer/VertexArrayImpl.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" namespace rx { @@ -32,11 +32,9 @@ class VertexArray11 : public VertexArrayImpl virtual void enableAttribute(size_t idx, bool enabledState) { } private: - DISALLOW_COPY_AND_ASSIGN(VertexArray11); - Renderer11 *mRenderer; }; } -#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp index a9d6fa2ca4..adc64cef5e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -6,12 +6,12 @@ // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. -#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/VertexAttribute.h" namespace rx { @@ -21,10 +21,12 @@ VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) mBuffer = NULL; mBufferSize = 0; mDynamicUsage = false; + mMappedResourceData = NULL; } VertexBuffer11::~VertexBuffer11() { + ASSERT(mMappedResourceData == NULL); SafeRelease(mBuffer); } @@ -65,6 +67,37 @@ VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) return static_cast<VertexBuffer11*>(vetexBuffer); } +gl::Error VertexBuffer11::mapResource() +{ + if (mMappedResourceData == NULL) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); + } + + mMappedResourceData = reinterpret_cast<uint8_t*>(mappedResource.pData); + } + + return gl::Error(GL_NO_ERROR); +} + +void VertexBuffer11::hintUnmapResource() +{ + if (mMappedResourceData != NULL) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + + mMappedResourceData = NULL; + } +} + gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, GLint start, GLsizei count, GLsizei instances, unsigned int offset) { @@ -75,24 +108,23 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri gl::Buffer *buffer = attrib.buffer.get(); int inputStride = ComputeVertexAttributeStride(attrib); - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) + // This will map the resource if it isn't already mapped. + gl::Error error = mapResource(); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); + return error; } - uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset; + uint8_t *output = mMappedResourceData + offset; const uint8_t *input = NULL; if (attrib.enabled) { if (buffer) { - BufferD3D *storage = BufferD3D::makeFromBuffer(buffer); - gl::Error error = storage->getData(&input); + BufferD3D *storage = GetImplAs<BufferD3D>(buffer); + error = storage->getData(&input); if (error.isError()) { return error; @@ -115,12 +147,10 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri } gl::VertexFormat vertexFormat(attrib, currentValue.Type); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel()); ASSERT(vertexFormatInfo.copyFunction != NULL); vertexFormatInfo.copyFunction(input, inputStride, count, output); - dxContext->Unmap(mBuffer, 0); - return gl::Error(GL_NO_ERROR); } @@ -141,7 +171,7 @@ gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GL } gl::VertexFormat vertexFormat(attrib); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel()); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); unsigned int elementSize = dxgiFormatInfo.pixelBytes; if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h index a9bbac98fa..2450e8955c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h @@ -6,10 +6,12 @@ // VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ -#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include <stdint.h> + +#include "libANGLE/renderer/d3d/VertexBuffer.h" namespace rx { @@ -35,18 +37,22 @@ class VertexBuffer11 : public VertexBuffer virtual gl::Error setBufferSize(unsigned int size); virtual gl::Error discard(); + virtual void hintUnmapResource(); + ID3D11Buffer *getBuffer() const; private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); + gl::Error mapResource(); Renderer11 *const mRenderer; ID3D11Buffer *mBuffer; unsigned int mBufferSize; bool mDynamicUsage; + + uint8_t *mMappedResourceData; }; } -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h new file mode 100644 index 0000000000..5501e361f1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013-2015 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. +// + +// copyvertex.h: Defines D3D11 vertex buffer copying and conversion functions + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ + +#include "common/mathutil.h" + +namespace rx +{ + +// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component) +template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits> +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <size_t componentCount> +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized> +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template <bool isSigned, bool normalized, bool toFloat> +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +} + +#include "copyvertex.inl" + +#endif // LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl index 7eef17b22b..60678d7b9f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2014-2015 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. // @@ -7,40 +7,111 @@ namespace rx { -template <typename T, size_t componentCount, uint32_t widenDefaultValueBits> +template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits> inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) { - const size_t attribSize = sizeof(T)* componentCount; - const T defaultValue = gl::bitCast<T>(widenDefaultValueBits); - const bool widen = (widenDefaultValueBits != 0); + const size_t attribSize = sizeof(T)* inputComponentCount; - if (attribSize == stride && !widen) + if (attribSize == stride && inputComponentCount == outputComponentCount) { memcpy(output, input, count * attribSize); } else { - size_t outputStride = widen ? 4 : componentCount; + const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); for (size_t i = 0; i < count; i++) { const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride)); - T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride; + T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount; - for (size_t j = 0; j < componentCount; j++) + for (size_t j = 0; j < inputComponentCount; j++) { offsetOutput[j] = offsetInput[j]; } - if (widen) + for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) { - offsetOutput[3] = defaultValue; + // Set the remaining G/B channels to 0. + offsetOutput[j] = 0; } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // Set the remaining alpha channel to the defaultAlphaValue. + offsetOutput[3] = defaultAlphaValue; + } + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride); + GLshort *offsetOutput = reinterpret_cast<GLshort*>(output)+i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast<GLshort>(offsetInput[j]); + } + + for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On integer formats, we must set the Alpha channel to 1 if it's unused. + offsetOutput[3] = 1; } } } -template <size_t componentCount> +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride); + GLshort *offsetOutput = reinterpret_cast<GLshort*>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + // The original GLbyte value ranges from -128 to +127 (INT8_MAX). + // When converted to GLshort, the value must be scaled to between -32768 and +32767 (INT16_MAX). + if (offsetInput[j] > 0) + { + offsetOutput[j] = offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6); + } + else + { + offsetOutput[j] = offsetInput[j] << 8; + } + } + + for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On normalized formats, we must set the Alpha channel to the max value if it's unused. + offsetOutput[3] = INT16_MAX; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) { static const float divisor = 1.0f / (1 << 16); @@ -48,16 +119,25 @@ inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size for (size_t i = 0; i < count; i++) { const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(input + (stride * i)); - float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount; + float* offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount; - for (size_t j = 0; j < componentCount; j++) + for (size_t j = 0; j < inputComponentCount; j++) { offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor; } + + // 4-component output formats would need special padding in the alpha channel. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } } } -template <typename T, size_t componentCount, bool normalized> +template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized> inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) { typedef std::numeric_limits<T> NL; @@ -65,9 +145,9 @@ inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t coun for (size_t i = 0; i < count; i++) { const T *offsetInput = reinterpret_cast<const T*>(input + (stride * i)); - float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount; + float *offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount; - for (size_t j = 0; j < componentCount; j++) + for (size_t j = 0; j < inputComponentCount; j++) { if (normalized) { @@ -86,6 +166,15 @@ inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t coun offsetOutput[j] = static_cast<float>(offsetInput[j]); } } + + // This would require special padding. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp index 90a879e170..2f81d6d608 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp @@ -7,12 +7,14 @@ // formatutils11.cpp: Queries for GL image formats and their translations to D3D11 // formats. -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/generatemip.h" -#include "libGLESv2/renderer/loadimage.h" -#include "libGLESv2/renderer/copyimage.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/copyvertex.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/d3d/copyimage.h" +#include "libANGLE/renderer/d3d/generatemip.h" +#include "libANGLE/renderer/d3d/loadimage.h" +#include "libANGLE/renderer/d3d/d3d11/copyvertex.h" namespace rx { @@ -127,6 +129,90 @@ static D3D11FastCopyMap BuildFastCopyMap() return map; } +struct DXGIColorFormatInfo +{ + size_t redBits; + size_t greenBits; + size_t blueBits; + + size_t luminanceBits; + + size_t alphaBits; + size_t sharedBits; +}; + +typedef std::map<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoMap; +typedef std::pair<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoPair; + +static inline void InsertDXGIColorFormatInfo(ColorFormatInfoMap *map, DXGI_FORMAT format, size_t redBits, size_t greenBits, + size_t blueBits, size_t alphaBits, size_t sharedBits) +{ + DXGIColorFormatInfo info; + info.redBits = redBits; + info.greenBits = greenBits; + info.blueBits = blueBits; + info.alphaBits = alphaBits; + info.sharedBits = sharedBits; + + map->insert(std::make_pair(format, info)); +} + +static ColorFormatInfoMap BuildColorFormatInfoMap() +{ + ColorFormatInfoMap map; + + // | DXGI format | R | G | B | A | S | + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_A8_UNORM, 0, 0, 0, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UNORM, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UNORM, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 8, 8, 8, 8, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SNORM, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SNORM, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UINT, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_UINT, 16, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_UINT, 32, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UINT, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_UINT, 16, 16, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_UINT, 32, 32, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_UINT, 32, 32, 32, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UINT, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_UINT, 16, 16, 16, 16, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_UINT, 32, 32, 32, 32, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SINT, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_SINT, 16, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_SINT, 32, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SINT, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_SINT, 16, 16, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_SINT, 32, 32, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_SINT, 32, 32, 32, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SINT, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_SINT, 16, 16, 16, 16, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_SINT, 32, 32, 32, 32, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UINT, 10, 10, 10, 2, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_FLOAT, 16, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_FLOAT, 16, 16, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_FLOAT, 32, 32, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_FLOAT, 32, 32, 32, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, 9, 9, 0, 5); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R11G11B10_FLOAT, 11, 11, 10, 0, 0); + + return map; +} + struct DXGIDepthStencilInfo { unsigned int depthBits; @@ -179,6 +265,11 @@ DXGIFormat::DXGIFormat() : pixelBytes(0), blockWidth(0), blockHeight(0), + redBits(0), + greenBits(0), + blueBits(0), + alphaBits(0), + sharedBits(0), depthBits(0), depthOffset(0), stencilBits(0), @@ -205,21 +296,27 @@ void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelB info.blockWidth = blockWidth; info.blockHeight = blockHeight; + static const ColorFormatInfoMap colorInfoMap = BuildColorFormatInfoMap(); + ColorFormatInfoMap::const_iterator colorInfoIter = colorInfoMap.find(dxgiFormat); + if (colorInfoIter != colorInfoMap.end()) + { + const DXGIColorFormatInfo &colorInfo = colorInfoIter->second; + info.redBits = colorInfo.redBits; + info.greenBits = colorInfo.greenBits; + info.blueBits = colorInfo.blueBits; + info.alphaBits = colorInfo.alphaBits; + info.sharedBits = colorInfo.sharedBits; + } + static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap(); DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat); if (dsInfoIter != dsInfoMap.end()) { - info.depthBits = dsInfoIter->second.depthBits; - info.depthOffset = dsInfoIter->second.depthOffset; - info.stencilBits = dsInfoIter->second.stencilBits; - info.stencilOffset = dsInfoIter->second.stencilOffset; - } - else - { - info.depthBits = 0; - info.depthOffset = 0; - info.stencilBits = 0; - info.stencilOffset = 0; + const DXGIDepthStencilInfo &dsInfo = dsInfoIter->second; + info.depthBits = dsInfo.depthBits; + info.depthOffset = dsInfo.depthOffset; + info.stencilBits = dsInfo.stencilBits; + info.stencilOffset = dsInfo.stencilOffset; } static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); @@ -452,7 +549,28 @@ static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internal (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc)); } -D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() +D3D11LoadFunctionMap BuildD3D11_FL9_3_LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // From GL_EXT_texture_storage. Also used by GL_ALPHA8 + // On feature level 9_3, A8_UNORM doesn't support mipmaps, so we must use RGBA8 instead + InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8); + + return map; +} + +D3D11LoadFunctionMap BuildD3D11_FL10_0Plus_LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // From GL_EXT_texture_storage. Also used by GL_ALPHA8 + InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1>); + + return map; +} + +D3D11LoadFunctionMap BuildBaseD3D11LoadFunctionMap() { D3D11LoadFunctionMap map; @@ -557,7 +675,7 @@ D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); // From GL_EXT_texture_storage - InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8 ); + // GL_ALPHA8_EXT GL_UNSIGNED_BYTE is in the feature-level-specific load function maps, due to differences between 9_3 and 10_0+ InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); @@ -627,8 +745,8 @@ TextureFormat::TextureFormat() { } -static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +static inline void InsertD3D11FormatInfoBase(D3D11ES3FormatMap *formatMap, const D3D11LoadFunctionMap &flLoadFunctions, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) { TextureFormat info; info.texFormat = texFormat; @@ -712,8 +830,8 @@ static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internal InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat); info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL; - // Gather all the load functions for this internal format - static const D3D11LoadFunctionMap loadFunctions = BuildD3D11LoadFunctionMap(); + // Gather all the load functions for this internal format from the base list + static const D3D11LoadFunctionMap loadFunctions = BuildBaseD3D11LoadFunctionMap(); D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat); if (loadFunctionIter != loadFunctions.end()) { @@ -726,7 +844,57 @@ static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internal } } - map->insert(std::make_pair(internalFormat, info)); + // Gather load functions for this internal format from the feature-level-specific list + D3D11LoadFunctionMap::const_iterator flLoadFunctionIter = flLoadFunctions.find(internalFormat); + if (flLoadFunctionIter != flLoadFunctions.end()) + { + const std::vector<TypeLoadFunctionPair> &flLoadFunctionVector = flLoadFunctionIter->second; + for (size_t i = 0; i < flLoadFunctionVector.size(); i++) + { + GLenum type = flLoadFunctionVector[i].first; + LoadImageFunction function = flLoadFunctionVector[i].second; + info.loadFunctions.insert(std::make_pair(type, function)); + } + } + + formatMap->insert(std::make_pair(internalFormat, info)); +} + +static inline void InsertD3D11_FL9_3_FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +{ + static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL9_3_LoadFunctionMap(); + InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat); +} + +static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +{ + static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL10_0Plus_LoadFunctionMap(); + InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat); +} + +static D3D11ES3FormatMap BuildD3D11_FL9_3FormatOverrideMap() +{ + // D3D11 Feature Level 9_3 doesn't support as many texture formats as Feature Level 10_0+. + // In particular, it doesn't support: + // - mipmaps on DXGI_FORMAT_A8_NORM + // - *_TYPELESS formats + // - DXGI_FORMAT_D32_FLOAT_S8X24_UINT or DXGI_FORMAT_D32_FLOAT + + D3D11ES3FormatMap map; + + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format + InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + + return map; } static D3D11ES3FormatMap BuildD3D11FormatMap() @@ -795,7 +963,7 @@ static D3D11ES3FormatMap BuildD3D11FormatMap() // From GL_EXT_texture_storage // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); @@ -846,9 +1014,21 @@ static D3D11ES3FormatMap BuildD3D11FormatMap() return map; } -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel) { static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); + static const D3D11ES3FormatMap formatMapFL9_3Override = BuildD3D11_FL9_3FormatOverrideMap(); + + if (featureLevel == D3D_FEATURE_LEVEL_9_3) + { + // First see if the internalFormat has a special map for FL9_3 + D3D11ES3FormatMap::const_iterator fl9_3Iter = formatMapFL9_3Override.find(internalFormat); + if (fl9_3Iter != formatMapFL9_3Override.end()) + { + return fl9_3Iter->second; + } + } + D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); if (iter != formatMap.end()) { @@ -897,6 +1077,68 @@ static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inp map->insert(D3D11VertexFormatPair(inputFormat, info)); } +static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap() +{ + // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature Level 10_0+. + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx + + D3D11VertexFormatInfoMap map; + + // GL_BYTE -- unnormalized + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<1, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<2, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<3, 4>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<4, 4>); + + // GL_BYTE -- normalized + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<1, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<2, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<3, 4>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<4, 4>); + + // GL_UNSIGNED_BYTE -- unnormalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 1, 4, 1>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 2, 4, 1>); + // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format table. + + // GL_UNSIGNED_BYTE -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>); + // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. + + // GL_SHORT -- unnormalized + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 1, 2, 0>); + // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table. + + // GL_SHORT -- normalized + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 1, 2, 0>); + // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table. + + // GL_UNSIGNED_SHORT -- unnormalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, false>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, false>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, false>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, false>); + + // GL_UNSIGNED_SHORT -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, true>); + + // GL_FIXED + // TODO: Add test to verify that this works correctly. + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<1, 2>); + // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table. + + // GL_FLOAT + // TODO: Add test to verify that this works correctly. + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 2, 0>); + // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table. + + return map; +} + static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() { D3D11VertexFormatInfoMap map; @@ -908,94 +1150,94 @@ static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() // // GL_BYTE -- un-normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 0>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 0>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 1>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 0>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>); // GL_BYTE -- normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 0>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 0>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, INT8_MAX>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 0>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 4, 0>); // GL_UNSIGNED_BYTE -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 1>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>); // GL_UNSIGNED_BYTE -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, UINT8_MAX>); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 4, 0>); // GL_SHORT -- un-normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 0>); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 0>); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 1>); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 0>); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>); // GL_SHORT -- normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 0>); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 0>); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, INT16_MAX>); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 0>); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 4, 0>); // GL_UNSIGNED_SHORT -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 1>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>); // GL_UNSIGNED_SHORT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, UINT16_MAX>); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 4, 0>); // GL_INT -- un-normalized - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 0>); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 0>); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 0>); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 0>); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>); // GL_INT -- normalized - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, true>); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, true>); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, true>); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, true>); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, 1, true>); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, 2, true>); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, 3, true>); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, 4, true>); // GL_UNSIGNED_INT -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 0>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 3, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 4, 0>); // GL_UNSIGNED_INT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, 1, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, 2, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, 3, true>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, 4, true>); // GL_FIXED - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>); // GL_HALF_FLOAT - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 0>); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 0>); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, gl::Float16One>); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 0>); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 4, 0>); // GL_FLOAT - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 0>); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 0>); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 0>); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 0>); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 1, 0>); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 2, 0>); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 3, 0>); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 4, 0>); // GL_INT_2_10_10_10_REV AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>); @@ -1003,60 +1245,71 @@ static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() // GL_UNSIGNED_INT_2_10_10_10_REV AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 0>); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 1, 0>); // // Integer Formats // // GL_BYTE - AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 0>); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 0>); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 1>); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 0>); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>); // GL_UNSIGNED_BYTE - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 1>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>); // GL_SHORT - AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 0>); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 0>); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 1>); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 0>); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>); // GL_UNSIGNED_SHORT - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 1>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>); // GL_INT - AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 0>); - AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 0>); - AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 0>); - AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 0>); + AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>); + AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>); + AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>); // GL_UNSIGNED_INT - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 0>); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 2, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 3, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 4, 0>); // GL_INT_2_10_10_10_REV AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>); // GL_UNSIGNED_INT_2_10_10_10_REV - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 0>); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>); return map; } -const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat) +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel) { static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); + static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = BuildD3D11_FL9_3VertexFormatInfoOverrideMap(); + + if (featureLevel == D3D_FEATURE_LEVEL_9_3) + { + // First see if the format has a special mapping for FL9_3 + D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMapFL9_3Override.find(vertexFormat); + if (iter != vertexFormatMapFL9_3Override.end()) + { + return iter->second; + } + } D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); if (iter != vertexFormatMap.end()) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h index ea11aaa74c..33fe29dc39 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h @@ -7,10 +7,13 @@ // formatutils11.h: Queries for GL image formats and their translations to D3D11 // formats. -#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_ -#define LIBGLESV2_RENDERER_FORMATUTILS11_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ -#include "libGLESv2/formatutils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/angletypes.h" + +#include "common/platform.h" #include <map> @@ -30,6 +33,12 @@ struct DXGIFormat GLuint blockWidth; GLuint blockHeight; + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + GLuint alphaBits; + GLuint sharedBits; + GLuint depthBits; GLuint depthOffset; GLuint stencilBits; @@ -65,7 +74,7 @@ struct TextureFormat typedef std::map<GLenum, LoadImageFunction> LoadFunctionMap; LoadFunctionMap loadFunctions; }; -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel); struct VertexFormat { @@ -75,10 +84,10 @@ struct VertexFormat DXGI_FORMAT nativeFormat; VertexCopyFunction copyFunction; }; -const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat); +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel); } } -#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp index 121aa3bbad..63085f497f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -7,12 +7,14 @@ // renderer11_utils.cpp: Conversion functions and other utility routines // specific to the D3D11 renderer. -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Program.h" +#include "libANGLE/Framebuffer.h" #include "common/debug.h" @@ -96,6 +98,9 @@ #ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT # define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 #endif +#if defined(ANGLE_MINGW32_COMPAT) +static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 }; +#endif namespace rx { @@ -305,25 +310,47 @@ D3D11_QUERY ConvertQueryType(GLenum queryType) namespace d3d11_gl { -static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device) +GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 3; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 2; + + default: UNREACHABLE(); return 0; + } +} + +static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device) { gl::TextureCaps textureCaps; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, device->GetFeatureLevel()); UINT formatSupport; if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport))) { - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0) { textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); } else { - textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) && - ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) && - ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0); + UINT formatSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; + if (maxClientVersion > 2) + { + formatSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + } + textureCaps.texturable = ((formatSupport & formatSupportMask) == formatSupportMask); } } @@ -355,7 +382,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -365,7 +392,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return true; // Provided that mipmaps & wrap modes are not used + case D3D_FEATURE_LEVEL_9_1: return false; default: UNREACHABLE(); return false; } @@ -375,7 +402,7 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; @@ -397,7 +424,7 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -419,7 +446,7 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -439,12 +466,18 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_10_0: return true; + + // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be instanced. + // D3D9 has a similar restriction, where stream 0 must not be instanced. + // This restriction can be worked around by remapping any non-instanced slot to slot 0. + // This works because HLSL uses shader semantics to match the vertex inputs to the elements in the input layout, rather than the slots. + // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 doesn't support OpenGL ES 3.0 case D3D_FEATURE_LEVEL_9_3: return true; case D3D_FEATURE_LEVEL_9_2: @@ -454,6 +487,44 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) } } +static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) { // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model @@ -464,7 +535,7 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -478,13 +549,32 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) } } +static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) { // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; @@ -504,7 +594,7 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; @@ -524,7 +614,7 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; @@ -544,7 +634,7 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; @@ -564,7 +654,7 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; @@ -584,7 +674,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; @@ -592,7 +682,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; - // No constants for D3D9 viewport size limits, use the maximum texture sizes + // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum texture sizes case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; @@ -605,12 +695,12 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) { // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's // returned from glGetInteger - META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); + static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -629,12 +719,12 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) { // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's // returned from glGetInteger - META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); + static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -653,7 +743,7 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; @@ -675,7 +765,7 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; @@ -702,7 +792,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); @@ -710,7 +800,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); - // Uniform blocks not supported in D3D9 feature levels + // Uniform blocks not supported on D3D11 Feature Level 9 case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: return 0; @@ -719,30 +809,55 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) } } -static size_t GetReservedVertexOutputVectors() +static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) { - // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize - return 4; + // According to The OpenGL ES Shading Language specifications + // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21) + // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord) + // which are statically used in the shader should be included in the variable packing algorithm. + // Therefore, we should not reserve output vectors for them. + + switch (featureLevel) + { + // We must reserve one output vector for dx_Position. + // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+, + // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved. +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 2; + + // Just reserve dx_Position on Feature Level 9, since we don't ever need to output gl_Position. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 1; + + default: UNREACHABLE(); return 0; + } + + return 1; } static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) { - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); + static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, "Unexpected D3D11 constant value."); switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - // Use D3D9 SM3 and SM2 limits - case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors(); + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel); default: UNREACHABLE(); return 0; } @@ -752,7 +867,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; @@ -760,7 +875,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; - // Vertex textures not supported in D3D9 feature levels according to + // Vertex textures not supported on D3D11 Feature Level 9 according to // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources case D3D_FEATURE_LEVEL_9_3: @@ -776,7 +891,7 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; @@ -803,7 +918,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); @@ -811,7 +926,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); - // Uniform blocks not supported in D3D9 feature levels + // Uniform blocks not supported on D3D11 Feature Level 9 case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: return 0; @@ -824,18 +939,18 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - // Use D3D9 SM3 and SM2 limits - case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors(); + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: return 8 - GetReservedVertexOutputVectors(featureLevel); case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(); + case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel); default: UNREACHABLE(); return 0; } @@ -845,7 +960,7 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; @@ -866,7 +981,7 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; @@ -887,7 +1002,7 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; @@ -912,7 +1027,7 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; @@ -933,7 +1048,7 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; @@ -953,7 +1068,7 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -973,7 +1088,7 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature { switch (featureLevel) { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) +#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / @@ -992,13 +1107,15 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature } } -void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) { + D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); + GLuint maxSamples = 0; const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device); + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device); textureCapsMap->insert(*internalFormat, textureCaps); maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); @@ -1009,8 +1126,6 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text } } - D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); - // GL core feature limits caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); @@ -1048,6 +1163,21 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text // Program and shader binary formats (no supported shader binary formats) caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + + // 32-bit integers are natively supported + caps->vertexHighpInt.setTwosComplementInt(32); + caps->vertexMediumpInt.setTwosComplementInt(32); + caps->vertexLowpInt.setTwosComplementInt(32); + caps->fragmentHighpInt.setTwosComplementInt(32); + caps->fragmentMediumpInt.setTwosComplementInt(32); + caps->fragmentLowpInt.setTwosComplementInt(32); + // We do not wait for server fence objects internally, so report a max timeout of zero. caps->maxServerWaitTimeout = 0; @@ -1074,6 +1204,24 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text // Setting a large alignment forces uniform buffers to bind with zero offset caps->uniformBufferOffsetAlignment = static_cast<GLuint>(std::numeric_limits<GLint>::max()); +#if defined(ANGLE_ENABLE_D3D11_1) + ID3D11DeviceContext1 *deviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(deviceContext); + + if (deviceContext1) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + + if (d3d11Options.ConstantBufferOffsetting) + { + // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each. + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx + caps->uniformBufferOffsetAlignment = 256; + } + + SafeRelease(deviceContext1); + } +#endif caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; caps->maxCombinedVertexUniformComponents = (static_cast<GLint64>(caps->maxVertexUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) + @@ -1109,13 +1257,13 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text extensions->timerQuery = false; // Unimplemented extensions->robustness = true; extensions->blendMinMax = true; - extensions->framebufferBlit = true; - extensions->framebufferMultisample = true; + extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel); + extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel); extensions->maxSamples = maxSamples; extensions->instancedArrays = GetInstancingSupport(featureLevel); extensions->packReverseRowOrder = true; extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); - extensions->shaderTextureLOD = true; + extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); extensions->fragDepth = true; extensions->textureUsage = true; // This could be false since it has no effect in D3D11 extensions->translatedShaderSource = true; @@ -1145,11 +1293,11 @@ void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsi *levelOffset = upsampleCount; } -void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, +void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth, GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, std::vector< std::vector<BYTE> > *outData) { - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel); ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); @@ -1196,16 +1344,16 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { -#if defined(_DEBUG) && !defined(__MINGW32__) +#if defined(_DEBUG) return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); #else return S_OK; #endif } -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT) +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT) { - RenderTarget *renderTarget = NULL; + RenderTargetD3D *renderTarget = NULL; gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); if (error.isError()) { @@ -1215,11 +1363,13 @@ gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, Rende return gl::Error(GL_NO_ERROR); } -Workarounds GenerateWorkarounds() +Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) { Workarounds workarounds; workarounds.mrtPerfWorkaround = true; workarounds.setDataFasterThanImageUpload = true; + workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3); + workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3); return workarounds; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h index 9df9c95763..207e6b5404 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -7,12 +7,12 @@ // renderer11_utils.h: Conversion functions and other utility routines // specific to the D3D11 renderer. -#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" #include <vector> @@ -50,7 +50,8 @@ D3D11_QUERY ConvertQueryType(GLenum queryType); namespace d3d11_gl { -void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); +GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); } @@ -59,7 +60,7 @@ namespace d3d11 void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); -void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, +void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth, GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, std::vector< std::vector<BYTE> > *outData); @@ -178,12 +179,12 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu context->Unmap(constantBuffer, 0); } -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); -Workarounds GenerateWorkarounds(); +Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); } } -#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl index 20e6623a30..c43734f6a3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl @@ -26,6 +26,7 @@ cbuffer BufferCopyParams : register(b0) float2 PositionScale; int2 TexLocationOffset; int2 TexLocationScale; + uint FirstSlice; } void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) @@ -42,7 +43,7 @@ void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f); outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col; - outVertex.slice = slice; + outVertex.slice = FirstSlice + slice; } void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl index b4cf38076e..2b3e1ebe4c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -13,12 +13,10 @@ struct PS_OutputFloat float4 color1 : SV_TARGET1; float4 color2 : SV_TARGET2; float4 color3 : SV_TARGET3; -#if SM4 float4 color4 : SV_TARGET4; float4 color5 : SV_TARGET5; float4 color6 : SV_TARGET6; float4 color7 : SV_TARGET7; -#endif }; PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) @@ -28,15 +26,30 @@ PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inCol outColor.color1 = inColor; outColor.color2 = inColor; outColor.color3 = inColor; -#if SM4 outColor.color4 = inColor; outColor.color5 = inColor; outColor.color6 = inColor; outColor.color7 = inColor; -#endif return outColor; } +struct PS_OutputFloat_FL9 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; +}; + +PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat_FL9 outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + return outColor; +} void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl index 8671c39fb7..8671c39fb7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl index c23c9032ec..c23c9032ec 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl index 505e222137..505e222137 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp index 46082a2e28..9d8f0bb96c 100644 --- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp @@ -6,17 +6,14 @@ // NativeWindow.cpp: Handler for managing HWND native window types. -#include "common/NativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/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) +NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window) { } @@ -35,7 +32,12 @@ bool NativeWindow::isIconic() return IsIconic(mWindow) == TRUE; } -HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory, +bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) +{ + return IsWindow(window) == TRUE; +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain** swapChain) { diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp index 9b65c15625..350526c867 100644 --- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp @@ -6,25 +6,22 @@ // CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. -#include <algorithm> -#include "common/winrt/CoreWindowNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/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) +bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { + mOrientationChangedEventToken.value = 0; ComPtr<IPropertySet> props = propertySet; ComPtr<IInspectable> win = window; - ComPtr<IInspectable> displayInformation = display; SIZE swapChainSize = {}; bool swapChainSizeSpecified = false; HRESULT result = S_OK; @@ -51,29 +48,6 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDis 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 @@ -87,14 +61,17 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDis } 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 }; - } + result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect); + } + } + + if (SUCCEEDED(result)) + { + ComPtr<ABI::Windows::Graphics::Display::IDisplayInformationStatics> displayInformation; + result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation); + if (SUCCEEDED(result)) + { + result = displayInformation->GetForCurrentView(&mDisplayInformation); } } @@ -110,8 +87,21 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDis bool CoreWindowNativeWindow::registerForSizeChangeEvents() { - HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(), - &mSizeChangedEventToken); + ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler; + HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + if (SUCCEEDED(result)) + { + result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + ComPtr<IDisplayOrientationEventHandler> orientationChangedHandler; + result = sizeChangedHandler.As(&orientationChangedHandler); + if (SUCCEEDED(result)) + { + result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken); + } +#endif if (SUCCEEDED(result)) { @@ -127,7 +117,14 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents() { (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); } +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + if (mDisplayInformation) + { + (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken); + } +#endif mSizeChangedEventToken.value = 0; + mOrientationChangedEventToken.value = 0; } HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) @@ -156,7 +153,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor if (SUCCEEDED(result)) { -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected +#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain. // 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. @@ -182,19 +179,36 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor return result; } -// Basically, this shouldn't be used on Phone -HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) +HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize) { - ABI::Windows::Foundation::Size size; - if (SUCCEEDED(e->get_Size(&size))) + ABI::Windows::Foundation::Rect bounds; + HRESULT result = coreWindow->get_Bounds(&bounds); + if (SUCCEEDED(result)) { - SIZE windowSizeInPixels = { - std::floor(size.Width * mScaleFactor + 0.5), - std::floor(size.Height * mScaleFactor + 0.5) - }; - setNewClientSize(windowSizeInPixels); + *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; } - return S_OK; + return result; +} + +static float GetLogicalDpi() +{ + ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties; + float dpi = 96.0f; + + if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf()))) + { + if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi))) + { + return dpi; + } + } + return dpi; +} + +long ConvertDipsToPixels(float dips) +{ + static const float dipsPerInch = 96.0f; + return lround((dips * GetLogicalDpi() / dipsPerInch)); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h new file mode 100644 index 0000000000..59df9d5a6c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h @@ -0,0 +1,110 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" + +#include <memory> +#include <windows.graphics.display.h> + +typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; +typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler; + +namespace rx +{ +long ConvertDipsToPixels(float dips); + +class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow> +{ + public: + ~CoreWindowNativeWindow(); + + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + + private: + ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow; + ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; + ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation; + EventRegistrationToken mOrientationChangedEventToken; +}; + +[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] +class CoreWindowSizeChangedHandler : + public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler> +{ + public: + CoreWindowSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // IWindowSizeChangedEventHandler + IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); + if (host) + { + ABI::Windows::Foundation::Size windowSize; + if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) + { + SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) }; + host->setNewClientSize(windowSizeInPixels); + } + } + + return S_OK; + } + + IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *) + { +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + NativeWindow::RotationFlags flags = NativeWindow::RotateNone; + ABI::Windows::Graphics::Display::DisplayOrientations orientation; + if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation))) + { + switch (orientation) + { + case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape: + flags = NativeWindow::RotateLeft; + break; + case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped: + flags = NativeWindow::RotateRight; + break; + default: + break; + } + } + std::shared_ptr<InspectableNativeWindow> host = mHost.lock(); + if (host) + { + host->setRotationFlags(flags); + } +#endif + return S_OK; + } + + private: + std::weak_ptr<InspectableNativeWindow> mHost; +}; + +HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize); +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp index 0589f6dce5..2bf48c5d94 100644 --- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp @@ -6,14 +6,14 @@ // InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. -#include "common/winrt/CoreWindowNativeWindow.h" -#include "common/winrt/SwapChainPanelNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) - : mWindow(window), mDisplay(display) +NativeWindow::NativeWindow(EGLNativeWindowType window) { + mWindow = window; } bool NativeWindow::initialize() @@ -40,7 +40,7 @@ bool NativeWindow::initialize() mImpl = std::make_shared<CoreWindowNativeWindow>(); if (mImpl) { - return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + return mImpl->initialize(mWindow, propertySet.Get()); } } else if (IsSwapChainPanel(mWindow, &swapChainPanel)) @@ -48,7 +48,7 @@ bool NativeWindow::initialize() mImpl = std::make_shared<SwapChainPanelNativeWindow>(); if (mImpl) { - return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + return mImpl->initialize(mWindow, propertySet.Get()); } } else @@ -69,11 +69,28 @@ bool NativeWindow::getClientRect(RECT *rect) return false; } +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +NativeWindow::RotationFlags NativeWindow::rotationFlags() const +{ + if (mImpl) + { + return mImpl->rotationFlags(); + } + + return NativeWindow::RotateNone; +} +#endif + bool NativeWindow::isIconic() { return false; } +bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) +{ + return IsValidEGLNativeWindowType(window); +} + HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) { if (mImpl) diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h index 402941a788..575bdf8a58 100644 --- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h @@ -7,11 +7,13 @@ // InspectableNativeWindow.h: Host specific implementation interface for // managing IInspectable native window types. -#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ -#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" #include "common/platform.h" -#include "common/NativeWindow.h" + #include "angle_windowsstore.h" #include <windows.ui.xaml.h> @@ -33,13 +35,13 @@ class InspectableNativeWindow mClientRectChanged(false), mClientRect({0,0,0,0}), mNewClientRect({0,0,0,0}), - mScaleFactor(1.0) + mRotationFlags(NativeWindow::RotateNone) { mSizeChangedEventToken.value = 0; } virtual ~InspectableNativeWindow(){} - virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; + virtual bool initialize(EGLNativeWindowType window, 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; @@ -50,7 +52,6 @@ class InspectableNativeWindow if (mClientRectChanged && mSupportsSwapChainResize) { mClientRect = mNewClientRect; - mClientRectChanged = false; } *rect = mClientRect; @@ -72,20 +73,33 @@ class InspectableNativeWindow } } + NativeWindow::RotationFlags rotationFlags() const + { + return mRotationFlags; + } + + void setRotationFlags(NativeWindow::RotationFlags flags) + { + mRotationFlags = flags; + } + protected: bool mSupportsSwapChainResize; bool mRequiresSwapChainScaling; RECT mClientRect; RECT mNewClientRect; bool mClientRectChanged; - DOUBLE mScaleFactor; + NativeWindow::RotationFlags mRotationFlags; EventRegistrationToken mSizeChangedEventToken; }; +bool IsValidEGLNativeWindowType(EGLNativeWindowType window); 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_ + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp index 268dfbd8f0..53899dbb30 100644 --- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp @@ -6,9 +6,11 @@ // SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. -#include "common/winrt/SwapChainPanelNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + #include <algorithm> #include <math.h> + using namespace ABI::Windows::Foundation::Collections; namespace rx @@ -18,7 +20,7 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() unregisterForSizeChangeEvents(); } -bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { ComPtr<IPropertySet> props = propertySet; ComPtr<IInspectable> win = window; diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h index 5bbf274e64..caf327d913 100644 --- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h @@ -6,10 +6,10 @@ // SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. -#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ -#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ -#include "common/winrt/InspectableNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" namespace rx { @@ -18,7 +18,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e public: ~SwapChainPanelNativeWindow(); - bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); bool registerForSizeChangeEvents(); void unregisterForSizeChangeEvents(); HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); @@ -76,4 +76,4 @@ class SwapChainPanelSizeChangedHandler : HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize); } -#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp index 2ca7a9cf8a..a0bc2960b7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp @@ -6,41 +6,41 @@ // Blit9.cpp: Surface copy utility class. -#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d9/Blit9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" namespace { // Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" const BYTE* const g_shaderCode[] = { - g_vs20_VS_standard, - g_vs20_VS_flipy, - g_ps20_PS_passthrough, - g_ps20_PS_luminance, - g_ps20_PS_componentmask + g_vs20_standardvs, + g_vs20_flipyvs, + g_ps20_passthroughps, + g_ps20_luminanceps, + g_ps20_componentmaskps }; const size_t g_shaderSize[] = { - sizeof(g_vs20_VS_standard), - sizeof(g_vs20_VS_flipy), - sizeof(g_ps20_PS_passthrough), - sizeof(g_ps20_PS_luminance), - sizeof(g_ps20_PS_componentmask) + sizeof(g_vs20_standardvs), + sizeof(g_vs20_flipyvs), + sizeof(g_ps20_passthroughps), + sizeof(g_ps20_luminanceps), + sizeof(g_ps20_componentmaskps) }; } @@ -217,7 +217,7 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - setViewport(getSurfaceRect(dest), 0, 0); + setViewport(getSurfaceRect(dest), gl::Offset(0, 0, 0)); render(); @@ -228,7 +228,7 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) return gl::Error(GL_NO_ERROR); } -gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) +gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) { gl::Error error = initialize(); if (error.isError()) @@ -259,7 +259,7 @@ gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GL } ASSERT(destSurface); - gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); SafeRelease(destSurface); SafeRelease(source); @@ -267,7 +267,7 @@ gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GL return result; } -gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) +gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) { gl::Error error = initialize(); if (error.isError()) @@ -298,7 +298,7 @@ gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, } ASSERT(destSurface); - gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); SafeRelease(destSurface); SafeRelease(source); @@ -306,7 +306,7 @@ gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, return result; } -gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) { ASSERT(source != NULL && dest != NULL); @@ -320,7 +320,7 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect { - RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; + RECT destRect = { destOffset.x, destOffset.y, destOffset.x + (sourceRect.right - sourceRect.left), destOffset.y + (sourceRect.bottom - sourceRect.top)}; HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); if (FAILED(result)) @@ -333,11 +333,11 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum } else { - return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); + return formatConvert(source, sourceRect, destFormat, destOffset, dest); } } -gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) { gl::Error error = initialize(); if (error.isError()) @@ -359,7 +359,7 @@ gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect device->SetTexture(0, texture); device->SetRenderTarget(0, dest); - setViewport(sourceRect, xoffset, yoffset); + setViewport(sourceRect, destOffset); setCommonBlitState(); @@ -548,13 +548,13 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so return gl::Error(GL_NO_ERROR); } -void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) +void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset) { IDirect3DDevice9 *device = mRenderer->getDevice(); D3DVIEWPORT9 vp; - vp.X = xoffset; - vp.Y = yoffset; + vp.X = offset.x; + vp.Y = offset.y; vp.Width = sourceRect.right - sourceRect.left; vp.Height = sourceRect.bottom - sourceRect.top; vp.MinZ = 0.0f; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h index 5c7a76ce05..586abd2580 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h @@ -6,17 +6,18 @@ // Blit9.cpp: Surface copy utility class. -#ifndef LIBGLESV2_BLIT9_H_ -#define LIBGLESV2_BLIT9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ #include "common/angleutils.h" -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include <GLES2/gl2.h> namespace gl { class Framebuffer; +struct Offset; } namespace rx @@ -24,7 +25,7 @@ namespace rx class Renderer9; class TextureStorage; -class Blit9 +class Blit9 : angle::NonCopyable { public: explicit Blit9(Renderer9 *renderer); @@ -34,13 +35,13 @@ class Blit9 // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - gl::Error copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - gl::Error copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); + gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level); + gl::Error copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. - gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest); // 2x2 box filter sample from source to dest. // Requires that source is RGB(A) and dest has the same format as source. @@ -55,9 +56,9 @@ class Blit9 gl::Error setFormatConvertShaders(GLenum destFormat); - gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest); gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture); - void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); + void setViewport(const RECT &sourceRect, const gl::Offset &offset); void setCommonBlitState(); RECT getSurfaceRect(IDirect3DSurface9 *surface) const; @@ -89,9 +90,8 @@ class Blit9 IDirect3DStateBlock9 *mSavedStateBlock; IDirect3DSurface9 *mSavedRenderTarget; IDirect3DSurface9 *mSavedDepthStencil; - - DISALLOW_COPY_AND_ASSIGN(Blit9); }; + } -#endif // LIBGLESV2_BLIT9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp index 430fe81e50..b051c81aa8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -6,15 +6,14 @@ // Buffer9.cpp Defines the Buffer9 class. -#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" namespace rx { Buffer9::Buffer9(Renderer9 *renderer) - : BufferD3D(), + : BufferD3D(renderer), mRenderer(renderer), mSize(0) {} @@ -114,9 +113,4 @@ void Buffer9::markTransformFeedbackUsage() UNREACHABLE(); } -RendererD3D *Buffer9::getRenderer() -{ - return mRenderer; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h index c80b009738..c1984146fc 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h @@ -6,12 +6,12 @@ // Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. -#ifndef LIBGLESV2_RENDERER_BUFFER9_H_ -#define LIBGLESV2_RENDERER_BUFFER9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "libGLESv2/angletypes.h" +#include "common/MemoryBuffer.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" namespace rx { @@ -28,7 +28,6 @@ class Buffer9 : public BufferD3D // BufferD3D implementation virtual size_t getSize() const { return mSize; } virtual bool supportsDirectBinding() const { return false; } - RendererD3D *getRenderer() override; // BufferImpl implementation virtual gl::Error setData(const void* data, size_t size, GLenum usage); @@ -40,8 +39,6 @@ class Buffer9 : public BufferD3D virtual void markTransformFeedbackUsage(); private: - DISALLOW_COPY_AND_ASSIGN(Buffer9); - Renderer9 *mRenderer; MemoryBuffer mMemory; size_t mSize; @@ -49,4 +46,4 @@ class Buffer9 : public BufferD3D } -#endif // LIBGLESV2_RENDERER_BUFFER9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp new file mode 100644 index 0000000000..09b229bcb1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp @@ -0,0 +1,36 @@ +// +// Copyright 2015 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. +// +// DebugAnnotator9.h: D3D9 helpers for adding trace annotations. +// + +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" + +#include "common/platform.h" + +namespace rx +{ + +void DebugAnnotator9::beginEvent(const std::wstring &eventName) +{ + D3DPERF_BeginEvent(0, eventName.c_str()); +} + +void DebugAnnotator9::endEvent() +{ + D3DPERF_EndEvent(); +} + +void DebugAnnotator9::setMarker(const std::wstring &markerName) +{ + D3DPERF_SetMarker(0, markerName.c_str()); +} + +bool DebugAnnotator9::getStatus() +{ + return !!D3DPERF_GetStatus(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h new file mode 100644 index 0000000000..02956f7183 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h @@ -0,0 +1,29 @@ +// +// Copyright 2015 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. +// +// DebugAnnotator9.h: D3D9 helpers for adding trace annotations. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ + +#include "common/debug.h" + +namespace rx +{ + +class DebugAnnotator9 : public gl::DebugAnnotator +{ + public: + DebugAnnotator9() {} + void beginEvent(const std::wstring &eventName) override; + void endEvent() override; + void setMarker(const std::wstring &markerName) override; + bool getStatus() override; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp index 66263fe110..27c265e28d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp @@ -6,10 +6,9 @@ // Fence9.cpp: Defines the rx::FenceNV9 class. -#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h index d7873d5264..4b86747396 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h @@ -6,10 +6,11 @@ // Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl. -#ifndef LIBGLESV2_RENDERER_FENCE9_H_ -#define LIBGLESV2_RENDERER_FENCE9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ -#include "libGLESv2/renderer/FenceImpl.h" +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" namespace rx { @@ -26,12 +27,10 @@ class FenceNV9 : public FenceNVImpl gl::Error finishFence(GLboolean *outFinished); private: - DISALLOW_COPY_AND_ASSIGN(FenceNV9); - Renderer9 *mRenderer; IDirect3DQuery9 *mQuery; }; } -#endif // LIBGLESV2_RENDERER_FENCE9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp new file mode 100644 index 0000000000..dbdfc6d6de --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -0,0 +1,422 @@ +// +// Copyright 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. +// + +// Framebuffer9.cpp: Implements the Framebuffer9 class. + +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" + +namespace rx +{ + +Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer) + : FramebufferD3D(data, renderer), + mRenderer(renderer) +{ + ASSERT(mRenderer != nullptr); +} + +Framebuffer9::~Framebuffer9() +{ +} + +gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams) +{ + const gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[0]; + const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment(); + + gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment); + if (error.isError()) + { + return error; + } + + float nearZ, farZ; + state.getDepthRange(&nearZ, &farZ); + mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true); + + mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled()); + + return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment); +} + +gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +{ + ASSERT(pack.pixelBuffer.get() == NULL); + + const gl::FramebufferAttachment *colorbuffer = mData.mColorAttachments[0]; + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); + + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + ASSERT(device); + + HRESULT result; + IDirect3DSurface9 *systemSurface = NULL; + bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() && + area.x == 0 && area.y == 0 && + static_cast<UINT>(area.width) == desc.Width && static_cast<UINT>(area.height) == desc.Height && + desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; + if (directToPixels) + { + // Use the pixels ptr as a shared handle to write directly into client's memory + result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels)); + if (FAILED(result)) + { + // Try again without the shared handle + directToPixels = false; + } + } + + if (!directToPixels) + { + result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, NULL); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); + } + } + + result = device->GetRenderTargetData(surface, systemSurface); + SafeRelease(surface); + + if (FAILED(result)) + { + SafeRelease(systemSurface); + + // It turns out that D3D will sometimes produce more error + // codes than those documented. + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else + { + UNREACHABLE(); + } + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); + } + + if (directToPixels) + { + SafeRelease(systemSurface); + return gl::Error(GL_NO_ERROR); + } + + RECT rect; + rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width)); + rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height)); + rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width)); + rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height)); + + D3DLOCKED_RECT lock; + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); + + if (FAILED(result)) + { + UNREACHABLE(); + SafeRelease(systemSurface); + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); + } + + uint8_t *source; + int inputPitch; + if (pack.reverseRowOrder) + { + source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + inputPitch = -lock.Pitch; + } + else + { + source = reinterpret_cast<uint8_t*>(lock.pBits); + inputPitch = lock.Pitch; + } + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); + if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) + { + // Direct copy possible + for (int y = 0; y < rect.bottom - rect.top; y++) + { + memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); + } + } + else + { + const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); + + GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); + + if (fastCopyFunc) + { + // Fast copy is possible through some special function + for (int y = 0; y < rect.bottom - rect.top; y++) + { + for (int x = 0; x < rect.right - rect.left; x++) + { + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + + fastCopyFunc(src, dest); + } + } + } + else + { + ColorReadFunction colorReadFunction = sourceD3DFormatInfo.colorReadFunction; + ColorWriteFunction colorWriteFunction = GetColorWriteFunction(format, type); + + uint8_t temp[sizeof(gl::ColorF)]; + for (int y = 0; y < rect.bottom - rect.top; y++) + { + for (int x = 0; x < rect.right - rect.left; x++) + { + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + colorReadFunction(src, temp); + colorWriteFunction(temp, dest); + } + } + } + } + + systemSurface->UnlockRect(); + SafeRelease(systemSurface); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) +{ + ASSERT(filter == GL_NEAREST); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + ASSERT(device); + + mRenderer->endScene(); + + if (blitRenderTarget) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0); + ASSERT(readBuffer); + + RenderTarget9 *readRenderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[0]; + ASSERT(drawBuffer); + + RenderTarget9 *drawRenderTarget = NULL; + error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readRenderTarget->getSurface(); + ASSERT(readSurface); + + IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface(); + ASSERT(drawSurface); + + gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + RECT srcRect; + srcRect.left = sourceArea.x; + srcRect.right = sourceArea.x + sourceArea.width; + srcRect.top = sourceArea.y; + srcRect.bottom = sourceArea.y + sourceArea.height; + + RECT dstRect; + dstRect.left = destArea.x; + dstRect.right = destArea.x + destArea.width; + dstRect.top = destArea.y; + dstRect.bottom = destArea.y + destArea.height; + + // Clip the rectangles to the scissor rectangle + if (scissor) + { + if (dstRect.left < scissor->x) + { + srcRect.left += (scissor->x - dstRect.left); + dstRect.left = scissor->x; + } + if (dstRect.top < scissor->y) + { + srcRect.top += (scissor->y - dstRect.top); + dstRect.top = scissor->y; + } + if (dstRect.right > scissor->x + scissor->width) + { + srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); + dstRect.right = scissor->x + scissor->width; + } + if (dstRect.bottom > scissor->y + scissor->height) + { + srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); + dstRect.bottom = scissor->y + scissor->height; + } + } + + // Clip the rectangles to the destination size + if (dstRect.left < 0) + { + srcRect.left += -dstRect.left; + dstRect.left = 0; + } + if (dstRect.right > dstSize.width) + { + srcRect.right -= (dstRect.right - dstSize.width); + dstRect.right = dstSize.width; + } + if (dstRect.top < 0) + { + srcRect.top += -dstRect.top; + dstRect.top = 0; + } + if (dstRect.bottom > dstSize.height) + { + srcRect.bottom -= (dstRect.bottom - dstSize.height); + dstRect.bottom = dstSize.height; + } + + // Clip the rectangles to the source size + if (srcRect.left < 0) + { + dstRect.left += -srcRect.left; + srcRect.left = 0; + } + if (srcRect.right > srcSize.width) + { + dstRect.right -= (srcRect.right - srcSize.width); + srcRect.right = srcSize.width; + } + if (srcRect.top < 0) + { + dstRect.top += -srcRect.top; + srcRect.top = 0; + } + if (srcRect.bottom > srcSize.height) + { + dstRect.bottom -= (srcRect.bottom - srcSize.height); + srcRect.bottom = srcSize.height; + } + + HRESULT result = device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + } + } + + if (blitDepth || blitStencil) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTarget9 *readDepthStencil = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(readDepthStencil); + + const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + ASSERT(drawBuffer); + + RenderTarget9 *drawDepthStencil = NULL; + error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(drawDepthStencil); + + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readDepthStencil->getSurface(); + ASSERT(readDepthStencil); + + IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); + ASSERT(drawDepthStencil); + + HRESULT result = device->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget9 *renderTarget9 = RenderTarget9::makeRenderTarget9(renderTarget); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat()); + return d3dFormatInfo.internalFormat; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h new file mode 100644 index 0000000000..292118e6db --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h @@ -0,0 +1,41 @@ +// +// Copyright 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. +// + +// Framebuffer9.h: Defines the Framebuffer9 class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ +class Renderer9; + +class Framebuffer9 : public FramebufferD3D +{ + public: + Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer); + virtual ~Framebuffer9(); + + private: + gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; + + gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, + const gl::PixelPackState &pack, uint8_t *pixels) const override; + + gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) override; + + GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + + Renderer9 *const mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp index 2a06d12942..d149f7a806 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -7,28 +7,30 @@ // Image9.cpp: Implements the rx::Image9 class, which acts as the interface to // the actual underlying surfaces of a Texture. -#include "libGLESv2/renderer/d3d/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" +#include "libANGLE/renderer/d3d/d3d9/Image9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Renderbuffer.h" #include "common/utilities.h" namespace rx { -Image9::Image9() +Image9::Image9(Renderer9 *renderer) { mSurface = NULL; mRenderer = NULL; mD3DPool = D3DPOOL_SYSTEMMEM; mD3DFormat = D3DFMT_UNKNOWN; + + mRenderer = renderer; } Image9::~Image9() @@ -92,7 +94,7 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 return gl::Error(GL_NO_ERROR); } -Image9 *Image9::makeImage9(Image *img) +Image9 *Image9::makeImage9(ImageD3D *img) { ASSERT(HAS_DYNAMIC_TYPE(Image9*, img)); return static_cast<Image9*>(img); @@ -168,32 +170,28 @@ gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface return gl::Error(GL_NO_ERROR); } -bool Image9::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) { // 3D textures are not supported by the D3D9 backend. - ASSERT(depth <= 1); + ASSERT(size.depth <= 1); // Only 2D and cube texture are supported by the D3D9 backend. ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP); - if (mWidth != width || - mHeight != height || - mDepth != depth || + if (mWidth != size.width || + mHeight != size.height || + mDepth != size.depth || mInternalFormat != internalformat || forceRelease) { - mRenderer = Renderer9::makeRenderer9(renderer); - - mWidth = width; - mHeight = height; - mDepth = depth; + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; mInternalFormat = internalformat; // compute the d3d format that will be used const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat); - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat); mD3DFormat = d3d9FormatInfo.texFormat; - mActualFormat = d3dFormatInfo.internalFormat; mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); SafeRelease(mSurface); @@ -397,7 +395,7 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i if (index.type == GL_TEXTURE_2D) { TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - gl::Error error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface); + error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface); if (error.isError()) { return error; @@ -405,23 +403,23 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i } else { - ASSERT(gl::IsCubemapTextureTarget(index.type)); + ASSERT(gl::IsCubeMapTextureTarget(index.type)); TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - gl::Error error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface); + error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface); if (error.isError()) { return error; } } - error = copyToSurface(destSurface, region.x, region.y, region.width, region.height); + error = copyToSurface(destSurface, region); SafeRelease(destSurface); return error; } -gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &area) { - ASSERT(width > 0 && height > 0); + ASSERT(area.width > 0 && area.height > 0 && area.depth == 1); ASSERT(destSurface); IDirect3DSurface9 *sourceSurface = NULL; @@ -434,10 +432,10 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, G ASSERT(sourceSurface && sourceSurface != destSurface); RECT rect; - rect.left = xoffset; - rect.top = yoffset; - rect.right = xoffset + width; - rect.bottom = yoffset + height; + rect.left = area.x; + rect.top = area.y; + rect.right = area.x + area.width; + rect.bottom = area.y + area.height; POINT point = {rect.left, rect.top}; @@ -480,22 +478,21 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, G // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input // into the target pixel rectangle. -gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) +gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) { // 3D textures are not supported by the D3D9 backend. - ASSERT(zoffset == 0 && depth == 1); + ASSERT(area.z == 0 && area.depth == 1); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); ASSERT(d3dFormatInfo.loadFunction != NULL); RECT lockRect = { - xoffset, yoffset, - xoffset + width, yoffset + height + area.x, area.y, + area.x + area.width, area.y + area.height }; D3DLOCKED_RECT locked; @@ -505,7 +502,7 @@ gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei return error; } - d3dFormatInfo.loadFunction(width, height, depth, + d3dFormatInfo.loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0, reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0); @@ -514,27 +511,26 @@ gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei return gl::Error(GL_NO_ERROR); } -gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) +gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) { // 3D textures are not supported by the D3D9 backend. - ASSERT(zoffset == 0 && depth == 1); + ASSERT(area.z == 0 && area.depth == 1); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); + GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); - ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); + ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); + ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); ASSERT(d3d9FormatInfo.loadFunction != NULL); RECT lockRect = { - xoffset, yoffset, - xoffset + width, yoffset + height + area.x, area.y, + area.x + area.width, area.y + area.height }; D3DLOCKED_RECT locked; @@ -544,7 +540,7 @@ gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset return error; } - d3d9FormatInfo.loadFunction(width, height, depth, + d3d9FormatInfo.loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0); @@ -554,12 +550,12 @@ gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset } // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) +gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) { ASSERT(source); // ES3.0 only behaviour to copy into a 3d texture - ASSERT(zoffset == 0); + ASSERT(destOffset.z == 0); RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source); @@ -593,7 +589,7 @@ gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Re int height = sourceArea.height; RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height }; - RECT destRect = { xoffset, yoffset, xoffset + width, yoffset + height }; + RECT destRect = { destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height }; D3DLOCKED_RECT sourceLock = {0}; result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); @@ -782,7 +778,7 @@ gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Re return gl::Error(GL_NO_ERROR); } -gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage) +gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Box &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage) { // Currently unreachable, due to only being used in a D3D11-only workaround UNIMPLEMENTED(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h index 8cc2258859..8cbfbbebf6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h @@ -7,10 +7,10 @@ // Image9.h: Defines the rx::Image9 class, which acts as the interface to // the actual underlying surfaces of a Texture. -#ifndef LIBGLESV2_RENDERER_IMAGE9_H_ -#define LIBGLESV2_RENDERER_IMAGE9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ -#include "libGLESv2/renderer/d3d/ImageD3D.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" #include "common/debug.h" namespace gl @@ -25,16 +25,16 @@ class Renderer9; class Image9 : public ImageD3D { public: - Image9(); + Image9(Renderer9 *renderer); ~Image9(); - static Image9 *makeImage9(Image *img); + static Image9 *makeImage9(ImageD3D *img); static gl::Error generateMipmap(Image9 *dest, Image9 *source); static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); - bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override; + bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; D3DFORMAT getD3DFormat() const; @@ -44,23 +44,19 @@ class Image9 : public ImageD3D virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level); virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); - virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input); - virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input); + virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source); + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source); private: - DISALLOW_COPY_AND_ASSIGN(Image9); - gl::Error getSurface(IDirect3DSurface9 **outSurface); gl::Error createSurface(); gl::Error setManagedSurface(IDirect3DSurface9 *surface); - gl::Error copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + gl::Error copyToSurface(IDirect3DSurface9 *dest, const gl::Box &area); gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect); void unlock(); @@ -74,4 +70,4 @@ class Image9 : public ImageD3D }; } -#endif // LIBGLESV2_RENDERER_IMAGE9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp index 1c51b9e985..c5d72e6a50 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -6,8 +6,8 @@ // Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. -#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h index 2375fcf4b0..61f8b11566 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h @@ -6,10 +6,10 @@ // Indexffer9.h: Defines the D3D9 IndexBuffer implementation. -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ -#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" namespace rx { @@ -38,8 +38,6 @@ class IndexBuffer9 : public IndexBuffer IDirect3DIndexBuffer9 *getBuffer() const; private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); - Renderer9 *const mRenderer; IDirect3DIndexBuffer9 *mIndexBuffer; @@ -50,4 +48,4 @@ class IndexBuffer9 : public IndexBuffer } -#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp index a3cab578be..96f12d7868 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp @@ -6,10 +6,9 @@ // Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. -#include "libGLESv2/renderer/d3d/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" #include <GLES2/gl2ext.h> @@ -132,8 +131,9 @@ gl::Error Query9::testQuery() mRenderer->notifyDeviceLost(); return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); } - else if (mRenderer->testDeviceLost(true)) + else if (mRenderer->testDeviceLost()) { + mRenderer->notifyDeviceLost(); return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h index 36851c6c6c..399da2ed83 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h @@ -6,10 +6,10 @@ // Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. -#ifndef LIBGLESV2_RENDERER_QUERY9_H_ -#define LIBGLESV2_RENDERER_QUERY9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ -#include "libGLESv2/renderer/QueryImpl.h" +#include "libANGLE/renderer/QueryImpl.h" namespace rx { @@ -27,8 +27,6 @@ class Query9 : public QueryImpl virtual gl::Error isResultAvailable(GLuint *available); private: - DISALLOW_COPY_AND_ASSIGN(Query9); - gl::Error testQuery(); GLuint mResult; @@ -40,4 +38,4 @@ class Query9 : public QueryImpl } -#endif // LIBGLESV2_RENDERER_QUERY9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp index 53d1f752fa..412c0109f5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp @@ -7,27 +7,21 @@ // RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 // pointers retained by renderbuffers. -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" namespace rx { -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTargetD3D *target) { ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target)); return static_cast<RenderTarget9*>(target); } -void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) -{ - // Currently a no-op -} - // TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) @@ -35,7 +29,7 @@ TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum in mHeight(height), mDepth(depth), mInternalFormat(internalFormat), - mActualFormat(internalFormat), + mD3DFormat(D3DFMT_UNKNOWN), mSamples(samples), mRenderTarget(surface) { @@ -45,9 +39,7 @@ TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum in { D3DSURFACE_DESC description; mRenderTarget->GetDesc(&description); - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format); - mActualFormat = d3dFormatInfo.internalFormat; + mD3DFormat = description.Format; } } @@ -76,11 +68,6 @@ GLenum TextureRenderTarget9::getInternalFormat() const return mInternalFormat; } -GLenum TextureRenderTarget9::getActualFormat() const -{ - return mActualFormat; -} - GLsizei TextureRenderTarget9::getSamples() const { return mSamples; @@ -98,6 +85,10 @@ IDirect3DSurface9 *TextureRenderTarget9::getSurface() return mRenderTarget; } +D3DFORMAT TextureRenderTarget9::getD3DFormat() const +{ + return mD3DFormat; +} SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth) : mSwapChain(swapChain), @@ -129,11 +120,6 @@ GLenum SurfaceRenderTarget9::getInternalFormat() const return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); } -GLenum SurfaceRenderTarget9::getActualFormat() const -{ - return d3d9::GetD3DFormatInfo(d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat; -} - GLsizei SurfaceRenderTarget9::getSamples() const { // Our EGL surfaces do not support multisampling. @@ -145,4 +131,9 @@ IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget()); } +D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const +{ + return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h index 4585697f4c..32c7dfa09c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h @@ -7,30 +7,27 @@ // RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers // retained by Renderbuffers. -#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ -#include "libGLESv2/renderer/RenderTarget.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" namespace rx { class Renderer9; class SwapChain9; -class RenderTarget9 : public RenderTarget +class RenderTarget9 : public RenderTargetD3D { public: RenderTarget9() { } virtual ~RenderTarget9() { } - static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); - - void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override; + static RenderTarget9 *makeRenderTarget9(RenderTargetD3D *renderTarget); virtual IDirect3DSurface9 *getSurface() = 0; - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget9); + virtual D3DFORMAT getD3DFormat() const = 0; }; class TextureRenderTarget9 : public RenderTarget9 @@ -44,19 +41,18 @@ class TextureRenderTarget9 : public RenderTarget9 GLsizei getHeight() const override; GLsizei getDepth() const override; GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; GLsizei getSamples() const override; IDirect3DSurface9 *getSurface() override; - private: - DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget9); + D3DFORMAT getD3DFormat() const override; + private: GLsizei mWidth; GLsizei mHeight; GLsizei mDepth; GLenum mInternalFormat; - GLenum mActualFormat; + D3DFORMAT mD3DFormat; GLsizei mSamples; IDirect3DSurface9 *mRenderTarget; @@ -72,18 +68,17 @@ class SurfaceRenderTarget9 : public RenderTarget9 GLsizei getHeight() const override; GLsizei getDepth() const override; GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; GLsizei getSamples() const override; IDirect3DSurface9 *getSurface() override; - private: - DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget9); + D3DFORMAT getD3DFormat() const override; + private: SwapChain9 *mSwapChain; bool mDepth; }; } -#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index 18e6e2d7f0..bf1c367693 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -6,79 +6,64 @@ // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h" -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/ProgramD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/State.h" -#include "libGLESv2/angletypes.h" - -#include "libEGL/Display.h" - -#include "common/features.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + #include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Display.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/features.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/renderer/d3d/d3d9/Blit9.h" +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Image9.h" +#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" + +#include "third_party/trace_event/trace_event.h" #include <sstream> -// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -#define REF_RAST 0 +#include <EGL/eglext.h> #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 #endif -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); +// Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2. +// Such a device would not be conformant. +#ifndef ANGLE_SUPPORT_SHADER_MODEL_2 +#define ANGLE_SUPPORT_SHADER_MODEL_2 0 +#endif namespace rx { -static const D3DFORMAT RenderTargetFormats[] = - { - D3DFMT_A1R5G5B5, - // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. - D3DFMT_A8R8G8B8, - D3DFMT_R5G6B5, - // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format - D3DFMT_X8R8G8B8 - }; - -static const D3DFORMAT DepthStencilFormats[] = - { - D3DFMT_UNKNOWN, - // D3DFMT_D16_LOCKABLE, - D3DFMT_D32, - // D3DFMT_D15S1, - D3DFMT_D24S8, - D3DFMT_D24X8, - // D3DFMT_D24X4S4, - D3DFMT_D16, - // D3DFMT_D32F_LOCKABLE, - // D3DFMT_D24FS8 - }; enum { @@ -91,10 +76,12 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 }; -Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes) - : RendererD3D(display), - mDc(hDc) +Renderer9::Renderer9(egl::Display *display) + : RendererD3D(display) { + // Initialize global annotator + gl::InitializeDebugAnnotations(&mAnnotator); + mD3d9Module = NULL; mD3d9 = NULL; @@ -106,13 +93,26 @@ Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl: mAdapter = D3DADAPTER_DEFAULT; - #if REF_RAST == 1 || defined(FORCE_REF_RAST) - mDeviceType = D3DDEVTYPE_REF; - #else + const egl::AttributeMap &attributes = display->getAttributeMap(); + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + switch (requestedDeviceType) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: mDeviceType = D3DDEVTYPE_HAL; - #endif + break; - mDeviceLost = false; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mDeviceType = D3DDEVTYPE_REF; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDeviceType = D3DDEVTYPE_NULLREF; + break; + + default: + UNREACHABLE(); + } mMaskedClearSavedState = NULL; @@ -140,20 +140,21 @@ Renderer9::~Renderer9() if (mDevice) { // If the device is lost, reset it first to prevent leaving the driver in an unstable state - if (testDeviceLost(false)) + if (testDeviceLost()) { resetDevice(); } } release(); + + gl::UninitializeDebugAnnotations(); } void Renderer9::release() { RendererD3D::cleanup(); - releaseShaderCompiler(); releaseDeviceResources(); SafeRelease(mDevice); @@ -178,19 +179,21 @@ Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) return static_cast<Renderer9*>(renderer); } -EGLint Renderer9::initialize() +egl::Error Renderer9::initialize() { if (!mCompiler.initialize()) { - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_COMPILER_ERROR, + "Compiler failed to initialize."); } + TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); if (mD3d9Module == NULL) { - ERR("No D3D9 module found - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found."); } typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); @@ -201,22 +204,23 @@ EGLint Renderer9::initialize() // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { + TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); ASSERT(mD3d9Ex); mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9)); ASSERT(mD3d9); } else { + TRACE_EVENT0("gpu", "Direct3DCreate9"); mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); } if (!mD3d9) { - ERR("Could not create D3D9 device - aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "Could not create D3D9 device."); } - if (mDc != NULL) + if (mDisplay->getNativeDisplayId() != nullptr) { // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to } @@ -225,6 +229,7 @@ EGLint Renderer9::initialize() // Give up on getting device caps after about one second. { + TRACE_EVENT0("gpu", "GetDeviceCaps"); for (int i = 0; i < 10; ++i) { result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); @@ -238,99 +243,83 @@ EGLint Renderer9::initialize() } else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from { - ERR("failed to get device caps (0x%x)\n", result); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_OTHER_ERROR, + "Failed to get device caps: Error code 0x%x\n", result); } } } - if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) +#if ANGLE_SUPPORT_SHADER_MODEL_2 + size_t minShaderModel = 2; +#else + size_t minShaderModel = 3; +#endif + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0)) { - ERR("Renderer does not support PS 2.0. aborting!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_UNSUPPORTED_VERSION, + "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0); } // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. // This is required by Texture2D::ensureRenderTarget. if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) { - ERR("Renderer does not support stretctrect from textures!\n"); - return EGL_NOT_INITIALIZED; + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_UNSUPPORTED_STRETCHRECT, + "Renderer does not support StretctRect from textures."); } { + TRACE_EVENT0("gpu", "GetAdapterIdentifier"); mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); } - mMinSwapInterval = 4; - mMaxSwapInterval = 0; - - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 0); - mMaxSwapInterval = std::max(mMaxSwapInterval, 0); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 1); - mMaxSwapInterval = std::max(mMaxSwapInterval, 1); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) - { - mMinSwapInterval = std::min(mMinSwapInterval, 2); - mMaxSwapInterval = std::max(mMaxSwapInterval, 2); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 3); - mMaxSwapInterval = std::max(mMaxSwapInterval, 3); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) - { - mMinSwapInterval = std::min(mMinSwapInterval, 4); - mMaxSwapInterval = std::max(mMaxSwapInterval, 4); - } - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); static const TCHAR className[] = TEXT("STATIC"); { + TRACE_EVENT0("gpu", "CreateWindowEx"); mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); } D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - - static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); - if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) - behaviorFlags |= D3DCREATE_MULTITHREADED; + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED; { + TRACE_EVENT0("gpu", "D3d9_CreateDevice"); result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) { - return EGL_BAD_ALLOC; + return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY, + "CreateDevice failed: device lost of out of memory"); } if (FAILED(result)) { + TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); - return EGL_BAD_ALLOC; + return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY, + "CreateDevice2 failed: device lost, not available, or of out of memory"); } } if (mD3d9Ex) { + TRACE_EVENT0("gpu", "mDevice_QueryInterface"); result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); ASSERT(SUCCEEDED(result)); } { + TRACE_EVENT0("gpu", "ShaderCache initialize"); mVertexShaderCache.initialize(mDevice); mPixelShaderCache.initialize(mDevice); } @@ -347,7 +336,7 @@ EGLint Renderer9::initialize() initializeDevice(); - return EGL_SUCCESS; + return egl::Error(EGL_SUCCESS); } // do any one-time device initialization @@ -389,7 +378,7 @@ void Renderer9::initializeDevice() ASSERT(!mVertexDataManager && !mIndexDataManager); mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this); + mIndexDataManager = new IndexDataManager(this, getRendererClass()); } D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() @@ -414,47 +403,124 @@ D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() return presentParameters; } -int Renderer9::generateConfigs(ConfigDesc **configDescList) +egl::ConfigSet Renderer9::generateConfigs() const { + static const GLenum colorBufferFormats[] = + { + GL_BGR5_A1_ANGLEX, + GL_BGRA8_EXT, + GL_RGB565, + + }; + + static const GLenum depthStencilBufferFormats[] = + { + GL_NONE, + GL_DEPTH_COMPONENT32_OES, + GL_DEPTH24_STENCIL8_OES, + GL_DEPTH_COMPONENT24_OES, + GL_DEPTH_COMPONENT16, + }; + + const gl::Caps &rendererCaps = getRendererCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + D3DDISPLAYMODE currentDisplayMode; mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - unsigned int numRenderFormats = ArraySize(RenderTargetFormats); - unsigned int numDepthFormats = ArraySize(DepthStencilFormats); - (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; - int numConfigs = 0; + // Determine the min and max swap intervals + int minSwapInterval = 4; + int maxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + { + minSwapInterval = std::min(minSwapInterval, 0); + maxSwapInterval = std::max(maxSwapInterval, 0); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + { + minSwapInterval = std::min(minSwapInterval, 1); + maxSwapInterval = std::max(maxSwapInterval, 1); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + { + minSwapInterval = std::min(minSwapInterval, 2); + maxSwapInterval = std::max(maxSwapInterval, 2); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + { + minSwapInterval = std::min(minSwapInterval, 3); + maxSwapInterval = std::max(maxSwapInterval, 3); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + { + minSwapInterval = std::min(minSwapInterval, 4); + maxSwapInterval = std::max(maxSwapInterval, 4); + } - for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + egl::ConfigSet configs; + for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) { - const d3d9::D3DFormat &renderTargetFormatInfo = d3d9::GetD3DFormatInfo(RenderTargetFormats[formatIndex]); - const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); - if (renderTargetFormatCaps.renderable) + GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; + const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + if (colorBufferFormatCaps.renderable) { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) { - const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]); - const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); - if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN) + GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex]; + const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE) { - ConfigDesc newConfig; - newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; - newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = (currentDisplayMode.Format == RenderTargetFormats[formatIndex]); - newConfig.es3Capable = false; - - (*configDescList)[numConfigs++] = newConfig; + const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + const d3d9::TextureFormat &d3d9ColorBufferFormatInfo = d3d9::GetTextureFormatInfo(colorBufferInternalFormat); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + // Mark as slow if blits to the back-buffer won't be straight forward + config.configCaveat = (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat) ? EGL_NONE : EGL_SLOW_CONFIG; + config.configID = static_cast<EGLint>(configs.size() + 1); + config.conformant = EGL_OPENGL_ES2_BIT; + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = maxSwapInterval; + config.minSwapInterval = minSwapInterval; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + config.renderableType = EGL_OPENGL_ES2_BIT; + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + + configs.add(config); } } } } - return numConfigs; -} - -void Renderer9::deleteConfigs(ConfigDesc *configDescList) -{ - delete [] (configDescList); + ASSERT(configs.size() > 0); + return configs; } void Renderer9::startScene() @@ -481,7 +547,39 @@ void Renderer9::endScene() } } -gl::Error Renderer9::sync(bool block) +gl::Error Renderer9::flush() +{ + IDirect3DQuery9* query = NULL; + gl::Error error = allocateEventQuery(&query); + if (error.isError()) + { + return error; + } + + HRESULT result = query->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); + } + + // Grab the query data once + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + freeEventQuery(query); + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::finish() { IDirect3DQuery9* query = NULL; gl::Error error = allocateEventQuery(&query); @@ -497,7 +595,7 @@ gl::Error Renderer9::sync(bool block) return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); } - // Grab the query data once in blocking and non-blocking case + // Grab the query data once result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); if (FAILED(result)) { @@ -510,8 +608,8 @@ gl::Error Renderer9::sync(bool block) return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); } - // If blocking, loop until the query completes - while (block && result == S_FALSE) + // Loop until the query completes + while (result == S_FALSE) { // Keep polling, but allow other threads to do something useful first Sleep(0); @@ -521,7 +619,7 @@ gl::Error Renderer9::sync(bool block) // explicitly check for device loss // some drivers seem to return S_FALSE even if the device is lost // instead of D3DERR_DEVICELOST like they should - if (result == S_FALSE && testDeviceLost(false)) + if (result == S_FALSE && testDeviceLost()) { result = D3DERR_DEVICELOST; } @@ -544,7 +642,7 @@ gl::Error Renderer9::sync(bool block) return gl::Error(GL_NO_ERROR); } -SwapChain *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) { return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); } @@ -651,7 +749,7 @@ bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const return false; } -gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, +gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. @@ -677,8 +775,19 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur int d3dSampler = index + d3dSamplerOffset; // Make sure to add the level offset for our tiny compressed texture workaround - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - DWORD baseLevel = samplerState.baseLevel + textureD3D->getNativeTexture()->getTopLevel(); + TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture); + + TextureStorage *storage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&storage); + if (error.isError()) + { + return error; + } + + // Storage should exist, texture should be complete + ASSERT(storage); + + DWORD baseLevel = samplerState.baseLevel + storage->getTopLevel(); mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); @@ -713,19 +822,25 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te if (texture) { - TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); + TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture); - TextureStorage *texStorage = textureImpl->getNativeTexture(); - if (texStorage) + TextureStorage *texStorage = nullptr; + gl::Error error = textureImpl->getNativeTexture(&texStorage); + if (error.isError()) { - TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); + return error; + } - gl::Error error = storage9->getBaseTexture(&d3dTexture); - if (error.isError()) - { - return error; - } + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); + error = storage9->getBaseTexture(&d3dTexture); + if (error.isError()) + { + return error; } + // If we get NULL back from getBaseTexture here, something went wrong // in the texture class and we're unexpectedly missing the d3d texture ASSERT(d3dTexture != NULL); @@ -745,7 +860,9 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) +gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/, + const GLint /*vertexUniformBuffers*/[], + const GLint /*fragmentUniformBuffers*/[]) { // No effect in ES2/D3D9 return gl::Error(GL_NO_ERROR); @@ -850,7 +967,7 @@ gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl: GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; // Set the color mask - bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; + bool zeroColorMaskAllowed = getVendorId() != VENDOR_ID_AMD; // Apparently some ATI cards have a bug where a draw with a zero color // write mask can cause later draws to have incorrect results. Instead, // set a nonzero color write mask but modify the blend state so that no @@ -1096,7 +1213,7 @@ void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF mForceSetViewport = false; } -bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) { switch (mode) { @@ -1137,7 +1254,7 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) } -gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer) +gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer) { ASSERT(depthbuffer); @@ -1158,7 +1275,7 @@ gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, } gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); - gl::Error error = nullRenderbuffer->setStorage(width, height, GL_NONE, 0); + gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height); if (error.isError()) { SafeDelete(nullRenderbuffer); @@ -1187,28 +1304,31 @@ gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) +gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer) { // if there is no color attachment we must synthesize a NULL colorattachment // to keep the D3D runtime happy. This should only be possible if depth texturing. - gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); - if (!attachment) + if (!colorBuffer) { - gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment); + gl::Error error = getNullColorbuffer(depthStencilBuffer, &colorBuffer); if (error.isError()) { return error; } } - ASSERT(attachment); + ASSERT(colorBuffer); + + size_t renderTargetWidth = 0; + size_t renderTargetHeight = 0; + D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN; bool renderTargetChanged = false; - unsigned int renderTargetSerial = GetAttachmentSerial(attachment); + unsigned int renderTargetSerial = GetAttachmentSerial(colorBuffer); if (renderTargetSerial != mAppliedRenderTargetSerial) { // Apply the render target on the device RenderTarget9 *renderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(attachment, &renderTarget); + gl::Error error = d3d9::GetAttachmentRenderTarget(colorBuffer, &renderTarget); if (error.isError()) { return error; @@ -1221,35 +1341,25 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) mDevice->SetRenderTarget(0, renderTargetSurface); SafeRelease(renderTargetSurface); + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + renderTargetFormat = renderTarget->getD3DFormat(); + mAppliedRenderTargetSerial = renderTargetSerial; renderTargetChanged = true; } - gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (depthStencil) - { - depthbufferSerial = GetAttachmentSerial(depthStencil); - } - else if (framebuffer->getStencilbuffer()) - { - depthStencil = framebuffer->getStencilbuffer(); - stencilbufferSerial = GetAttachmentSerial(depthStencil); - } - - if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial || - !mDepthStencilInitialized) + unsigned int depthStencilSerial = (depthStencilBuffer != nullptr) ? GetAttachmentSerial(depthStencilBuffer) : 0; + if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized) { unsigned int depthSize = 0; unsigned int stencilSize = 0; // Apply the depth stencil on the device - if (depthStencil) + if (depthStencilBuffer) { RenderTarget9 *depthStencilRenderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); + gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencilBuffer, &depthStencilRenderTarget); if (error.isError()) { return error; @@ -1262,8 +1372,8 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) mDevice->SetDepthStencilSurface(depthStencilSurface); SafeRelease(depthStencilSurface); - depthSize = depthStencil->getDepthSize(); - stencilSize = depthStencil->getStencilSize(); + depthSize = depthStencilBuffer->getDepthSize(); + stencilSize = depthStencilBuffer->getStencilSize(); } else { @@ -1282,8 +1392,7 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) mForceSetDepthStencilState = true; } - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; + mAppliedDepthStencilSerial = depthStencilSerial; mDepthStencilInitialized = true; } @@ -1293,16 +1402,21 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) mForceSetViewport = true; mForceSetBlendState = true; - mRenderTargetDesc.width = attachment->getWidth(); - mRenderTargetDesc.height = attachment->getHeight(); - mRenderTargetDesc.format = attachment->getActualFormat(); + mRenderTargetDesc.width = renderTargetWidth; + mRenderTargetDesc.height = renderTargetHeight; + mRenderTargetDesc.format = renderTargetFormat; mRenderTargetDescInitialized = true; } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) +{ + return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer()); +} + +gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); @@ -1311,7 +1425,7 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsi return error; } - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getCurrentProgramBinary(), instances, &mRepeatDraw); + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getProgram(), instances, &mRepeatDraw); } // Applies the indices and element array bindings to the Direct3D 9 device @@ -1339,12 +1453,12 @@ gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *element void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) { - UNREACHABLE(); + ASSERT(!state.isTransformFeedbackActiveUnpaused()); } -gl::Error Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) { - ASSERT(!transformFeedbackActive); + ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); startScene(); @@ -1414,7 +1528,7 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); intptr_t offset = reinterpret_cast<intptr_t>(indices); const uint8_t *bufferData = NULL; gl::Error error = storage->getData(&bufferData); @@ -1616,7 +1730,7 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid if (elementArrayBuffer) { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); + BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer); intptr_t offset = reinterpret_cast<intptr_t>(indices); const uint8_t *bufferData = NULL; @@ -1710,22 +1824,22 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, +gl::Error Renderer9::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive) { ASSERT(!transformFeedbackActive); ASSERT(!rasterizerDiscard); - ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); + ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program); - ShaderExecutable *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe); + ShaderExecutableD3D *vertexExe = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); if (error.isError()) { return error; } - ShaderExecutable *pixelExe = NULL; + ShaderExecutableD3D *pixelExe = NULL; error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); if (error.isError()) { @@ -1752,7 +1866,7 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve // per-program, checking the program serial guarantees we upload fresh // uniform data even if our shader pointers are the same. // https://code.google.com/p/angleproject/issues/detail?id=661 - unsigned int programSerial = programBinary->getSerial(); + unsigned int programSerial = programD3D->getSerial(); if (programSerial != mAppliedProgramSerial) { programD3D->dirtyAllUniforms(); @@ -1862,7 +1976,9 @@ void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v applyUniformnfv(targetUniform, (GLfloat*)vector); } -gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) +gl::Error Renderer9::clear(const ClearParameters &clearParams, + const gl::FramebufferAttachment *colorBuffer, + const gl::FramebufferAttachment *depthStencilBuffer) { if (clearParams.colorClearType != GL_FLOAT) { @@ -1886,10 +2002,20 @@ gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Fra DWORD stencil = clearParams.stencilClearValue & 0x000000FF; unsigned int stencilUnmasked = 0x0; - if (clearParams.clearStencil && frameBuffer->hasStencil()) + if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0) { - unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits; - stencilUnmasked = (0x1 << stencilSize) - 1; + RenderTargetD3D *stencilRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(depthStencilBuffer, &stencilRenderTarget); + if (error.isError()) + { + return error; + } + + RenderTarget9 *stencilRenderTarget9 = RenderTarget9::makeRenderTarget9(stencilRenderTarget); + ASSERT(stencilRenderTarget9); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat()); + stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1; } const bool needMaskedStencilClear = clearParams.clearStencil && @@ -1899,14 +2025,23 @@ gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Fra D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); if (clearColor) { - const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); + RenderTargetD3D *colorRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(colorBuffer, &colorRenderTarget); + if (error.isError()) + { + return error; + } - color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - gl::unorm<8>((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - gl::unorm<8>((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); + RenderTarget9 *colorRenderTarget9 = RenderTarget9::makeRenderTarget9(colorRenderTarget); + ASSERT(colorRenderTarget9); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(colorBuffer->getInternalFormat()); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat()); + + color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || @@ -2082,8 +2217,7 @@ gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Fra void Renderer9::markAllStateDirty() { mAppliedRenderTargetSerial = 0; - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; + mAppliedDepthStencilSerial = 0; mDepthStencilInitialized = false; mRenderTargetDescInitialized = false; @@ -2141,19 +2275,8 @@ void Renderer9::releaseDeviceResources() } } -void Renderer9::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer9::isDeviceLost() -{ - return mDeviceLost; -} - // set notify to true to broadcast a message to all contexts of the device loss -bool Renderer9::testDeviceLost(bool notify) +bool Renderer9::testDeviceLost() { HRESULT status = getDeviceStatusCode(); bool isLost = FAILED(status); @@ -2166,10 +2289,6 @@ bool Renderer9::testDeviceLost(bool notify) // Note that we don't want to clear the device loss status here // -- this needs to be done by resetDevice mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } } return isLost; @@ -2217,7 +2336,7 @@ bool Renderer9::resetDevice() D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); HRESULT result = D3D_OK; - bool lost = testDeviceLost(false); + bool lost = testDeviceLost(); bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); // Device Removed is a feature which is only present with D3D9Ex @@ -2237,7 +2356,7 @@ bool Renderer9::resetDevice() { Sleep(500); // Give the graphics driver some CPU time result = mDeviceEx->ResetEx(&presentParameters, NULL); - lost = testDeviceLost(false); + lost = testDeviceLost(); } else { @@ -2252,7 +2371,7 @@ bool Renderer9::resetDevice() { result = mDevice->Reset(&presentParameters); } - lost = testDeviceLost(false); + lost = testDeviceLost(); } } @@ -2311,12 +2430,12 @@ bool Renderer9::resetRemovedDevice() // adapters and create another Direct3D device. If application continues rendering without // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. release(); - return (initialize() == EGL_SUCCESS); + return !initialize().isError(); } -DWORD Renderer9::getAdapterVendor() const +VendorID Renderer9::getVendorId() const { - return mAdapterIdentifier.VendorId; + return static_cast<VendorID>(mAdapterIdentifier.VendorId); } std::string Renderer9::getRendererDescription() const @@ -2367,7 +2486,7 @@ unsigned int Renderer9::getReservedFragmentUniformBuffers() const bool Renderer9::getShareHandleSupport() const { // PIX doesn't seem to support using share handles, so disable them. - return (mD3d9Ex != NULL) && !gl::perfActive(); + return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive(); } bool Renderer9::getPostSubBufferSupport() const @@ -2380,19 +2499,19 @@ int Renderer9::getMajorShaderModel() const return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); } -DWORD Renderer9::getCapsDeclTypes() const +int Renderer9::getMinorShaderModel() const { - return mDeviceCaps.DeclTypes; + return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); } -int Renderer9::getMinSwapInterval() const +std::string Renderer9::getShaderModelSuffix() const { - return mMinSwapInterval; + return ""; } -int Renderer9::getMaxSwapInterval() const +DWORD Renderer9::getCapsDeclTypes() const { - return mMaxSwapInterval; + return mDeviceCaps.DeclTypes; } D3DPOOL Renderer9::getBufferPool(DWORD usage) const @@ -2412,8 +2531,8 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const return D3DPOOL_DEFAULT; } -gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) { RECT rect; rect.left = sourceRect.x; @@ -2421,11 +2540,11 @@ gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectang rect.right = sourceRect.x + sourceRect.width; rect.bottom = sourceRect.y + sourceRect.height; - return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); + return mBlit->copy2D(framebuffer, rect, destFormat, destOffset, storage, level); } -gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) +gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) { RECT rect; rect.left = sourceRect.x; @@ -2433,385 +2552,26 @@ gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Recta rect.right = sourceRect.x + sourceRect.width; rect.bottom = sourceRect.y + sourceRect.height; - return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); + return mBlit->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level); } -gl::Error Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) { // 3D textures are not available in the D3D9 backend. UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); } -gl::Error Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) { // 2D array textures are not available in the D3D9 backend. UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); } -gl::Error Renderer9::blitRect(const gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, - const gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) -{ - ASSERT(filter == GL_NEAREST); - - endScene(); - - if (blitRenderTarget) - { - gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); - ASSERT(readBuffer); - - RenderTarget9 *readRenderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(readRenderTarget); - - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); - ASSERT(drawBuffer); - - RenderTarget9 *drawRenderTarget = NULL; - error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(drawRenderTarget); - - // The getSurface calls do an AddRef so save them until after no errors are possible - IDirect3DSurface9* readSurface = readRenderTarget->getSurface(); - ASSERT(readSurface); - - IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface(); - ASSERT(drawSurface); - - gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); - gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); - - RECT srcRect; - srcRect.left = readRect.x; - srcRect.right = readRect.x + readRect.width; - srcRect.top = readRect.y; - srcRect.bottom = readRect.y + readRect.height; - - RECT dstRect; - dstRect.left = drawRect.x; - dstRect.right = drawRect.x + drawRect.width; - dstRect.top = drawRect.y; - dstRect.bottom = drawRect.y + drawRect.height; - - // Clip the rectangles to the scissor rectangle - if (scissor) - { - if (dstRect.left < scissor->x) - { - srcRect.left += (scissor->x - dstRect.left); - dstRect.left = scissor->x; - } - if (dstRect.top < scissor->y) - { - srcRect.top += (scissor->y - dstRect.top); - dstRect.top = scissor->y; - } - if (dstRect.right > scissor->x + scissor->width) - { - srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); - dstRect.right = scissor->x + scissor->width; - } - if (dstRect.bottom > scissor->y + scissor->height) - { - srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); - dstRect.bottom = scissor->y + scissor->height; - } - } - - // Clip the rectangles to the destination size - if (dstRect.left < 0) - { - srcRect.left += -dstRect.left; - dstRect.left = 0; - } - if (dstRect.right > dstSize.width) - { - srcRect.right -= (dstRect.right - dstSize.width); - dstRect.right = dstSize.width; - } - if (dstRect.top < 0) - { - srcRect.top += -dstRect.top; - dstRect.top = 0; - } - if (dstRect.bottom > dstSize.height) - { - srcRect.bottom -= (dstRect.bottom - dstSize.height); - dstRect.bottom = dstSize.height; - } - - // Clip the rectangles to the source size - if (srcRect.left < 0) - { - dstRect.left += -srcRect.left; - srcRect.left = 0; - } - if (srcRect.right > srcSize.width) - { - dstRect.right -= (srcRect.right - srcSize.width); - srcRect.right = srcSize.width; - } - if (srcRect.top < 0) - { - dstRect.top += -srcRect.top; - srcRect.top = 0; - } - if (srcRect.bottom > srcSize.height) - { - dstRect.bottom -= (srcRect.bottom - srcSize.height); - srcRect.bottom = srcSize.height; - } - - HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); - - SafeRelease(readSurface); - SafeRelease(drawSurface); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); - } - } - - if (blitDepth || blitStencil) - { - gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - ASSERT(readBuffer); - - RenderTarget9 *readDepthStencil = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil); - if (error.isError()) - { - return error; - } - ASSERT(readDepthStencil); - - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); - ASSERT(drawBuffer); - - RenderTarget9 *drawDepthStencil = NULL; - error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil); - if (error.isError()) - { - return error; - } - ASSERT(drawDepthStencil); - - // The getSurface calls do an AddRef so save them until after no errors are possible - IDirect3DSurface9* readSurface = readDepthStencil->getSurface(); - ASSERT(readDepthStencil); - - IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); - ASSERT(drawDepthStencil); - - HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); - - SafeRelease(readSurface); - SafeRelease(drawSurface); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) -{ - ASSERT(pack.pixelBuffer.get() == NULL); - - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); - ASSERT(colorbuffer); - - RenderTarget9 *renderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); - - IDirect3DSurface9 *surface = renderTarget->getSurface(); - ASSERT(surface); - - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) - { - UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); - } - - HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && getShareHandleSupport() && - x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && - desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; - if (directToPixels) - { - // Use the pixels ptr as a shared handle to write directly into client's memory - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels)); - if (FAILED(result)) - { - // Try again without the shared handle - directToPixels = false; - } - } - - if (!directToPixels) - { - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, NULL); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); - } - } - - result = mDevice->GetRenderTargetData(surface, systemSurface); - SafeRelease(surface); - - if (FAILED(result)) - { - SafeRelease(systemSurface); - - // It turns out that D3D will sometimes produce more error - // codes than those documented. - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } - else - { - UNREACHABLE(); - } - - return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); - } - - if (directToPixels) - { - SafeRelease(systemSurface); - return gl::Error(GL_NO_ERROR); - } - - RECT rect; - rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width)); - rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height)); - rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width)); - rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height)); - - D3DLOCKED_RECT lock; - result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); - - if (FAILED(result)) - { - UNREACHABLE(); - SafeRelease(systemSurface); - - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); - } - - uint8_t *source; - int inputPitch; - if (pack.reverseRowOrder) - { - source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = reinterpret_cast<uint8_t*>(lock.pBits); - inputPitch = lock.Pitch; - } - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); - if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) - { - // Direct copy possible - for (int y = 0; y < rect.bottom - rect.top; y++) - { - memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); - } - } - else - { - const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); - - const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); - - if (fastCopyFunc) - { - // Fast copy is possible through some special function - for (int y = 0; y < rect.bottom - rect.top; y++) - { - for (int x = 0; x < rect.right - rect.left; x++) - { - uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - fastCopyFunc(src, dest); - } - } - } - else - { - uint8_t temp[sizeof(gl::ColorF)]; - for (int y = 0; y < rect.bottom - rect.top; y++) - { - for (int x = 0; x < rect.right - rect.left; x++) - { - uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - // readFunc and writeFunc will be using the same type of color, CopyTexImage - // will not allow the copy otherwise. - sourceD3DFormatInfo.colorReadFunction(src, temp); - destFormatTypeInfo.colorWriteFunction(temp, dest); - } - } - } - } - - systemSurface->UnlockRect(); - SafeRelease(systemSurface); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - *outRT = new SurfaceRenderTarget9(swapChain9, depth); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) +gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) { const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format); @@ -2862,24 +2622,34 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL return gl::Error(GL_NO_ERROR); } -ShaderImpl *Renderer9::createShader(const gl::Data &data, GLenum type) +FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::Framebuffer::Data &data) { - return new ShaderD3D(data, type, this); + return createFramebuffer(data); } -ProgramImpl *Renderer9::createProgram() +FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data) { - return new ProgramD3D(this); + return new Framebuffer9(data, this); +} + +CompilerImpl *Renderer9::createCompiler(const gl::Data &data) +{ + return new CompilerD3D(data, SH_HLSL9_OUTPUT); } -void Renderer9::releaseShaderCompiler() +ShaderImpl *Renderer9::createShader(GLenum type) { - ShaderD3D::releaseCompiler(); + return new ShaderD3D(type); +} + +ProgramImpl *Renderer9::createProgram() +{ + return new ProgramD3D(this); } gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable) + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) { // Transform feedback is not supported in ES2 or D3D9 ASSERT(transformFeedbackVaryings.size() == 0); @@ -2918,8 +2688,8 @@ gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderT gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable) + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) { // Transform feedback is not supported in ES2 or D3D9 ASSERT(transformFeedbackVaryings.size() == 0); @@ -2943,17 +2713,16 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; - if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION) + if (workarounds.skipOptimization) { flags = D3DCOMPILE_SKIP_OPTIMIZATION; } - else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION) + else if (workarounds.useMaxOptimization) { flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; } - else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE); - if (gl::perfActive()) + if (gl::DebugAnnotationsActive()) { #ifndef NDEBUG flags = D3DCOMPILE_SKIP_OPTIMIZATION; @@ -3002,9 +2771,9 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string return gl::Error(GL_NO_ERROR); } -UniformStorage *Renderer9::createUniformStorage(size_t storageSize) +UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize) { - return new UniformStorage(storageSize); + return new UniformStorageD3D(storageSize); } gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) @@ -3065,32 +2834,32 @@ gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurfac return gl::Error(GL_NO_ERROR); } -Image *Renderer9::createImage() +ImageD3D *Renderer9::createImage() { - return new Image9(); + return new Image9(this); } -gl::Error Renderer9::generateMipmap(Image *dest, Image *src) +gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src) { Image9 *src9 = Image9::makeImage9(src); Image9 *dst9 = Image9::makeImage9(dest); return Image9::generateMipmap(dst9, src9); } -TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) +TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain) { SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); return new TextureStorage9_2D(this, swapChain9); } -TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) { return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); } -TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) +TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) { - return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels); + return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); } TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) @@ -3127,13 +2896,6 @@ RenderbufferImpl *Renderer9::createRenderbuffer() return renderbuffer; } -RenderbufferImpl *Renderer9::createRenderbuffer(SwapChain *swapChain, bool depth) -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - renderbuffer->setStorage(swapChain, depth); - return renderbuffer; -} - bool Renderer9::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h index 10d2fb11e8..19bea3eb35 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -6,16 +6,17 @@ // Renderer9.h: Defines a back-end specific class for the D3D9 renderer. -#ifndef LIBGLESV2_RENDERER_RENDERER9_H_ -#define LIBGLESV2_RENDERER_RENDERER9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ #include "common/angleutils.h" #include "common/mathutil.h" -#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h" +#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" namespace gl { @@ -29,33 +30,54 @@ class AttributeMap; namespace rx { -class VertexDataManager; +class Blit9; class IndexDataManager; class StreamingIndexBufferInterface; class StaticIndexBufferInterface; +class VertexDataManager; +struct ClearParameters; struct TranslatedAttribute; -class Blit9; + +enum D3D9InitError +{ + D3D9_INIT_SUCCESS = 0, + // Failed to load the D3D or ANGLE compiler + D3D9_INIT_COMPILER_ERROR, + // Failed to load a necessary DLL + D3D9_INIT_MISSING_DEP, + // Device creation error + D3D9_INIT_CREATE_DEVICE_ERROR, + // System does not meet minimum shader spec + D3D9_INIT_UNSUPPORTED_VERSION, + // System does not support stretchrect from textures + D3D9_INIT_UNSUPPORTED_STRETCHRECT, + // A call returned out of memory or device lost + D3D9_INIT_OUT_OF_MEMORY, + // Other unspecified error + D3D9_INIT_OTHER_ERROR, + NUM_D3D9_INIT_ERRORS +}; class Renderer9 : public RendererD3D { public: - Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes); + explicit Renderer9(egl::Display *display); virtual ~Renderer9(); static Renderer9 *makeRenderer9(Renderer *renderer); - virtual EGLint initialize(); + egl::Error initialize() override; virtual bool resetDevice(); - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); + egl::ConfigSet generateConfigs() const override; void startScene(); void endScene(); - virtual gl::Error sync(bool block); + gl::Error flush() override; + gl::Error finish() override; - virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); void freeEventQuery(IDirect3DQuery9* query); @@ -69,7 +91,9 @@ class Renderer9 : public RendererD3D virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); + gl::Error setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) override; virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, @@ -82,30 +106,31 @@ class Renderer9 : public RendererD3D bool ignoreViewport); gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer); + virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive); virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray); - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances); + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); + virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances); virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - virtual void applyTransformFeedbackBuffers(const gl::State& state); + void applyTransformFeedbackBuffers(const gl::State &state) override; - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); + gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override; virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override; + gl::Error clear(const ClearParameters &clearParams, + const gl::FramebufferAttachment *colorBuffer, + const gl::FramebufferAttachment *depthStencilBuffer); virtual void markAllStateDirty(); // lost device - void notifyDeviceLost() override; - bool isDeviceLost() override; - bool testDeviceLost(bool notify) override; + bool testDeviceLost() override; bool testDeviceResettable() override; - DWORD getAdapterVendor() const override; + VendorID getVendorId() const override; std::string getRendererDescription() const override; GUID getAdapterIdentifier() const override; @@ -119,53 +144,49 @@ class Renderer9 : public RendererD3D virtual bool getPostSubBufferSupport() const; virtual int getMajorShaderModel() const; + int getMinorShaderModel() const override; + std::string getShaderModelSuffix() const override; + DWORD getCapsDeclTypes() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; // Pixel operations - virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - - gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, - const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) override; - - virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); // RenderTarget creation - virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT); - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT); + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + + // Framebuffer creation + FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; + FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; // Shader creation - virtual ShaderImpl *createShader(const gl::Data &data, GLenum type); + virtual CompilerImpl *createCompiler(const gl::Data &data); + virtual ShaderImpl *createShader(GLenum type); virtual ProgramImpl *createProgram(); // Shader operations - void releaseShaderCompiler() override; virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable); + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable); - virtual UniformStorage *createUniformStorage(size_t storageSize); + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable); + virtual UniformStorageD3D *createUniformStorage(size_t storageSize); // Image operations - virtual Image *createImage(); - gl::Error generateMipmap(Image *dest, Image *source) override; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); + virtual ImageD3D *createImage(); + gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); @@ -174,7 +195,6 @@ class Renderer9 : public RendererD3D // Renderbuffer creation virtual RenderbufferImpl *createRenderbuffer(); - virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth); // Buffer creation virtual BufferImpl *createBuffer(); @@ -194,7 +214,7 @@ class Renderer9 : public RendererD3D // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); // D3D9-renderer specific methods @@ -202,15 +222,17 @@ class Renderer9 : public RendererD3D D3DPOOL getTexturePool(DWORD usage) const; - virtual bool getLUID(LUID *adapterLuid) const; + bool getLUID(LUID *adapterLuid) const override; virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - private: - DISALLOW_COPY_AND_ASSIGN(Renderer9); + RendererClass getRendererClass() const override { return RENDERER_D3D9; } + + D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; } + private: void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; Workarounds generateWorkarounds() const override; @@ -225,12 +247,11 @@ class Renderer9 : public RendererD3D gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); - gl::Error getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer); + gl::Error getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer); D3DPOOL getBufferPool(DWORD usage) const; HMODULE mD3d9Module; - HDC mDc; void initializeDevice(); D3DPRESENT_PARAMETERS getDefaultPresentParameters(); @@ -253,7 +274,6 @@ class Renderer9 : public RendererD3D HWND mDeviceWindow; - bool mDeviceLost; D3DCAPS9 mDeviceCaps; D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; @@ -262,21 +282,25 @@ class Renderer9 : public RendererD3D GLsizei mRepeatDraw; bool mSceneStarted; - int mMinSwapInterval; - int mMaxSwapInterval; bool mVertexTextureSupport; // current render target states unsigned int mAppliedRenderTargetSerial; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; + unsigned int mAppliedDepthStencilSerial; bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; - RenderTarget::Desc mRenderTargetDesc; unsigned int mCurStencilSize; unsigned int mCurDepthSize; + struct RenderTargetDesc + { + size_t width; + size_t height; + D3DFORMAT format; + }; + RenderTargetDesc mRenderTargetDesc; + IDirect3DStateBlock9 *mMaskedClearSavedState; // previously set render states @@ -346,7 +370,8 @@ class Renderer9 : public RendererD3D } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; UINT mMaxNullColorbufferLRU; + DebugAnnotator9 mAnnotator; }; } -#endif // LIBGLESV2_RENDERER_RENDERER9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h index 6d7d2d648f..cf831c62fa 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h @@ -7,10 +7,10 @@ // ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects // keyed by their byte code. -#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ -#define LIBGLESV2_RENDERER_SHADER_CACHE_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ -#include "libGLESv2/Error.h" +#include "libANGLE/Error.h" #include "common/debug.h" @@ -21,7 +21,7 @@ namespace rx { template <typename ShaderObject> -class ShaderCache +class ShaderCache : angle::NonCopyable { public: ShaderCache() : mDevice(NULL) @@ -82,8 +82,6 @@ class ShaderCache } private: - DISALLOW_COPY_AND_ASSIGN(ShaderCache); - const static size_t kMaxMapSize = 100; HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) @@ -107,4 +105,4 @@ typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache; } -#endif // LIBGLESV2_RENDERER_SHADER_CACHE_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp index bc7120461b..280e80930b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -7,7 +7,7 @@ // ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" #include "common/debug.h" @@ -15,14 +15,14 @@ namespace rx { ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) - : ShaderExecutable(function, length) + : ShaderExecutableD3D(function, length) { mPixelExecutable = executable; mVertexExecutable = NULL; } ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) - : ShaderExecutable(function, length) + : ShaderExecutableD3D(function, length) { mVertexExecutable = executable; mPixelExecutable = NULL; @@ -34,7 +34,7 @@ ShaderExecutable9::~ShaderExecutable9() SafeRelease(mPixelExecutable); } -ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) +ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutableD3D *executable) { ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); return static_cast<ShaderExecutable9*>(executable); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h index fa1e6c2844..561f7defc8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h @@ -7,33 +7,31 @@ // ShaderExecutable9.h: Defines a D3D9-specific class to contain shader // executable implementation details. -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ -#include "libGLESv2/renderer/ShaderExecutable.h" +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" namespace rx { -class ShaderExecutable9 : public ShaderExecutable +class ShaderExecutable9 : public ShaderExecutableD3D { public: ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); virtual ~ShaderExecutable9(); - static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); + static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutableD3D *executable); IDirect3DPixelShader9 *getPixelShader() const; IDirect3DVertexShader9 *getVertexShader() const; private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); - IDirect3DPixelShader9 *mPixelExecutable; IDirect3DVertexShader9 *mVertexExecutable; }; } -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
\ No newline at end of file +#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp index 95eb1a4371..1620668166 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp @@ -6,12 +6,11 @@ // SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" - -#include "common/features.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/features.h" namespace rx { @@ -19,7 +18,9 @@ namespace rx SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) : mRenderer(renderer), - SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat) + SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + mColorRenderTarget(this, false), + mDepthStencilRenderTarget(this, true) { mSwapChain = NULL; mBackBuffer = NULL; @@ -155,8 +156,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); + // Don't create a swapchain for NULLREF devices + D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType(); EGLNativeWindowType window = mNativeWindow.getNativeWindow(); - if (window) + if (window && deviceType != D3DDEVTYPE_NULLREF) { D3DPRESENT_PARAMETERS presentParameters = {0}; presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; @@ -181,7 +184,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI // // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. - if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL) + if (mRenderer->getVendorId() == VENDOR_ID_INTEL) { presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; } @@ -381,7 +384,7 @@ IDirect3DTexture9 *SwapChain9::getOffscreenTexture() return mOffscreenTexture; } -SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) +SwapChain9 *SwapChain9::makeSwapChain9(SwapChainD3D *swapChain) { ASSERT(HAS_DYNAMIC_TYPE(SwapChain9*, swapChain)); return static_cast<SwapChain9*>(swapChain); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h index cb33bfbc0c..81ac08ca7b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h @@ -6,17 +6,18 @@ // SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ #include "common/angleutils.h" -#include "libGLESv2/renderer/SwapChain.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" namespace rx { class Renderer9; -class SwapChain9 : public SwapChain +class SwapChain9 : public SwapChainD3D { public: SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, @@ -28,6 +29,9 @@ class SwapChain9 : public SwapChain virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); virtual void recreate(); + RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } + RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + virtual IDirect3DSurface9 *getRenderTarget(); virtual IDirect3DSurface9 *getDepthStencil(); virtual IDirect3DTexture9 *getOffscreenTexture(); @@ -35,11 +39,9 @@ class SwapChain9 : public SwapChain EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } - static SwapChain9 *makeSwapChain9(SwapChain *swapChain); + static SwapChain9 *makeSwapChain9(SwapChainD3D *swapChain); private: - DISALLOW_COPY_AND_ASSIGN(SwapChain9); - void release(); Renderer9 *mRenderer; @@ -52,7 +54,10 @@ class SwapChain9 : public SwapChain IDirect3DSurface9 *mRenderTarget; IDirect3DSurface9 *mDepthStencil; IDirect3DTexture9* mOffscreenTexture; + + SurfaceRenderTarget9 mColorRenderTarget; + SurfaceRenderTarget9 mDepthStencilRenderTarget; }; } -#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp index 0ff4fd3b0f..139cb3eb08 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp @@ -8,15 +8,15 @@ // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the // D3D9 texture. -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Texture.h" namespace rx { @@ -92,7 +92,7 @@ int TextureStorage9::getLevelCount() const return mMipLevels - mTopLevel; } -gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, +gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData) { UNREACHABLE(); @@ -180,7 +180,7 @@ gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSu return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT) +gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTargetD3D **outRT) { if (!mRenderTarget && isRenderTarget()) { @@ -286,7 +286,7 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) return gl::Error(GL_NO_ERROR); } -TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels) +TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; @@ -356,7 +356,7 @@ gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) +gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(outRT); ASSERT(index.mipIndex == 0); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h index da0e1f2f18..5cc06f07b1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h @@ -8,17 +8,17 @@ // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the // D3D9 texture. -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ -#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" #include "common/debug.h" namespace rx { class Renderer9; class SwapChain9; -class RenderTarget; +class RenderTargetD3D; class RenderTarget9; class TextureStorage9 : public TextureStorage @@ -34,14 +34,14 @@ class TextureStorage9 : public TextureStorage DWORD getUsage() const; virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0; - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; virtual int getTopLevel() const; virtual bool isRenderTarget() const; virtual bool isManaged() const; virtual int getLevelCount() const; - virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData); protected: @@ -57,8 +57,6 @@ class TextureStorage9 : public TextureStorage TextureStorage9(Renderer9 *renderer, DWORD usage); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9); - const DWORD mD3DUsage; const D3DPOOL mD3DPool; }; @@ -73,14 +71,12 @@ class TextureStorage9_2D : public TextureStorage9 static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); virtual gl::Error copyToStorage(TextureStorage *destStorage); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); - IDirect3DTexture9 *mTexture; RenderTarget9 *mRenderTarget; }; @@ -88,20 +84,18 @@ class TextureStorage9_2D : public TextureStorage9 class TextureStorage9_Cube : public TextureStorage9 { public: - TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual ~TextureStorage9_Cube(); static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); virtual gl::Error copyToStorage(TextureStorage *destStorage); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); - static const size_t CUBE_FACE_COUNT = 6; IDirect3DCubeTexture9 *mTexture; @@ -110,5 +104,5 @@ class TextureStorage9_Cube : public TextureStorage9 } -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h index 791c108462..fb626bc0cf 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -6,11 +6,11 @@ // VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. -#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_ -#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ -#include "libGLESv2/renderer/VertexArrayImpl.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" namespace rx { @@ -33,11 +33,9 @@ class VertexArray9 : public VertexArrayImpl virtual void enableAttribute(size_t idx, bool enabledState) { } private: - DISALLOW_COPY_AND_ASSIGN(VertexArray9); - Renderer9 *mRenderer; }; } -#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp index b90133097c..cb5003997f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -6,13 +6,13 @@ // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/vertexconversion.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/Buffer.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/Buffer.h" namespace rx { @@ -97,9 +97,9 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib { if (buffer) { - BufferD3D *storage = BufferD3D::makeFromBuffer(buffer); + BufferD3D *storage = GetImplAs<BufferD3D>(buffer); ASSERT(storage); - gl::Error error = storage->getData(&input); + error = storage->getData(&input); if (error.isError()) { return error; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h index 9af2b98a6e..f5b110b22b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h @@ -6,10 +6,10 @@ // VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ -#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" namespace rx { @@ -37,8 +37,6 @@ class VertexBuffer9 : public VertexBuffer IDirect3DVertexBuffer9 *getBuffer() const; private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - Renderer9 *mRenderer; IDirect3DVertexBuffer9 *mVertexBuffer; @@ -51,4 +49,4 @@ class VertexBuffer9 : public VertexBuffer } -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp index cefd786f11..f9eded9b50 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -6,11 +6,11 @@ // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. -#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" +#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" namespace rx { @@ -40,7 +40,7 @@ VertexDeclarationCache::~VertexDeclarationCache() } } -gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) +gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw) { *repeatDraw = 1; @@ -155,7 +155,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra element->Type = d3d9VertexInfo.nativeFormat; element->Method = D3DDECLMETHOD_DEFAULT; element->Usage = D3DDECLUSAGE_TEXCOORD; - element->UsageIndex = programBinary->getSemanticIndex(i); + element->UsageIndex = program->getSemanticIndex(i); element++; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h index 9af36e0d7a..fbd673097f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -6,15 +6,16 @@ // VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. -#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ -#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ -#include "libGLESv2/Error.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" namespace gl { class VertexDataManager; +class Program; } namespace rx @@ -26,7 +27,7 @@ class VertexDeclarationCache VertexDeclarationCache(); ~VertexDeclarationCache(); - gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); + gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw); void markStateDirty(); @@ -56,4 +57,4 @@ class VertexDeclarationCache } -#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp index f3acaf7987..9bad5503d9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp @@ -7,12 +7,12 @@ // formatutils9.cpp: Queries for GL image formats and their translations to D3D9 // formats. -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/generatemip.h" -#include "libGLESv2/renderer/loadimage.h" -#include "libGLESv2/renderer/copyimage.h" -#include "libGLESv2/renderer/vertexconversion.h" +#include "libANGLE/renderer/d3d/copyimage.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" +#include "libANGLE/renderer/d3d/generatemip.h" +#include "libANGLE/renderer/d3d/loadimage.h" namespace rx { @@ -57,6 +57,13 @@ D3DFormat::D3DFormat() : pixelBytes(0), blockWidth(0), blockHeight(0), + redBits(0), + greenBits(0), + blueBits(0), + alphaBits(0), + luminanceBits(0), + depthBits(0), + stencilBits(0), internalFormat(GL_NONE), mipGenerationFunction(NULL), colorReadFunction(NULL), @@ -71,13 +78,22 @@ ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) con } static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth, - GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc, + GLuint blockHeight, GLuint redBits, GLuint greenBits, GLuint blueBits, + GLuint alphaBits, GLuint lumBits, GLuint depthBits, GLuint stencilBits, + GLenum internalFormat, MipGenerationFunction mipFunc, ColorReadFunction colorReadFunc) { D3DFormat info; info.pixelBytes = bits / 8; info.blockWidth = blockWidth; info.blockHeight = blockHeight; + info.redBits = redBits; + info.greenBits = greenBits; + info.blueBits = blueBits; + info.alphaBits = alphaBits; + info.luminanceBits = lumBits; + info.depthBits = depthBits; + info.stencilBits = stencilBits; info.internalFormat = internalFormat; info.mipGenerationFunction = mipFunc; info.colorReadFunction = colorReadFunc; @@ -96,35 +112,35 @@ static D3D9FormatInfoMap BuildD3D9FormatInfoMap() { D3D9FormatInfoMap map; - // | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function | - InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>); - InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> ); - InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>); - - InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); + // | D3DFORMAT | S |W |H | R | G | B | A | L | D | S | Internal format | Mip generation function | Color read function | + InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, 0, 0, 0, 0, 8, 0, 0, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, 0, 0, 0, 8, 0, 0, 0, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, 0, 0, 0, 8, 8, 0, 0, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, 5, 6, 5, 0, 0, 0, 0, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, 8, 8, 8, 0, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, 8, 8, 8, 8, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, 16, 0, 0, 0, 0, 0, 0, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, 16, 16, 0, 0, 0, 0, 0, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, 16, 16, 16, 16, 0, 0, 0, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>); + InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, 32, 0, 0, 0, 0, 0, 0, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, 32, 32, 0, 0, 0, 0, 0, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> ); + InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, 32, 32, 32, 32, 0, 0, 0, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>); + + InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, 0, 0, 0, 0, 0, 16, 0, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 0, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, 0, 0, 0, 0, 0, 32, 0, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); return map; } @@ -192,8 +208,8 @@ typedef std::pair<GLenum, TextureFormat> D3D9FormatPair; typedef std::map<GLenum, TextureFormat> D3D9FormatMap; TextureFormat::TextureFormat() - : texFormat(D3DFMT_NULL), - renderFormat(D3DFMT_NULL), + : texFormat(D3DFMT_UNKNOWN), + renderFormat(D3DFMT_UNKNOWN), dataInitializerFunction(NULL), loadFunction(UnreachableLoad) { @@ -544,7 +560,7 @@ const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::Vert static bool initialized = false; static DWORD intializedDeclTypes = 0; static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - if (!initialized) + if (intializedDeclTypes != supportedDeclTypes) { const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] { @@ -576,8 +592,6 @@ const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::Vert intializedDeclTypes = supportedDeclTypes; } - ASSERT(intializedDeclTypes == supportedDeclTypes); - // Pure integer attributes only supported in ES3.0 ASSERT(!vertexFormat.mPureInteger); return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h index f26fe43b36..15e26599c8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h @@ -7,10 +7,13 @@ // formatutils9.h: Queries for GL image formats and their translations to D3D9 // formats. -#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_ -#define LIBGLESV2_RENDERER_FORMATUTILS9_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ -#include "libGLESv2/formatutils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/angletypes.h" + +#include "common/platform.h" #include <map> @@ -32,6 +35,15 @@ struct D3DFormat GLuint blockWidth; GLuint blockHeight; + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + GLuint alphaBits; + GLuint luminanceBits; + + GLuint depthBits; + GLuint stencilBits; + GLenum internalFormat; MipGenerationFunction mipGenerationFunction; @@ -71,4 +83,4 @@ const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); } -#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp index a98b2081f3..c9711ac052 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -7,12 +7,13 @@ // renderer9_utils.cpp: Conversion functions and other utility routines // specific to the D3D9 renderer. -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" #include "common/mathutil.h" #include "common/debug.h" @@ -276,29 +277,41 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3 const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); - } - else + + if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN) { - textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) && - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat)); - } + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } + else + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat)); + } - textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); - textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)) || - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } - textureCaps.sampleCounts.insert(1); - for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN) { - D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); - HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); - if (SUCCEEDED(result)) + if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) && !textureCaps.renderable) { - textureCaps.sampleCounts.insert(i); + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + } + + textureCaps.sampleCounts.insert(1); + for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + { + D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); + + HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); + if (SUCCEEDED(result)) + { + textureCaps.sampleCounts.insert(i); + } } } @@ -378,6 +391,22 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT // Program and shader binary formats (no supported shader binary formats) caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + + // Some (most) hardware only supports single-precision floating-point numbers, + // which can accurately represent integers up to +/-16777216 + caps->vertexHighpInt.setSimulatedInt(24); + caps->vertexMediumpInt.setSimulatedInt(24); + caps->vertexLowpInt.setSimulatedInt(24); + caps->fragmentHighpInt.setSimulatedInt(24); + caps->fragmentMediumpInt.setSimulatedInt(24); + caps->fragmentLowpInt.setSimulatedInt(24); + // WaitSync is ES3-only, set to zero caps->maxServerWaitTimeout = 0; @@ -454,14 +483,23 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT extensions->mapBuffer = false; extensions->mapBufferRange = false; - // ATI cards on XP have problems with non-power-of-two textures. + // textureRG is emulated and not performant. + extensions->textureRG = false; + D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) { + // ATI cards on XP have problems with non-power-of-two textures. extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); + + // Disable depth texture support on AMD cards (See ANGLE issue 839) + if (adapterId.VendorId == VENDOR_ID_AMD) + { + extensions->depthTextures = false; + } } else { @@ -533,9 +571,9 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize *levelOffset = upsampleCount; } -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT) +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT) { - RenderTarget *renderTarget = NULL; + RenderTargetD3D *renderTarget = NULL; gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); if (error.isError()) { @@ -550,6 +588,7 @@ Workarounds GenerateWorkarounds() Workarounds workarounds; workarounds.mrtPerfWorkaround = true; workarounds.setDataFasterThanImageUpload = false; + workarounds.useInstancedPointSpriteEmulation = false; return workarounds; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h index 9760b9735a..3c6a57aee3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h @@ -7,12 +7,12 @@ // renderer9_utils.h: Conversion functions and other utility routines // specific to the D3D9 renderer -#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" namespace gl { @@ -76,11 +76,11 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT); +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT); Workarounds GenerateWorkarounds(); } } -#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps index eb43eb3e7a..dc357d0fa6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps @@ -11,7 +11,7 @@ uniform float4 add : c1; // Passthrough Pixel Shader // Outputs texture 0 sampled at texcoord 0. -float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR +float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR { return tex2D(tex, texcoord.xy); }; @@ -19,7 +19,7 @@ float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR // Luminance Conversion Pixel Shader // Performs a mad operation using the LA data from the texture with mult.xw and add.xw. // Returns data in the form of llla -float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR +float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR { return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; }; @@ -27,7 +27,7 @@ float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR // RGB/A Component Mask Pixel Shader // Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. // Returns data in the form of rgba -float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR +float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR { return tex2D(tex, texcoord.xy) * mult + add; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs index 3bd611ba5d..3a36980b93 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs @@ -17,7 +17,7 @@ uniform float4 halfPixelSize : c0; // Outputs the homogenous position as-is. // Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. // C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. -VS_OUTPUT VS_standard(in float4 position : POSITION) +VS_OUTPUT standardvs(in float4 position : POSITION) { VS_OUTPUT Out; @@ -32,7 +32,7 @@ VS_OUTPUT VS_standard(in float4 position : POSITION) // Outputs the homogenous position as-is. // Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. // C0.XY must be the half-pixel width and height. C0.ZW must be 0. -VS_OUTPUT VS_flipy(in float4 position : POSITION) +VS_OUTPUT flipyvs(in float4 position : POSITION) { VS_OUTPUT Out; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h index 81ba8a0767..32eb376a78 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h @@ -7,8 +7,8 @@ // vertexconversion.h: A library of vertex conversion classes that can be used to build // the FormatConverter objects used by the buffer conversion system. -#ifndef LIBGLESV2_VERTEXCONVERSION_H_ -#define LIBGLESV2_VERTEXCONVERSION_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ #include <limits> #include <cstdint> @@ -194,4 +194,4 @@ struct VertexDataConverter } -#endif // LIBGLESV2_VERTEXCONVERSION_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp new file mode 100644 index 0000000000..8a4d41cbd9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp @@ -0,0 +1,147 @@ +// +// Copyright (c) 2015 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. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D +// formats. + +#include "libANGLE/renderer/d3d/formatutilsD3D.h" + +#include <map> + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/imageformats.h" +#include "libANGLE/renderer/d3d/copyimage.h" + +namespace rx +{ + +typedef std::pair<GLenum, GLenum> FormatTypePair; +typedef std::pair<FormatTypePair, ColorWriteFunction> FormatWriteFunctionPair; +typedef std::map<FormatTypePair, ColorWriteFunction> FormatWriteFunctionMap; + +static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map, GLenum format, GLenum type, + ColorWriteFunction writeFunc) +{ + map->insert(FormatWriteFunctionPair(FormatTypePair(format, type), writeFunc)); +} + +static FormatWriteFunctionMap BuildFormatWriteFunctionMap() +{ + FormatWriteFunctionMap map; + + // | Format | Type | Color write function | + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor<R8G8B8A8S, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor<R4G4B4A4, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor<R5G5B5A1, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor<R32G32B32A32F, GLfloat>); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor<R16G16B16A16F, GLfloat>); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor<R16G16B16A16F, GLfloat>); + + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor<R8G8B8A8S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16A16, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor<R16G16B16A16S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32A32, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor<R32G32B32A32S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLuint> ); + + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor<R8G8B8S, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor<R5G6B5, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor<R11G11B10F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor<R9G9B9E5, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor<R32G32B32F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor<R16G16B16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor<R16G16B16F, GLfloat> ); + + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor<R8G8B8S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor<R16G16B16S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor<R32G32B32S, GLint> ); + + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor<R8G8S, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor<R32G32F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor<R16G16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor<R16G16F, GLfloat> ); + + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor<R8G8S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor<R16G16S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor<R32G32S, GLint> ); + + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor<R8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor<R8S, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor<R32F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor<R16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor<R16F, GLfloat> ); + + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor<R8S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor<R16S, GLint> ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor<R32, GLuint> ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor<R32S, GLint> ); + + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor<L8A8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor<L8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor<A8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor<L32A32F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor<L32F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor<A32F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor<L16A16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor<L16A16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor<L16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor<L16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor<A16F, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor<A16F, GLfloat> ); + + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor<B8G8R8A8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<B4G4R4A4, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<B5G5R5A1, GLfloat> ); + + InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> ); + InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> ); + + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, NULL ); + + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, NULL ); + + InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, NULL ); + + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL ); + + return map; +} + +ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type) +{ + static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap(); + FormatWriteFunctionMap::const_iterator iter = formatTypeMap.find(FormatTypePair(format, type)); + ASSERT(iter != formatTypeMap.end()); + if (iter != formatTypeMap.end()) + { + return iter->second; + } + else + { + return NULL; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h new file mode 100644 index 0000000000..6dd59ca94b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2015 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. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ +#define LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ + +#include "angle_gl.h" + +#include <cstddef> +#include <stdint.h> + +namespace rx +{ + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest); +typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest); +typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest); + +typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +enum VertexConversionType +{ + VERTEX_CONVERT_NONE = 0, + VERTEX_CONVERT_CPU = 1, + VERTEX_CONVERT_GPU = 2, + VERTEX_CONVERT_BOTH = 3 +}; + +ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type); + +} + +#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h index a57b00d444..398ef26b30 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2015 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. // @@ -7,11 +7,11 @@ // generatemip.h: Defines the GenerateMip function, templated on the format // type of the image for which mip levels are being generated. -#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_ -#define LIBGLESV2_RENDERER_GENERATEMIP_H_ +#ifndef LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ +#define LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ -#include "libGLESv2/renderer/imageformats.h" -#include "libGLESv2/angletypes.h" +#include "libANGLE/renderer/d3d/imageformats.h" +#include "libANGLE/angletypes.h" namespace rx { @@ -25,4 +25,4 @@ inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDe #include "generatemip.inl" -#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ +#endif // LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl index 6788a42f03..265783641e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2015 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. // diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h index 2140a9ee72..e0f9a16c1a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2015 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. // @@ -7,8 +7,10 @@ // imageformats.h: Defines image format types with functions for mip generation // and copying. -#ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_ -#define LIBGLESV2_RENDERER_IMAGEFORMATS_H_ +#ifndef LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ +#define LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ + +#include "libANGLE/angletypes.h" #include "common/mathutil.h" @@ -2026,4 +2028,4 @@ struct R11G11B10F } -#endif // LIBGLESV2_RENDERER_IMAGEFORMATS_H_ +#endif // LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp index 1986191a75..172832b3e7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp @@ -1,12 +1,12 @@ // -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2015 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. // // loadimage.cpp: Defines image loading functions. -#include "libGLESv2/renderer/loadimage.h" +#include "libANGLE/renderer/d3d/loadimage.h" namespace rx { @@ -91,9 +91,10 @@ void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); for (size_t x = 0; x < width; x++) { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; + uint8_t sourceVal = source[x]; + dest[4 * x + 0] = sourceVal; + dest[4 * x + 1] = sourceVal; + dest[4 * x + 2] = sourceVal; dest[4 * x + 3] = 0xFF; } } @@ -341,7 +342,7 @@ void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint32_t rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h index bcdff24a66..6967dc868e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h @@ -1,17 +1,17 @@ // -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2013-2015 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. // // loadimage.h: Defines image loading functions -#ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_ -#define LIBGLESV2_RENDERER_LOADIMAGE_H_ +#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ +#define LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ -#include "libGLESv2/angletypes.h" +#include "libANGLE/angletypes.h" -#include <cstdint> +#include <stdint.h> namespace rx { @@ -190,4 +190,4 @@ inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_ #include "loadimage.inl" -#endif // LIBGLESV2_RENDERER_LOADIMAGE_H_ +#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl index abd0a3673c..920e667db1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl @@ -1,5 +1,5 @@ // -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2014-2015 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. // diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp index 159b4c7e9f..c87d35c82b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2015 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. // @@ -8,7 +8,13 @@ // in a separated file for GCC, which can enable SSE usage only per-file, // not for code blocks that use SSE2 explicitly. -#include "libGLESv2/renderer/loadimage.h" +#include "libANGLE/renderer/d3d/loadimage.h" + +#include "common/platform.h" + +#ifdef ANGLE_USE_SSE +#include <emmintrin.h> +#endif namespace rx { @@ -17,12 +23,7 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { -#if defined(_M_ARM) - // Ensure that this function is reported as not implemented for ARM builds because - // the instructions below are not present for that architecture. - UNIMPLEMENTED(); - return; -#else +#if defined(ANGLE_USE_SSE) __m128i zeroWide = _mm_setzero_si128(); for (size_t z = 0; z < depth; z++) @@ -60,6 +61,11 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, } } } +#else + // Ensure that this function is reported as not implemented for ARM builds because + // the instructions below are not present for that architecture. + UNIMPLEMENTED(); + return; #endif } @@ -67,12 +73,7 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { -#if defined(_M_ARM) - // Ensure that this function is reported as not implemented for ARM builds because - // the instructions below are not present for that architecture. - UNIMPLEMENTED(); - return; -#else +#if defined(ANGLE_USE_SSE) __m128i brMask = _mm_set1_epi32(0x00ff00ff); for (size_t z = 0; z < depth; z++) @@ -88,7 +89,7 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++) { uint32_t rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); } for (; x + 3 < width; x += 4) @@ -108,11 +109,17 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, for (; x < width; x++) { uint32_t rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); } } } +#else + // Ensure that this function is reported as not implemented for ARM builds because + // the instructions below are not present for that architecture. + UNIMPLEMENTED(); + return; #endif } } + diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp new file mode 100644 index 0000000000..12ee6a2b93 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp @@ -0,0 +1,503 @@ +// +// Copyright (c) 2015 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. +// + +// validationEGL.cpp: Validation functions for generic EGL entry point parameters + +#include "libANGLE/validationEGL.h" + +#include "libANGLE/Config.h" +#include "libANGLE/Context.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" + +#include <EGL/eglext.h> + +namespace egl +{ + +Error ValidateDisplay(const Display *display) +{ + if (display == EGL_NO_DISPLAY) + { + return Error(EGL_BAD_DISPLAY); + } + + if (!display->isInitialized()) + { + return Error(EGL_NOT_INITIALIZED); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateSurface(const Display *display, Surface *surface) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidSurface(surface)) + { + return Error(EGL_BAD_SURFACE); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateConfig(const Display *display, const Config *config) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidConfig(config)) + { + return Error(EGL_BAD_CONFIG); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateContext(const Display *display, gl::Context *context) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidContext(context)) + { + return Error(EGL_BAD_CONTEXT); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext, + const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, configuration); + if (error.isError()) + { + return error; + } + + // Get the requested client version (default is 1) and check it is 2 or 3. + EGLint clientMajorVersion = 1; + EGLint clientMinorVersion = 0; + EGLint contextFlags = 0; + bool resetNotification = false; + bool robustAccess = false; + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_CONTEXT_CLIENT_VERSION: + clientMajorVersion = value; + break; + + case EGL_CONTEXT_MINOR_VERSION: + clientMinorVersion = value; + break; + + case EGL_CONTEXT_FLAGS_KHR: + contextFlags = value; + break; + + case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: + // Only valid for OpenGL (non-ES) contexts + return Error(EGL_BAD_ATTRIBUTE); + + case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: + if (!display->getExtensions().createContextRobustness) + { + return Error(EGL_BAD_ATTRIBUTE); + } + if (value != EGL_TRUE && value != EGL_FALSE) + { + return Error(EGL_BAD_ATTRIBUTE); + } + robustAccess = (value == EGL_TRUE); + break; + + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR: + static_assert(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR, "EGL extension enums not equal."); + static_assert(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR, "EGL extension enums not equal."); + // same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: + if (!display->getExtensions().createContextRobustness) + { + return Error(EGL_BAD_ATTRIBUTE); + } + if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT) + { + resetNotification = true; + } + else if (value != EGL_NO_RESET_NOTIFICATION_EXT) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if ((clientMajorVersion != 2 && clientMajorVersion != 3) || clientMinorVersion != 0) + { + return Error(EGL_BAD_CONFIG); + } + + if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG)) + { + return Error(EGL_BAD_CONFIG); + } + + // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES + const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | + EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR); + if ((contextFlags & ~validContextFlags) != 0) + { + return Error(EGL_BAD_ATTRIBUTE); + } + + if ((contextFlags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) > 0) + { + robustAccess = true; + } + + if (robustAccess) + { + // Unimplemented + return Error(EGL_BAD_CONFIG); + } + + if (shareContext) + { + // Shared context is invalid or is owned by another display + if (!display->isValidContext(shareContext)) + { + return Error(EGL_BAD_MATCH); + } + + if (shareContext->isResetNotificationEnabled() != resetNotification) + { + return Error(EGL_BAD_MATCH); + } + + if (shareContext->getClientVersion() != clientMajorVersion) + { + return Error(EGL_BAD_CONTEXT); + } + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window, + const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, config); + if (error.isError()) + { + return error; + } + + if (!display->isValidNativeWindow(window)) + { + return Error(EGL_BAD_NATIVE_WINDOW); + } + + const DisplayExtensions &displayExtensions = display->getExtensions(); + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_RENDER_BUFFER: + switch (value) + { + case EGL_BACK_BUFFER: + break; + case EGL_SINGLE_BUFFER: + return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + if (!displayExtensions.postSubBuffer) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_WIDTH: + case EGL_HEIGHT: + if (!displayExtensions.windowFixedSize) + { + return Error(EGL_BAD_ATTRIBUTE); + } + if (value < 0) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + case EGL_FIXED_SIZE_ANGLE: + if (!displayExtensions.windowFixedSize) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_VG_COLORSPACE: + return Error(EGL_BAD_MATCH); + + case EGL_VG_ALPHA_FORMAT: + return Error(EGL_BAD_MATCH); + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if (Display::hasExistingWindowSurface(window)) + { + return Error(EGL_BAD_ALLOC); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, config); + if (error.isError()) + { + return error; + } + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_WIDTH: + case EGL_HEIGHT: + if (value < 0) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + case EGL_LARGEST_PBUFFER: + break; + + case EGL_TEXTURE_FORMAT: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_TEXTURE_TARGET: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_2D: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_MIPMAP_TEXTURE: + break; + + case EGL_VG_COLORSPACE: + break; + + case EGL_VG_ALPHA_FORMAT: + break; + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if (!(config->surfaceType & EGL_PBUFFER_BIT)) + { + return Error(EGL_BAD_MATCH); + } + + const Caps &caps = display->getCaps(); + + EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); + EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); + + if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || + (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) + { + return Error(EGL_BAD_MATCH); + } + + if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) || + (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE)) + { + return Error(EGL_BAD_ATTRIBUTE); + } + + EGLint width = attributes.get(EGL_WIDTH, 0); + EGLint height = attributes.get(EGL_HEIGHT, 0); + if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) + { + return Error(EGL_BAD_MATCH); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer, + Config *config, const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, config); + if (error.isError()) + { + return error; + } + + const DisplayExtensions &displayExtensions = display->getExtensions(); + + switch (buftype) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + if (!displayExtensions.d3dShareHandleClientBuffer) + { + return Error(EGL_BAD_PARAMETER); + } + if (buffer == nullptr) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + default: + return Error(EGL_BAD_PARAMETER); + } + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_WIDTH: + case EGL_HEIGHT: + if (!displayExtensions.d3dShareHandleClientBuffer) + { + return Error(EGL_BAD_PARAMETER); + } + if (value < 0) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + case EGL_TEXTURE_FORMAT: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_TEXTURE_TARGET: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_2D: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_MIPMAP_TEXTURE: + break; + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if (!(config->surfaceType & EGL_PBUFFER_BIT)) + { + return Error(EGL_BAD_MATCH); + } + + EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); + EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); + if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || + (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) + { + return Error(EGL_BAD_MATCH); + } + + if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) || + (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE)) + { + return Error(EGL_BAD_ATTRIBUTE); + } + + if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + { + EGLint width = attributes.get(EGL_WIDTH, 0); + EGLint height = attributes.get(EGL_HEIGHT, 0); + + if (width == 0 || height == 0) + { + return Error(EGL_BAD_ATTRIBUTE); + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check + const Caps &caps = display->getCaps(); + if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) + { + return Error(EGL_BAD_MATCH); + } +#endif + } + + return Error(EGL_SUCCESS); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.h b/src/3rdparty/angle/src/libANGLE/validationEGL.h new file mode 100644 index 0000000000..4daff791fd --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationEGL.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2015 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. +// + +// validationEGL.h: Validation functions for generic EGL entry point parameters + +#ifndef LIBANGLE_VALIDATIONEGL_H_ +#define LIBANGLE_VALIDATIONEGL_H_ + +#include "libANGLE/Error.h" + +#include <EGL/egl.h> + +namespace gl +{ +class Context; +} + +namespace egl +{ + +class AttributeMap; +struct Config; +class Display; +class Surface; + +// Object validation +Error ValidateDisplay(const Display *display); +Error ValidateSurface(const Display *display, Surface *surface); +Error ValidateConfig(const Display *display, const Config *config); +Error ValidateContext(const Display *display, gl::Context *context); + +// Entry point validation +Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext, + const AttributeMap& attributes); + +Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window, + const AttributeMap& attributes); + +Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes); +Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer, + Config *config, const AttributeMap& attributes); + + +} + +#endif // LIBANGLE_VALIDATIONEGL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libANGLE/validationES.cpp index 265f4b4fba..d267cbf2e6 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationES.cpp @@ -6,27 +6,24 @@ // validationES.h: Validation functions for generic OpenGL ES entry point parameters -#include "libGLESv2/validationES.h" -#include "libGLESv2/validationES2.h" -#include "libGLESv2/validationES3.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/renderer/BufferImpl.h" +#include "libANGLE/validationES.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/Context.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Query.h" +#include "libANGLE/Program.h" +#include "libANGLE/Uniform.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/BufferImpl.h" #include "common/mathutil.h" #include "common/utilities.h" -// FIXME(jmadill): remove this when we support buffer data caching -#include "libGLESv2/renderer/d3d/BufferD3D.h" - namespace gl { @@ -95,7 +92,8 @@ bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) bool ValidFramebufferTarget(GLenum target) { - META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER); + static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER, + "ANGLE framebuffer enums must equal the ES3 framebuffer enums."); switch (target) { @@ -212,8 +210,8 @@ bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLs bool ValidQueryType(const Context *context, GLenum queryType) { - META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT); - META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); + static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal."); + static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal."); switch (queryType) { @@ -288,9 +286,8 @@ bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) return true; } -bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, - GLenum internalformat, GLsizei width, GLsizei height, - bool angleExtension) +bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height) { switch (target) { @@ -316,8 +313,7 @@ bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains - // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the - // internal format must be sized and not an integer format if samples is greater than zero. + // only sized internal formats. const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); if (formatInfo.pixelBytes == 0) { @@ -325,55 +321,47 @@ bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, return false; } - if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) + if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_VALUE)); return false; } - if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize) + GLuint handle = context->getState().getRenderbufferId(); + if (handle == 0) { - context->recordError(Error(GL_INVALID_VALUE)); + context->recordError(Error(GL_INVALID_OPERATION)); return false; } - // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal - // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2) - // states that samples must be less than or equal to the maximum samples for the specified - // internal format. - if (angleExtension) - { - ASSERT(context->getExtensions().framebufferMultisample); - if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } + return true; +} - // Check if this specific format supports enough samples - if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) - { - context->recordError(Error(GL_OUT_OF_MEMORY)); - return false; - } - } - else +bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height) +{ + ASSERT(samples == 0 || context->getExtensions().framebufferMultisample); + + // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal + // to MAX_SAMPLES_ANGLE (Context::getExtensions().maxSamples) otherwise GL_INVALID_VALUE is + // generated. + if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples) { - if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - GLuint handle = context->getState().getRenderbufferId(); - if (handle == 0) + // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create + // the specified storage. This is different than ES 3.0 in which a sample number higher + // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_OUT_OF_MEMORY)); return false; } - return true; + return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height); } bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, @@ -507,13 +495,13 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint return false; } - if (!readFramebuffer->completeness(context->getData())) + if (!readFramebuffer->checkStatus(context->getData())) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (!drawFramebuffer->completeness(context->getData())) + if (!drawFramebuffer->checkStatus(context->getData())) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; @@ -534,14 +522,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (readColorBuffer && drawColorBuffer) { - GLenum readInternalFormat = readColorBuffer->getActualFormat(); + GLenum readInternalFormat = readColorBuffer->getInternalFormat(); const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) + for (GLuint i = 0; i < context->getCaps().maxColorAttachments; i++) { if (drawFramebuffer->isEnabledColorAttachment(i)) { - GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat(); + GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getInternalFormat(); const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat); // The GL ES 3.0.2 spec (pg 193) states that: @@ -583,21 +571,26 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (fromAngleExtension) { - const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); - if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER) + FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer(); + if (!readColorAttachment || + (!(readColorAttachment->type() == GL_TEXTURE && readColorAttachment->getTextureImageIndex()->type == GL_TEXTURE_2D) && + readColorAttachment->type() != GL_RENDERBUFFER && + readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + for (GLuint colorAttachment = 0; colorAttachment < context->getCaps().maxColorAttachments; ++colorAttachment) { if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) { FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); ASSERT(attachment); - if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER) + if (!(attachment->type() == GL_TEXTURE && attachment->getTextureImageIndex()->type == GL_TEXTURE_2D) && + attachment->type() != GL_RENDERBUFFER && + attachment->type() != GL_FRAMEBUFFER_DEFAULT) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -625,77 +618,44 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint } } - if (mask & GL_DEPTH_BUFFER_BIT) + GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT}; + GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + for (size_t i = 0; i < 2; i++) { - gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer(); - gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer(); - - if (readDepthBuffer && drawDepthBuffer) + if (mask & masks[i]) { - if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } + gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]); - if (readDepthBuffer->getSamples() > 0 && !sameBounds) + if (readBuffer && drawBuffer) { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (fromAngleExtension) - { - if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer, - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + if (readBuffer->getInternalFormat() != drawBuffer->getInternalFormat()) { - ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + context->recordError(Error(GL_INVALID_OPERATION)); return false; } - if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0) + if (readBuffer->getSamples() > 0 && !sameBounds) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - } - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) - { - gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer(); - gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); - - if (readStencilBuffer && drawStencilBuffer) - { - if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - if (readStencilBuffer->getSamples() > 0 && !sameBounds) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (fromAngleExtension) - { - if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer, - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + if (fromAngleExtension) { - ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted - return false; - } + if (IsPartialBlit(context, readBuffer, drawBuffer, + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + { + ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); + context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + return false; + } - if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; + if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } } } @@ -720,7 +680,8 @@ bool ValidateGetVertexAttribParameters(Context *context, GLenum pname) case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses // the same constant. - META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); + static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE, + "ANGLE extension enums not equal to GL enums."); return true; case GL_VERTEX_ATTRIB_ARRAY_INTEGER: @@ -931,7 +892,7 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; @@ -944,17 +905,18 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize return false; } - if (!framebuffer->getReadColorbuffer()) + const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer(); + if (!readBuffer) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - GLenum currentInternalFormat, currentFormat, currentType; + GLenum currentFormat = framebuffer->getImplementationColorReadFormat(); + GLenum currentType = framebuffer->getImplementationColorReadType(); + GLenum currentInternalFormat = readBuffer->getInternalFormat(); GLuint clientVersion = context->getClientVersion(); - context->getCurrentReadFormatType(¤tInternalFormat, ¤tFormat, ¤tType); - bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) : ValidES3ReadFormatType(context, currentInternalFormat, format, type); @@ -967,7 +929,7 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment()); + GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), 0); // sized query sanity check if (bufSize) { @@ -1064,8 +1026,8 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform return false; } - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - if (!programBinary) + gl::Program *program = context->getState().getProgram(); + if (!program) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1077,13 +1039,13 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform return false; } - if (!programBinary->isValidUniformLocation(location)) + if (!program->isValidUniformLocation(location)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - LinkedUniform *uniform = programBinary->getUniformByLocation(location); + LinkedUniform *uniform = program->getUniformByLocation(location); // attempting to write an array to a non-array uniform is an INVALID_OPERATION if (uniform->elementCount() == 1 && count > 1) @@ -1112,7 +1074,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G } GLenum targetBoolType = VariableBoolVectorType(uniformType); - bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT); + bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT); if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1163,11 +1125,13 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, return false; } + const Caps &caps = context->getCaps(); + if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) { unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0); - if (colorAttachment >= context->getCaps().maxDrawBuffers) + if (colorAttachment >= caps.maxDrawBuffers) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1180,7 +1144,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, case GL_TEXTURE_BINDING_CUBE_MAP: case GL_TEXTURE_BINDING_3D: case GL_TEXTURE_BINDING_2D_ARRAY: - if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits) + if (context->getState().getActiveSampler() >= caps.maxCombinedTextureImageUnits) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1192,7 +1156,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, { Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1256,7 +1220,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi } gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; @@ -1270,28 +1234,11 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi const gl::Caps &caps = context->getCaps(); - gl::Texture *texture = NULL; - GLenum textureInternalFormat = GL_NONE; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - GLint textureLevelDepth = 0; GLuint maxDimension = 0; - switch (target) { case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - if (texture2d) - { - textureInternalFormat = texture2d->getInternalFormat(level); - textureLevelWidth = texture2d->getWidth(level); - textureLevelHeight = texture2d->getHeight(level); - textureLevelDepth = 1; - texture = texture2d; - maxDimension = caps.max2DTextureSize; - } - } + maxDimension = caps.max2DTextureSize; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -1300,48 +1247,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - if (textureCube) - { - textureInternalFormat = textureCube->getInternalFormat(target, level); - textureLevelWidth = textureCube->getWidth(target, level); - textureLevelHeight = textureCube->getHeight(target, level); - textureLevelDepth = 1; - texture = textureCube; - maxDimension = caps.maxCubeMapTextureSize; - } - } + maxDimension = caps.maxCubeMapTextureSize; break; case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture2dArray = context->getTexture2DArray(); - if (texture2dArray) - { - textureInternalFormat = texture2dArray->getInternalFormat(level); - textureLevelWidth = texture2dArray->getWidth(level); - textureLevelHeight = texture2dArray->getHeight(level); - textureLevelDepth = texture2dArray->getLayers(level); - texture = texture2dArray; - maxDimension = caps.max2DTextureSize; - } - } + maxDimension = caps.max2DTextureSize; break; case GL_TEXTURE_3D: - { - gl::Texture3D *texture3d = context->getTexture3D(); - if (texture3d) - { - textureInternalFormat = texture3d->getInternalFormat(level); - textureLevelWidth = texture3d->getWidth(level); - textureLevelHeight = texture3d->getHeight(level); - textureLevelDepth = texture3d->getDepth(level); - texture = texture3d; - maxDimension = caps.max3DTextureSize; - } - } + maxDimension = caps.max3DTextureSize; break; default: @@ -1349,6 +1263,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi return false; } + gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); if (!texture) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1369,21 +1284,17 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi return false; } - if (formatInfo.compressed) + if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height)) { - if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) || - ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (isSubImage) { - if (xoffset + width > textureLevelWidth || - yoffset + height > textureLevelHeight || - zoffset >= textureLevelDepth) + if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) || + static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) || + static_cast<size_t>(zoffset) >= texture->getDepth(target, level)) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -1391,7 +1302,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi } else { - if (IsCubemapTextureTarget(target) && width != height) + if (IsCubeMapTextureTarget(target) && width != height) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -1411,7 +1322,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi } } - *textureFormatOut = textureInternalFormat; + *textureFormatOut = texture->getInternalFormat(target, level); return true; } @@ -1461,20 +1372,20 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz } const gl::Framebuffer *fbo = state.getDrawFramebuffer(); - if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (state.getCurrentProgramId() == 0) + gl::Program *program = state.getProgram(); + if (!program) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); - if (!programBinary->validateSamplers(NULL, context->getCaps())) + if (!program->validateSamplers(NULL, context->getCaps())) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1485,7 +1396,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); - bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1); + bool attribActive = (program->getSemanticIndex(attributeIndex) != -1); if (attribActive && attrib.enabled) { gl::Buffer *buffer = attrib.buffer.get(); @@ -1525,6 +1436,36 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz } } + // Uniform buffer validation + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) + { + const gl::UniformBlock *uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); + GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex); + const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding); + + if (!uniformBuffer) + { + // undefined behaviour + context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.")); + return false; + } + + size_t uniformBufferSize = state.getIndexedUniformBufferSize(blockBinding); + + if (uniformBufferSize == 0) + { + // Bind the whole buffer. + uniformBufferSize = uniformBuffer->getSize(); + } + + if (uniformBufferSize < uniformBlock->dataSize) + { + // undefined behaviour + context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.")); + return false; + } + } + // No-op if zero count return (count > 0); } @@ -1579,13 +1520,13 @@ static bool ValidateDrawInstancedANGLE(Context *context) // Verify there is at least one active attribute with a divisor of zero const gl::State& state = context->getState(); - gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); + gl::Program *program = state.getProgram(); const VertexArray *vao = state.getVertexArray(); for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); - bool active = (programBinary->getSemanticIndex(attributeIndex) != -1); + bool active = (program->getSemanticIndex(attributeIndex) != -1); if (active && attrib.divisor == 0) { return true; @@ -1646,7 +1587,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t } const gl::VertexArray *vao = state.getVertexArray(); - const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); if (!indices && !elementArrayBuffer) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1688,12 +1629,11 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t if (elementArrayBuffer) { uintptr_t offset = reinterpret_cast<uintptr_t>(indices); - if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) + if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut)) { - // FIXME(jmadill): Use buffer data caching instead of the D3D back-end - rx::BufferD3D *bufferD3D = rx::BufferD3D::makeBufferD3D(elementArrayBuffer->getImplementation()); + rx::BufferImpl *bufferImpl = elementArrayBuffer->getImplementation(); const uint8_t *dataPointer = NULL; - Error error = bufferD3D->getData(&dataPointer); + Error error = bufferImpl->getData(&dataPointer); if (error.isError()) { context->recordError(error); @@ -1702,6 +1642,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t const uint8_t *offsetPointer = dataPointer + offset; *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); + elementArrayBuffer->getIndexRangeCache()->addRange(type, offset, count, *indexRangeOut); } } else @@ -1827,12 +1768,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach context->recordError(Error(GL_INVALID_OPERATION)); return false; } - gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex); - if (tex2d->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } } break; @@ -1853,12 +1788,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach context->recordError(Error(GL_INVALID_OPERATION)); return false; } - gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex); - if (texcube->isCompressed(textarget, level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } } break; @@ -1866,6 +1795,13 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach context->recordError(Error(GL_INVALID_ENUM)); return false; } + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level)); + if (internalFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } return true; @@ -1892,14 +1828,7 @@ bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) return false; } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!programBinary->isValidUniformLocation(location)) + if (!programObject->isValidUniformLocation(location)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1927,10 +1856,9 @@ static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint loca gl::Program *programObject = context->getProgram(program); ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); // sized queries -- ensure the provided buffer is large enough - LinkedUniform *uniform = programBinary->getUniformByLocation(location); + LinkedUniform *uniform = programObject->getUniformByLocation(location); size_t requiredBytes = VariableExternalSize(uniform->type); if (static_cast<size_t>(bufSize) < requiredBytes) { diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.h b/src/3rdparty/angle/src/libANGLE/validationES.h index 1fdb633cb6..b0ccd8eecc 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES.h +++ b/src/3rdparty/angle/src/libANGLE/validationES.h @@ -6,8 +6,8 @@ // validationES.h: Validation functions for generic OpenGL ES entry point parameters -#ifndef LIBGLESV2_VALIDATION_ES_H -#define LIBGLESV2_VALIDATION_ES_H +#ifndef LIBANGLE_VALIDATION_ES_H_ +#define LIBANGLE_VALIDATION_ES_H_ #include "common/mathutil.h" @@ -32,9 +32,11 @@ bool ValidQueryType(const Context *context, GLenum queryType); bool ValidProgram(Context *context, GLuint id); bool ValidateAttachmentTarget(Context *context, GLenum attachment); -bool ValidateRenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, - GLenum internalformat, GLsizei width, GLsizei height, - bool angleExtension); +bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height); +bool ValidateRenderbufferStorageParametersANGLE(Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height); + bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); @@ -49,7 +51,7 @@ bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param); bool ValidateSamplerObjectParameter(Context *context, GLenum pname); bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); + GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); bool ValidateEndQuery(Context *context, GLenum target); @@ -61,8 +63,8 @@ bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); bool ValidateCopyTexImageParametersBase(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border, GLenum *textureInternalFormatOut); + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *textureInternalFormatOut); bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); @@ -79,7 +81,7 @@ bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei c bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, GLuint texture, GLint level); bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level); + GLenum textarget, GLuint texture, GLint level); bool ValidateGetUniformBase(Context *context, GLuint program, GLint location); bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params); @@ -89,4 +91,4 @@ bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, } -#endif // LIBGLESV2_VALIDATION_ES_H +#endif // LIBANGLE_VALIDATION_ES_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp index f950454df0..9eece1b54a 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp @@ -6,15 +6,14 @@ // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters -#include "libGLESv2/validationES2.h" -#include "libGLESv2/validationES.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/FramebufferAttachment.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES.h" +#include "libANGLE/Context.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/FramebufferAttachment.h" #include "common/mathutil.h" #include "common/utilities.h" @@ -22,227 +21,118 @@ namespace gl { -static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, - gl::Texture2D *texture) +bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid *pixels) { - if (!texture) + if (!ValidTexture2DDestinationTarget(context, target)) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_ENUM)); return false; } - if (compressed != texture->isCompressed(level)) + if (!ValidImageSize(context, target, level, width, height, 1)) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_VALUE)); return false; } - if (format != GL_NONE) - { - if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (compressed) - { - if ((width % 4 != 0 && width != texture->getWidth(level)) || - (height % 4 != 0 && height != texture->getHeight(level))) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (xoffset + width > texture->getWidth(level) || - yoffset + height > texture->getHeight(level)) + if (level < 0 || xoffset < 0 || + std::numeric_limits<GLsizei>::max() - xoffset < width || + std::numeric_limits<GLsizei>::max() - yoffset < height) { context->recordError(Error(GL_INVALID_VALUE)); return false; } - return true; -} - -static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type, - gl::TextureCubeMap *texture) -{ - if (!texture) + if (!isSubImage && !isCompressed && internalformat != format) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - if (compressed != texture->isCompressed(target, level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } + const gl::Caps &caps = context->getCaps(); - if (format != GL_NONE) + if (target == GL_TEXTURE_2D) { - if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level)) + if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || + static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_VALUE)); return false; } } - - if (compressed) + else if (IsCubeMapTextureTarget(target)) { - if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || - (height % 4 != 0 && height != texture->getHeight(target, 0))) + if (!isSubImage && width != height) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_VALUE)); return false; } - } - if (xoffset + width > texture->getWidth(target, level) || - yoffset + height > texture->getHeight(target, level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; + if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) || + static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } } - - return true; -} - -bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - if (!ValidTexture2DDestinationTarget(context, target)) + else { context->recordError(Error(GL_INVALID_ENUM)); return false; } - if (!ValidImageSize(context, target, level, width, height, 1)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (level < 0 || xoffset < 0 || - std::numeric_limits<GLsizei>::max() - xoffset < width || - std::numeric_limits<GLsizei>::max() - yoffset < height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!isSubImage && !isCompressed && internalformat != format) + gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + if (!texture) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - const gl::Caps &caps = context->getCaps(); - - gl::Texture *texture = NULL; - bool textureCompressed = false; - GLenum textureInternalFormat = GL_NONE; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - switch (target) + if (isSubImage) { - case GL_TEXTURE_2D: + if (format != GL_NONE) { - if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || - static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2D *tex2d = context->getTexture2D(); - if (tex2d) - { - textureCompressed = tex2d->isCompressed(level); - textureInternalFormat = tex2d->getInternalFormat(level); - textureLevelWidth = tex2d->getWidth(level); - textureLevelHeight = tex2d->getHeight(level); - texture = tex2d; - } - - if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset, - level, format, type, tex2d)) + if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level)) { + context->recordError(Error(GL_INVALID_OPERATION)); return false; } - - texture = tex2d; } - break; - 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: + if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) || + static_cast<size_t>(yoffset + height) > texture->getHeight(target, level)) { - if (!isSubImage && width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) || - static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::TextureCubeMap *texCube = context->getTextureCubeMap(); - if (texCube) - { - textureCompressed = texCube->isCompressed(target, level); - textureInternalFormat = texCube->getInternalFormat(target, level); - textureLevelWidth = texCube->getWidth(target, level); - textureLevelHeight = texCube->getHeight(target, level); - texture = texCube; - } - - if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset, - target, level, format, type, texCube)) - { - return false; - } + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; } - - if (!texture) + else { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; + if (texture->isImmutable()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } - if (!isSubImage && texture->isImmutable()) + // Verify zero border + if (border != 0) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_VALUE)); return false; } - // Verify zero border - if (border != 0) + GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat; + const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat); + + if (isCompressed != actualFormatInfo.compressed) { - context->recordError(Error(GL_INVALID_VALUE)); + context->recordError(Error(GL_INVALID_OPERATION)); return false; } - GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; if (isCompressed) { if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) @@ -521,7 +411,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); - GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format; + const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat); + GLenum textureFormat = internalFormatInfo.format; // [OpenGL ES 2.0.24] table 3.9 if (isSubImage) @@ -558,7 +449,11 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_R32F && + colorbufferFormat != GL_RG32F && + colorbufferFormat != GL_RGB32F && + colorbufferFormat != GL_RGBA32F) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -570,7 +465,10 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_RG32F && + colorbufferFormat != GL_RGB32F && + colorbufferFormat != GL_RGBA32F) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -581,7 +479,9 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_RGB32F && + colorbufferFormat != GL_RGBA32F) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -591,7 +491,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le case GL_RGBA: if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_RGBA32F) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -611,6 +512,13 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le context->recordError(Error(GL_INVALID_OPERATION)); return false; } + + if (internalFormatInfo.type == GL_FLOAT && + !context->getExtensions().textureFloat) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } else { @@ -621,7 +529,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -635,7 +544,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -649,7 +559,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -662,7 +573,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -674,7 +586,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -685,7 +598,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -903,19 +817,7 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le break; } - gl::Texture *texture = NULL; - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: - UNREACHABLE(); - } - + gl::Texture *texture = context->getTargetTexture(target); if (!texture || texture->id() == 0) { context->recordError(Error(GL_INVALID_OPERATION)); diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.h b/src/3rdparty/angle/src/libANGLE/validationES2.h index 53a0b630ea..b9c1fd3bc4 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES2.h +++ b/src/3rdparty/angle/src/libANGLE/validationES2.h @@ -6,8 +6,8 @@ // validationES2.h: Validation functions for OpenGL ES 2.0 entry point parameters -#ifndef LIBGLESV2_VALIDATION_ES2_H -#define LIBGLESV2_VALIDATION_ES2_H +#ifndef LIBANGLE_VALIDATION_ES2_H_ +#define LIBANGLE_VALIDATION_ES2_H_ #include <GLES2/gl2.h> @@ -25,10 +25,10 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le GLint border); bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height); + GLsizei width, GLsizei height); bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type); } -#endif // LIBGLESV2_VALIDATION_ES2_H +#endif // LIBANGLE_VALIDATION_ES2_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libANGLE/validationES3.cpp index 2d3a039e13..e141bb6ece 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationES3.cpp @@ -6,17 +6,17 @@ // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters -#include "libGLESv2/validationES3.h" -#include "libGLESv2/validationES.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/FramebufferAttachment.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/validationES.h" +#include "libANGLE/Context.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/FramebufferAttachment.h" #include "common/mathutil.h" +#include "common/utilities.h" namespace gl { @@ -311,33 +311,14 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, const gl::Caps &caps = context->getCaps(); - gl::Texture *texture = NULL; - bool textureCompressed = false; - GLenum textureInternalFormat = GL_NONE; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - GLint textureLevelDepth = 0; switch (target) { case GL_TEXTURE_2D: + if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || + static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) { - if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || - static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2D *texture2d = context->getTexture2D(); - if (texture2d) - { - textureCompressed = texture2d->isCompressed(level); - textureInternalFormat = texture2d->getInternalFormat(level); - textureLevelWidth = texture2d->getWidth(level); - textureLevelHeight = texture2d->getHeight(level); - textureLevelDepth = 1; - texture = texture2d; - } + context->recordError(Error(GL_INVALID_VALUE)); + return false; } break; @@ -347,83 +328,45 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (!isSubImage && width != height) { - if (!isSubImage && width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - if (textureCube) - { - textureCompressed = textureCube->isCompressed(target, level); - textureInternalFormat = textureCube->getInternalFormat(target, level); - textureLevelWidth = textureCube->getWidth(target, level); - textureLevelHeight = textureCube->getHeight(target, level); - textureLevelDepth = 1; - texture = textureCube; - } + if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; } break; case GL_TEXTURE_3D: + if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) || + static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) || + static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level)) { - if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) || - static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) || - static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture3D *texture3d = context->getTexture3D(); - if (texture3d) - { - textureCompressed = texture3d->isCompressed(level); - textureInternalFormat = texture3d->getInternalFormat(level); - textureLevelWidth = texture3d->getWidth(level); - textureLevelHeight = texture3d->getHeight(level); - textureLevelDepth = texture3d->getDepth(level); - texture = texture3d; - } + context->recordError(Error(GL_INVALID_VALUE)); + return false; } break; - case GL_TEXTURE_2D_ARRAY: - { - if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || - static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) || - static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2DArray *texture2darray = context->getTexture2DArray(); - if (texture2darray) - { - textureCompressed = texture2darray->isCompressed(level); - textureInternalFormat = texture2darray->getInternalFormat(level); - textureLevelWidth = texture2darray->getWidth(level); - textureLevelHeight = texture2darray->getHeight(level); - textureLevelDepth = texture2darray->getLayers(level); - texture = texture2darray; - } - } - break; + case GL_TEXTURE_2D_ARRAY: + if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || + static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) || + static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; default: context->recordError(Error(GL_INVALID_ENUM)); return false; } + gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); if (!texture) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -437,7 +380,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, } // Validate texture formats - GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; + GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat; const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat); if (isCompressed) { @@ -476,22 +419,12 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, // Validate sub image parameters if (isSubImage) { - if (isCompressed != textureCompressed) + if (isCompressed != actualFormatInfo.compressed) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - if (isCompressed) - { - if ((width % 4 != 0 && width != textureLevelWidth) || - (height % 4 != 0 && height != textureLevelHeight)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - if (width == 0 || height == 0 || depth == 0) { return false; @@ -511,9 +444,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, return false; } - if (xoffset + width > textureLevelWidth || - yoffset + height > textureLevelHeight || - zoffset + depth > textureLevelDepth) + if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) || + static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) || + static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level)) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -798,8 +731,8 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen { // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format // texture. We can use the same table we use when creating textures to get its effective sized format. - const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type); - sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat); + GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type); + sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat); } } else @@ -876,7 +809,7 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; @@ -932,13 +865,10 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le const gl::Caps &caps = context->getCaps(); - gl::Texture *texture = NULL; switch (target) { case GL_TEXTURE_2D: { - texture = context->getTexture2D(); - if (static_cast<GLuint>(width) > caps.max2DTextureSize || static_cast<GLuint>(height) > caps.max2DTextureSize) { @@ -950,8 +880,6 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le case GL_TEXTURE_CUBE_MAP: { - texture = context->getTextureCubeMap(); - if (width != height) { context->recordError(Error(GL_INVALID_VALUE)); @@ -968,8 +896,6 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le case GL_TEXTURE_3D: { - texture = context->getTexture3D(); - if (static_cast<GLuint>(width) > caps.max3DTextureSize || static_cast<GLuint>(height) > caps.max3DTextureSize || static_cast<GLuint>(depth) > caps.max3DTextureSize) @@ -982,8 +908,6 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le case GL_TEXTURE_2D_ARRAY: { - texture = context->getTexture2DArray(); - if (static_cast<GLuint>(width) > caps.max2DTextureSize || static_cast<GLuint>(height) > caps.max2DTextureSize || static_cast<GLuint>(depth) > caps.maxArrayTextureLayers) @@ -999,6 +923,7 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le return false; } + gl::Texture *texture = context->getTargetTexture(target); if (!texture || texture->id() == 0) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1068,13 +993,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att context->recordError(Error(GL_INVALID_VALUE)); return false; } - - gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex); - if (texArray->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } } break; @@ -1091,13 +1009,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att context->recordError(Error(GL_INVALID_VALUE)); return false; } - - gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex); - if (tex3d->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } } break; @@ -1105,6 +1016,13 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att context->recordError(Error(GL_INVALID_OPERATION)); return false; } + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level)); + if (internalFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } return true; @@ -1187,6 +1105,33 @@ bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum form return true; } +bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height) +{ + if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height)) + { + return false; + } + + //The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer format if samples is greater than zero. + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY. + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + return true; +} + bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, const GLenum* attachments) { @@ -1263,7 +1208,7 @@ bool ValidateClearBuffer(Context *context) } const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); - if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; @@ -1283,4 +1228,55 @@ bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLu return ValidateGetUniformBase(context, program, location); } +bool ValidateReadBuffer(Context *context, GLenum src) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + Framebuffer *readFBO = context->getState().getReadFramebuffer(); + + if (readFBO == nullptr) + { + context->recordError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer.")); + return false; + } + + if (src == GL_NONE) + { + return true; + } + + if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT15)) + { + context->recordError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer")); + return false; + } + + if (readFBO->id() == 0) + { + if (src != GL_BACK) + { + const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer."; + context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg)); + return false; + } + } + else + { + GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0); + + if (drawBuffer >= context->getCaps().maxDrawBuffers) + { + const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS."; + context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg)); + return false; + } + } + + return true; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.h b/src/3rdparty/angle/src/libANGLE/validationES3.h index cafacca601..517cb5d27f 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.h +++ b/src/3rdparty/angle/src/libANGLE/validationES3.h @@ -6,8 +6,8 @@ // validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters -#ifndef LIBGLESV2_VALIDATION_ES3_H -#define LIBGLESV2_VALIDATION_ES3_H +#ifndef LIBANGLE_VALIDATION_ES3_H_ +#define LIBANGLE_VALIDATION_ES3_H_ #include <GLES3/gl3.h> @@ -32,6 +32,9 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type); +bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height); + bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, const GLenum* attachments); @@ -39,6 +42,8 @@ bool ValidateClearBuffer(Context *context); bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); +bool ValidateReadBuffer(Context *context, GLenum mode); + } -#endif // LIBGLESV2_VALIDATION_ES3_H +#endif // LIBANGLE_VALIDATION_ES3_H_ diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp deleted file mode 100644 index fdc41a95f0..0000000000 --- a/src/3rdparty/angle/src/libEGL/Config.cpp +++ /dev/null @@ -1,353 +0,0 @@ -// -// Copyright (c) 2002-2010 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. -// - -// Config.cpp: Implements the egl::Config class, describing the format, type -// and size for an egl::Surface. Implements EGLConfig and related functionality. -// [EGL 1.4] section 3.4 page 15. - -#include "libEGL/Config.h" - -#include <algorithm> -#include <vector> - -#include "angle_gl.h" -#include <EGL/eglext.h> - -#include "common/debug.h" - -using namespace std; - -namespace egl -{ -Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight) - : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample) -{ - mBindToTextureRGB = EGL_FALSE; - mBindToTextureRGBA = EGL_FALSE; - switch (desc.renderTargetFormat) - { - case GL_RGB5_A1: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 5; - mBlueSize = 5; - mAlphaSize = 1; - break; - case GL_BGR5_A1_ANGLEX: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 5; - mBlueSize = 5; - mAlphaSize = 1; - break; - case GL_RGBA8_OES: - mBufferSize = 32; - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - mAlphaSize = 8; - mBindToTextureRGBA = true; - break; - case GL_RGB565: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 6; - mBlueSize = 5; - mAlphaSize = 0; - break; - case GL_RGB8_OES: - mBufferSize = 32; - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - mAlphaSize = 0; - mBindToTextureRGB = true; - break; - case GL_BGRA8_EXT: - mBufferSize = 32; - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - mAlphaSize = 8; - mBindToTextureRGBA = true; - break; - default: - UNREACHABLE(); // Other formats should not be valid - } - - mLuminanceSize = 0; - mAlphaMaskSize = 0; - mColorBufferType = EGL_RGB_BUFFER; - mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG; - mConfigID = 0; - mConformant = EGL_OPENGL_ES2_BIT; - - switch (desc.depthStencilFormat) - { - case GL_NONE: - mDepthSize = 0; - mStencilSize = 0; - break; - case GL_DEPTH_COMPONENT32_OES: - mDepthSize = 32; - mStencilSize = 0; - break; - case GL_DEPTH24_STENCIL8_OES: - mDepthSize = 24; - mStencilSize = 8; - break; - case GL_DEPTH_COMPONENT24_OES: - mDepthSize = 24; - mStencilSize = 0; - break; - case GL_DEPTH_COMPONENT16: - mDepthSize = 16; - mStencilSize = 0; - break; - default: - UNREACHABLE(); - } - - mLevel = 0; - mMatchNativePixmap = EGL_NONE; - mMaxPBufferWidth = texWidth; - mMaxPBufferHeight = texHeight; - mMaxPBufferPixels = texWidth*texHeight; - mMaxSwapInterval = maxInterval; - mMinSwapInterval = minInterval; - mNativeRenderable = EGL_FALSE; - mNativeVisualID = 0; - mNativeVisualType = 0; - mRenderableType = EGL_OPENGL_ES2_BIT; - mSampleBuffers = desc.multiSample ? 1 : 0; - mSamples = desc.multiSample; - mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; - mTransparentType = EGL_NONE; - mTransparentRedValue = 0; - mTransparentGreenValue = 0; - mTransparentBlueValue = 0; - - if (desc.es3Capable) - { - mRenderableType |= EGL_OPENGL_ES3_BIT_KHR; - mConformant |= EGL_OPENGL_ES3_BIT_KHR; - } -} - -EGLConfig Config::getHandle() const -{ - return (EGLConfig)(size_t)mConfigID; -} - -SortConfig::SortConfig(const EGLint *attribList) - : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false) -{ - scanForWantedComponents(attribList); -} - -void SortConfig::scanForWantedComponents(const EGLint *attribList) -{ - // [EGL] section 3.4.1 page 24 - // Sorting rule #3: by larger total number of color bits, not considering - // components that are 0 or don't-care. - for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) - { - if (attr[1] != 0 && attr[1] != EGL_DONT_CARE) - { - switch (attr[0]) - { - case EGL_RED_SIZE: mWantRed = true; break; - case EGL_GREEN_SIZE: mWantGreen = true; break; - case EGL_BLUE_SIZE: mWantBlue = true; break; - case EGL_ALPHA_SIZE: mWantAlpha = true; break; - case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; - } - } - } -} - -EGLint SortConfig::wantedComponentsSize(const Config &config) const -{ - EGLint total = 0; - - if (mWantRed) total += config.mRedSize; - if (mWantGreen) total += config.mGreenSize; - if (mWantBlue) total += config.mBlueSize; - if (mWantAlpha) total += config.mAlphaSize; - if (mWantLuminance) total += config.mLuminanceSize; - - return total; -} - -bool SortConfig::operator()(const Config *x, const Config *y) const -{ - return (*this)(*x, *y); -} - -bool SortConfig::operator()(const Config &x, const Config &y) const -{ - #define SORT(attribute) \ - if (x.attribute != y.attribute) \ - { \ - return x.attribute < y.attribute; \ - } - - META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); - SORT(mConfigCaveat); - - META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); - SORT(mColorBufferType); - - // By larger total number of color bits, only considering those that are requested to be > 0. - EGLint xComponentsSize = wantedComponentsSize(x); - EGLint yComponentsSize = wantedComponentsSize(y); - if (xComponentsSize != yComponentsSize) - { - return xComponentsSize > yComponentsSize; - } - - SORT(mBufferSize); - SORT(mSampleBuffers); - SORT(mSamples); - SORT(mDepthSize); - SORT(mStencilSize); - SORT(mAlphaMaskSize); - SORT(mNativeVisualType); - SORT(mConfigID); - - #undef SORT - - return false; -} - -// We'd like to use SortConfig to also eliminate duplicate configs. -// This works as long as we never have two configs with different per-RGB-component layouts, -// but the same total. -// 5551 and 565 are different because R+G+B is different. -// 5551 and 555 are different because bufferSize is different. -const EGLint ConfigSet::mSortAttribs[] = -{ - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_LUMINANCE_SIZE, 1, - // BUT NOT ALPHA - EGL_NONE -}; - -ConfigSet::ConfigSet() - : mSet(SortConfig(mSortAttribs)) -{ -} - -void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight) -{ - Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight); - mSet.insert(config); -} - -size_t ConfigSet::size() const -{ - return mSet.size(); -} - -bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) -{ - vector<const Config*> passed; - passed.reserve(mSet.size()); - - for (Iterator config = mSet.begin(); config != mSet.end(); config++) - { - bool match = true; - const EGLint *attribute = attribList; - - while (attribute[0] != EGL_NONE) - { - switch (attribute[0]) - { - case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; - case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; - case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; - case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; - case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; - case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; - case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; - case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break; - case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; - case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; - case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break; - case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; - case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; - case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; - case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; - case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break; - case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; - case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; - case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; - case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break; - case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break; - case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; - case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; - case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; - case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; - case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break; - case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; - case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; - case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break; - case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break; - case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break; - case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break; - default: - return false; - } - - if (!match) - { - break; - } - - attribute += 2; - } - - if (match) - { - passed.push_back(&*config); - } - } - - if (configs) - { - sort(passed.begin(), passed.end(), SortConfig(attribList)); - - EGLint index; - for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++) - { - configs[index] = passed[index]->getHandle(); - } - - *numConfig = index; - } - else - { - *numConfig = passed.size(); - } - - return true; -} - -const egl::Config *ConfigSet::get(EGLConfig configHandle) -{ - for (Iterator config = mSet.begin(); config != mSet.end(); config++) - { - if (config->getHandle() == configHandle) - { - return &(*config); - } - } - - return NULL; -} -} diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h deleted file mode 100644 index 98441142f4..0000000000 --- a/src/3rdparty/angle/src/libEGL/Config.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright (c) 2002-2010 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. -// - -// Config.h: Defines the egl::Config class, describing the format, type -// and size for an egl::Surface. Implements EGLConfig and related functionality. -// [EGL 1.4] section 3.4 page 15. - -#ifndef INCLUDE_CONFIG_H_ -#define INCLUDE_CONFIG_H_ - -#include <EGL/egl.h> - -#include <set> - -#include "libGLESv2/renderer/Renderer.h" -#include "common/angleutils.h" - -namespace egl -{ -class Display; - -class Config -{ - public: - Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); - - EGLConfig getHandle() const; - - const GLenum mRenderTargetFormat; - const GLenum mDepthStencilFormat; - const GLint mMultiSample; - - EGLint mBufferSize; // Depth of the color buffer - EGLint mRedSize; // Bits of Red in the color buffer - EGLint mGreenSize; // Bits of Green in the color buffer - EGLint mBlueSize; // Bits of Blue in the color buffer - EGLint mLuminanceSize; // Bits of Luminance in the color buffer - EGLint mAlphaSize; // Bits of Alpha in the color buffer - EGLint mAlphaMaskSize; // Bits of Alpha Mask in the mask buffer - EGLBoolean mBindToTextureRGB; // True if bindable to RGB textures. - EGLBoolean mBindToTextureRGBA; // True if bindable to RGBA textures. - EGLenum mColorBufferType; // Color buffer type - EGLenum mConfigCaveat; // Any caveats for the configuration - EGLint mConfigID; // Unique EGLConfig identifier - EGLint mConformant; // Whether contexts created with this config are conformant - EGLint mDepthSize; // Bits of Z in the depth buffer - EGLint mLevel; // Frame buffer level - EGLBoolean mMatchNativePixmap; // Match the native pixmap format - EGLint mMaxPBufferWidth; // Maximum width of pbuffer - EGLint mMaxPBufferHeight; // Maximum height of pbuffer - EGLint mMaxPBufferPixels; // Maximum size of pbuffer - EGLint mMaxSwapInterval; // Maximum swap interval - EGLint mMinSwapInterval; // Minimum swap interval - EGLBoolean mNativeRenderable; // EGL_TRUE if native rendering APIs can render to surface - EGLint mNativeVisualID; // Handle of corresponding native visual - EGLint mNativeVisualType; // Native visual type of the associated visual - EGLint mRenderableType; // Which client rendering APIs are supported. - EGLint mSampleBuffers; // Number of multisample buffers - EGLint mSamples; // Number of samples per pixel - EGLint mStencilSize; // Bits of Stencil in the stencil buffer - EGLint mSurfaceType; // Which types of EGL surfaces are supported. - EGLenum mTransparentType; // Type of transparency supported - EGLint mTransparentRedValue; // Transparent red value - EGLint mTransparentGreenValue; // Transparent green value - EGLint mTransparentBlueValue; // Transparent blue value -}; - -// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24. -class SortConfig -{ - public: - explicit SortConfig(const EGLint *attribList); - - bool operator()(const Config *x, const Config *y) const; - bool operator()(const Config &x, const Config &y) const; - - private: - void scanForWantedComponents(const EGLint *attribList); - EGLint wantedComponentsSize(const Config &config) const; - - bool mWantRed; - bool mWantGreen; - bool mWantBlue; - bool mWantAlpha; - bool mWantLuminance; -}; - -class ConfigSet -{ - friend Display; - - public: - ConfigSet(); - - void add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); - size_t size() const; - bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); - const egl::Config *get(EGLConfig configHandle); - - private: - DISALLOW_COPY_AND_ASSIGN(ConfigSet); - - typedef std::set<Config, SortConfig> Set; - typedef Set::iterator Iterator; - Set mSet; - - static const EGLint mSortAttribs[]; -}; -} - -#endif // INCLUDE_CONFIG_H_ diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp deleted file mode 100644 index eea93b1d87..0000000000 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ /dev/null @@ -1,648 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Display.cpp: Implements the egl::Display class, representing the abstract -// display on which graphics are drawn. Implements EGLDisplay. -// [EGL 1.4] section 2.1.2 page 3. - -#include "libEGL/Display.h" - -#include <algorithm> -#include <map> -#include <vector> -#include <sstream> -#include <iterator> - -#include "common/debug.h" -#include "common/mathutil.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/SwapChain.h" - -#include "libEGL/main.h" -#include "libEGL/Surface.h" - -namespace egl -{ - -typedef std::map<EGLNativeDisplayType, Display*> DisplayMap; -static DisplayMap *GetDisplayMap() -{ - static DisplayMap displays; - return &displays; -} - -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()) - { - display = iter->second; - } - else - { - display = new egl::Display(displayId); - 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) - : mDisplayId(displayId), - mAttributeMap(), - mRenderer(NULL) -{ -} - -Display::~Display() -{ - terminate(); - - DisplayMap *displays = GetDisplayMap(); - DisplayMap::iterator iter = displays->find(mDisplayId); - if (iter != displays->end()) - { - displays->erase(iter); - } -} - -void Display::setAttributes(const AttributeMap &attribMap) -{ - mAttributeMap = attribMap; -} - -Error Display::initialize() -{ - if (isInitialized()) - { - return Error(EGL_SUCCESS); - } - - mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap); - - if (!mRenderer) - { - terminate(); - 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; - - rx::ConfigDesc *descList; - int numConfigs = mRenderer->generateConfigs(&descList); - ConfigSet configSet; - - for (int i = 0; i < numConfigs; ++i) - { - configSet.add(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize); - } - - // Give the sorted configs a unique ID and store them internally - EGLint index = 1; - for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) - { - Config configuration = *config; - configuration.mConfigID = index; - index++; - - mConfigSet.mSet.insert(configuration); - } - - mRenderer->deleteConfigs(descList); - descList = NULL; - - if (!isInitialized()) - { - terminate(); - return Error(EGL_NOT_INITIALIZED); - } - - initDisplayExtensionString(); - initVendorString(); - - return Error(EGL_SUCCESS); -} - -void Display::terminate() -{ - while (!mSurfaceSet.empty()) - { - destroySurface(*mSurfaceSet.begin()); - } - - while (!mContextSet.empty()) - { - destroyContext(*mContextSet.begin()); - } - - glDestroyRenderer(mRenderer); - mRenderer = NULL; - - mConfigSet.mSet.clear(); -} - -bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) -{ - return mConfigSet.getConfigs(configs, attribList, configSize, numConfig); -} - -bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) -{ - const egl::Config *configuration = mConfigSet.get(config); - - switch (attribute) - { - case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break; - case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break; - case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break; - case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break; - case EGL_RED_SIZE: *value = configuration->mRedSize; break; - case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break; - case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break; - case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break; - case EGL_CONFIG_ID: *value = configuration->mConfigID; break; - case EGL_LEVEL: *value = configuration->mLevel; break; - case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break; - case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break; - case EGL_SAMPLES: *value = configuration->mSamples; break; - case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break; - case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break; - case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break; - case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break; - case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break; - case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break; - case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break; - case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break; - case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break; - case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break; - case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break; - case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break; - case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break; - case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break; - case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break; - case EGL_CONFORMANT: *value = configuration->mConformant; break; - case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break; - case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break; - case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break; - default: - return false; - } - - return true; -} - - - -Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface) -{ - const Config *configuration = mConfigSet.get(config); - EGLint postSubBufferSupported = EGL_FALSE; - - EGLint width = 0; - EGLint height = 0; - EGLint fixedSize = EGL_FALSE; - - if (attribList) - { - while (*attribList != EGL_NONE) - { - switch (attribList[0]) - { - case EGL_RENDER_BUFFER: - switch (attribList[1]) - { - case EGL_BACK_BUFFER: - break; - case EGL_SINGLE_BUFFER: - return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported - default: - return Error(EGL_BAD_ATTRIBUTE); - } - break; - case EGL_POST_SUB_BUFFER_SUPPORTED_NV: - postSubBufferSupported = attribList[1]; - break; - case EGL_WIDTH: - width = attribList[1]; - break; - case EGL_HEIGHT: - height = attribList[1]; - break; - case EGL_FIXED_SIZE_ANGLE: - fixedSize = attribList[1]; - break; - case EGL_VG_COLORSPACE: - return Error(EGL_BAD_MATCH); - case EGL_VG_ALPHA_FORMAT: - return Error(EGL_BAD_MATCH); - default: - return Error(EGL_BAD_ATTRIBUTE); - } - - attribList += 2; - } - } - - if (width < 0 || height < 0) - { - return Error(EGL_BAD_PARAMETER); - } - - if (!fixedSize) - { - width = -1; - height = -1; - } - - if (hasExistingWindowSurface(window)) - { - return Error(EGL_BAD_ALLOC); - } - - if (mRenderer->testDeviceLost(false)) - { - Error error = restoreLostDevice(); - if (error.isError()) - { - return error; - } - } - - Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported); - Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - mSurfaceSet.insert(surface); - - *outSurface = surface; - return Error(EGL_SUCCESS); -} - -Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface) -{ - EGLint width = 0, height = 0; - EGLenum textureFormat = EGL_NO_TEXTURE; - EGLenum textureTarget = EGL_NO_TEXTURE; - const Config *configuration = mConfigSet.get(config); - - if (attribList) - { - while (*attribList != EGL_NONE) - { - switch (attribList[0]) - { - case EGL_WIDTH: - width = attribList[1]; - break; - case EGL_HEIGHT: - height = attribList[1]; - break; - case EGL_LARGEST_PBUFFER: - if (attribList[1] != EGL_FALSE) - UNIMPLEMENTED(); // FIXME - break; - case EGL_TEXTURE_FORMAT: - switch (attribList[1]) - { - case EGL_NO_TEXTURE: - case EGL_TEXTURE_RGB: - case EGL_TEXTURE_RGBA: - textureFormat = attribList[1]; - break; - default: - return Error(EGL_BAD_ATTRIBUTE); - } - break; - case EGL_TEXTURE_TARGET: - switch (attribList[1]) - { - case EGL_NO_TEXTURE: - case EGL_TEXTURE_2D: - textureTarget = attribList[1]; - break; - default: - return Error(EGL_BAD_ATTRIBUTE); - } - break; - case EGL_MIPMAP_TEXTURE: - if (attribList[1] != EGL_FALSE) - return Error(EGL_BAD_ATTRIBUTE); - break; - case EGL_VG_COLORSPACE: - return Error(EGL_BAD_MATCH); - case EGL_VG_ALPHA_FORMAT: - return Error(EGL_BAD_MATCH); - default: - return Error(EGL_BAD_ATTRIBUTE); - } - - attribList += 2; - } - } - - if (width < 0 || height < 0) - { - return Error(EGL_BAD_PARAMETER); - } - - if (width == 0 || height == 0) - { - return Error(EGL_BAD_ATTRIBUTE); - } - - if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) - { - 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); - } - - if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) - { - 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); - } - - if (mRenderer->testDeviceLost(false)) - { - Error error = restoreLostDevice(); - if (error.isError()) - { - return error; - } - } - - Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); - Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - mSurfaceSet.insert(surface); - - *outSurface = surface; - return Error(EGL_SUCCESS); -} - -Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, - bool robustAccess, EGLContext *outContext) -{ - if (!mRenderer) - { - *outContext = EGL_NO_CONTEXT; - return Error(EGL_SUCCESS); - } - else if (mRenderer->testDeviceLost(false)) // Lost device - { - Error error = restoreLostDevice(); - if (error.isError()) - { - return error; - } - } - - //TODO(jmadill): shader model is not cross-platform - if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4) - { - return Error(EGL_BAD_CONFIG); - } - - gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess); - mContextSet.insert(context); - - *outContext = context; - return Error(EGL_SUCCESS); -} - -Error Display::restoreLostDevice() -{ - for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) - { - if ((*ctx)->isResetNotificationEnabled()) - { - // 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++) - { - (*surface)->release(); - } - - if (!mRenderer->resetDevice()) - { - return Error(EGL_BAD_ALLOC); - } - - // Restore any surfaces that may have been lost - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - Error error = (*surface)->resetSwapChain(); - if (error.isError()) - { - return error; - } - } - - return Error(EGL_SUCCESS); -} - - -void Display::destroySurface(egl::Surface *surface) -{ - delete surface; - mSurfaceSet.erase(surface); -} - -void Display::destroyContext(gl::Context *context) -{ - glDestroyContext(context); - mContextSet.erase(context); -} - -void Display::notifyDeviceLost() -{ - for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) - { - (*context)->markContextLost(); - } -} - -void Display::recreateSwapChains() -{ - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - (*surface)->getSwapChain()->recreate(); - } -} - -bool Display::isInitialized() const -{ - return mRenderer != NULL && mConfigSet.size() > 0; -} - -bool Display::isValidConfig(EGLConfig config) -{ - return mConfigSet.get(config) != NULL; -} - -bool Display::isValidContext(gl::Context *context) -{ - return mContextSet.find(context) != mContextSet.end(); -} - -bool Display::isValidSurface(egl::Surface *surface) -{ - return mSurfaceSet.find(surface) != mSurfaceSet.end(); -} - -bool Display::hasExistingWindowSurface(EGLNativeWindowType window) -{ - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - if ((*surface)->getWindowHandle() == window) - { - return true; - } - } - - return false; -} - -std::string Display::generateClientExtensionString() -{ - std::vector<std::string> extensions; - - extensions.push_back("EGL_EXT_client_extensions"); - - extensions.push_back("ANGLE_platform_angle"); - - if (supportsPlatformD3D()) - { - extensions.push_back("ANGLE_platform_angle_d3d"); - } - - if (supportsPlatformOpenGL()) - { - extensions.push_back("ANGLE_platform_angle_opengl"); - } - - std::ostringstream stream; - std::copy(extensions.begin(), extensions.end(), std::ostream_iterator<std::string>(stream, " ")); - return stream.str(); -} - -void Display::initDisplayExtensionString() -{ - std::vector<std::string> extensions; - - // Multi-vendor (EXT) extensions - extensions.push_back("EGL_EXT_create_context_robustness"); - - // ANGLE-specific extensions - if (mRenderer->getShareHandleSupport()) - { - extensions.push_back("EGL_ANGLE_d3d_share_handle_client_buffer"); - extensions.push_back("EGL_ANGLE_surface_d3d_texture_2d_share_handle"); - } - - extensions.push_back("EGL_ANGLE_query_surface_pointer"); - extensions.push_back("EGL_ANGLE_window_fixed_size"); - - if (mRenderer->getPostSubBufferSupport()) - { - extensions.push_back("EGL_NV_post_sub_buffer"); - } - -#if defined (ANGLE_TEST_CONFIG) - // TODO: complete support for the EGL_KHR_create_context extension - extensions.push_back("EGL_KHR_create_context"); -#endif - - std::ostringstream stream; - std::copy(extensions.begin(), extensions.end(), std::ostream_iterator<std::string>(stream, " ")); - mDisplayExtensionString = stream.str(); -} - -const char *Display::getExtensionString(egl::Display *display) -{ - if (display != EGL_NO_DISPLAY) - { - return display->mDisplayExtensionString.c_str(); - } - else - { - static std::string clientExtensions = generateClientExtensionString(); - return clientExtensions.c_str(); - } -} - -bool Display::supportsPlatformD3D() -{ -#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) - return true; -#else - return false; -#endif -} - -bool Display::supportsPlatformOpenGL() -{ - return false; -} - -void Display::initVendorString() -{ - mVendorString = "Google Inc."; - - LUID adapterLuid = {0}; - - //TODO(jmadill): LUID is not cross-platform - if (mRenderer && mRenderer->getLUID(&adapterLuid)) - { - char adapterLuidString[64]; - sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); - - mVendorString += adapterLuidString; - } -} - -const char *Display::getVendorString() const -{ - return mVendorString.c_str(); -} - -} diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h deleted file mode 100644 index b3ffcc84c5..0000000000 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ /dev/null @@ -1,104 +0,0 @@ -// -// Copyright (c) 2002-2013 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. -// - -// Display.h: Defines the egl::Display class, representing the abstract -// display on which graphics are drawn. Implements EGLDisplay. -// [EGL 1.4] section 2.1.2 page 3. - -#ifndef LIBEGL_DISPLAY_H_ -#define LIBEGL_DISPLAY_H_ - -#include <set> -#include <vector> - -#include "libEGL/Error.h" -#include "libEGL/Config.h" -#include "libEGL/AttributeMap.h" - -namespace gl -{ -class Context; -} - -namespace egl -{ -class Surface; - -class Display -{ - public: - ~Display(); - - Error initialize(); - void terminate(); - - static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); - - static const char *getExtensionString(egl::Display *display); - - static bool supportsPlatformD3D(); - static bool supportsPlatformOpenGL(); - - bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); - bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); - - 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); - - bool isInitialized() const; - bool isValidConfig(EGLConfig config); - bool isValidContext(gl::Context *context); - bool isValidSurface(egl::Surface *surface); - bool hasExistingWindowSurface(EGLNativeWindowType window); - - rx::Renderer *getRenderer() { return mRenderer; }; - - // exported methods must be virtual - virtual void notifyDeviceLost(); - virtual void recreateSwapChains(); - - const char *getExtensionString() const; - const char *getVendorString() const; - EGLNativeDisplayType getDisplayId() const { return mDisplayId; } - - private: - DISALLOW_COPY_AND_ASSIGN(Display); - - Display(EGLNativeDisplayType displayId); - - void setAttributes(const AttributeMap &attribMap); - - Error restoreLostDevice(); - - EGLNativeDisplayType mDisplayId; - AttributeMap mAttributeMap; - - typedef std::set<Surface*> SurfaceSet; - SurfaceSet mSurfaceSet; - - ConfigSet mConfigSet; - - typedef std::set<gl::Context*> ContextSet; - ContextSet mContextSet; - - rx::Renderer *mRenderer; - - static std::string generateClientExtensionString(); - - void initDisplayExtensionString(); - std::string mDisplayExtensionString; - - void initVendorString(); - std::string mVendorString; -}; -} - -#endif // LIBEGL_DISPLAY_H_ diff --git a/src/3rdparty/angle/src/libEGL/Error.cpp b/src/3rdparty/angle/src/libEGL/Error.cpp deleted file mode 100644 index df5f163d32..0000000000 --- a/src/3rdparty/angle/src/libEGL/Error.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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 deleted file mode 100644 index 71805d2fb7..0000000000 --- a/src/3rdparty/angle/src/libEGL/Error.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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 deleted file mode 100644 index b664a8530e..0000000000 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Surface.cpp: Implements the egl::Surface class, representing a drawing surface -// such as the client area of a window, including any back buffers. -// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. - -#include <tchar.h> - -#include <algorithm> - -#include "libEGL/Surface.h" - -#include "common/debug.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/SwapChain.h" -#include "libGLESv2/main.h" - -#include "libEGL/main.h" -#include "libEGL/Display.h" - -#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), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported) -{ - //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; - mTextureFormat = EGL_NO_TEXTURE; - mTextureTarget = EGL_NO_TEXTURE; - - mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio - mRenderBuffer = EGL_BACK_BUFFER; - mSwapBehavior = EGL_BUFFER_PRESERVED; - mSwapInterval = -1; - mWidth = width; - mHeight = height; - mFixedWidth = mWidth; - mFixedHeight = mHeight; - setSwapInterval(1); - mFixedSize = fixedSize; - - subclassWindow(); -} - -Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) - : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) -{ - //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; - mTextureFormat = textureFormat; - mTextureTarget = textureType; - - mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio - mRenderBuffer = EGL_BACK_BUFFER; - mSwapBehavior = EGL_BUFFER_PRESERVED; - mSwapInterval = -1; - setSwapInterval(1); - // This constructor is for offscreen surfaces, which are always fixed-size. - mFixedSize = EGL_TRUE; - mFixedWidth = mWidth; - mFixedHeight = mHeight; -} - -Surface::~Surface() -{ - unsubclassWindow(); - release(); -} - -Error Surface::initialize() -{ - if (mNativeWindow.getNativeWindow()) - { - if (!mNativeWindow.initialize()) - { - return Error(EGL_BAD_SURFACE); - } - } - - Error error = resetSwapChain(); - if (error.isError()) - { - return error; - } - - return Error(EGL_SUCCESS); -} - -void Surface::release() -{ - delete mSwapChain; - mSwapChain = NULL; - - if (mTexture) - { - mTexture->releaseTexImage(); - mTexture = NULL; - } -} - -Error Surface::resetSwapChain() -{ - ASSERT(!mSwapChain); - - int width; - int height; - - if (!mFixedSize) - { - RECT windowRect; - if (!mNativeWindow.getClientRect(&windowRect)) - { - ASSERT(false); - - return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); - } - - width = windowRect.right - windowRect.left; - height = windowRect.bottom - windowRect.top; - } - else - { - // non-window surface - size is determined at creation - width = mWidth; - height = mHeight; - } - - mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, - mConfig->mRenderTargetFormat, - mConfig->mDepthStencilFormat); - if (!mSwapChain) - { - return Error(EGL_BAD_ALLOC); - } - - Error error = resetSwapChain(width, height); - if (error.isError()) - { - SafeDelete(mSwapChain); - return error; - } - - return Error(EGL_SUCCESS); -} - -Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) -{ - ASSERT(mSwapChain); - -#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 Error(status); - } - else if (status != EGL_SUCCESS) - { - return Error(status); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - return Error(EGL_SUCCESS); -} - -Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) -{ - ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); - ASSERT(mSwapChain); - - EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); - - if (status == EGL_CONTEXT_LOST) - { - mRenderer->notifyDeviceLost(); - return Error(status); - } - else if (status != EGL_SUCCESS) - { - return Error(status); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mSwapIntervalDirty = false; - - return Error(EGL_SUCCESS); -} - -Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return Error(EGL_SUCCESS); - } - - if (x + width > abs(mWidth)) - { - width = abs(mWidth) - x; - } - - if (y + height > abs(mHeight)) - { - height = abs(mHeight) - y; - } - - if (width == 0 || height == 0) - { - return Error(EGL_SUCCESS); - } - - ASSERT(width > 0); - ASSERT(height > 0); - - EGLint status = mSwapChain->swapRect(x, y, width, height); - - if (status == EGL_CONTEXT_LOST) - { - mRenderer->notifyDeviceLost(); - return Error(status); - } - else if (status != EGL_SUCCESS) - { - return Error(status); - } - - checkForOutOfDateSwapChain(); - - return Error(EGL_SUCCESS); -} - -EGLNativeWindowType Surface::getWindowHandle() -{ - return mNativeWindow.getNativeWindow(); -} - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") -#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") - -static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) -{ - if (message == WM_SIZE) - { - Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty)); - if(surf) - { - surf->checkForOutOfDateSwapChain(); - } - } - WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc)); - return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); -} -#endif - -void Surface::subclassWindow() -{ -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); - if (!window) - { - return; - } - - DWORD processId; - DWORD threadId = GetWindowThreadProcessId(window, &processId); - if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) - { - return; - } - - SetLastError(0); - LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); - if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) - { - mWindowSubclassed = false; - return; - } - - SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this)); - SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc)); - mWindowSubclassed = true; -#endif -} - -void Surface::unsubclassWindow() -{ - 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(window, kParentWndProc)); - - // Check the windowproc is still SurfaceWindowProc. - // If this assert fails, then it is likely the application has subclassed the - // hwnd as well and did not unsubclass before destroying its EGL context. The - // application should be modified to either subclass before initializing the - // EGL context, or to unsubclass before destroying the EGL context. - if(parentWndFunc) - { - LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); - UNUSED_ASSERTION_VARIABLE(prevWndFunc); - ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc)); - } - - RemoveProp(window, kSurfaceProperty); - RemoveProp(window, kParentWndProc); -#endif - mWindowSubclassed = false; -} - -bool Surface::checkForOutOfDateSwapChain() -{ - RECT client; - int clientWidth = getWidth(); - int clientHeight = getHeight(); - bool sizeDirty = false; - if (!mFixedSize && !mNativeWindow.isIconic()) - { - // 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 (!mNativeWindow.getClientRect(&client)) - { - ASSERT(false); - return false; - } - - // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. - clientWidth = client.right - client.left; - clientHeight = client.bottom - client.top; - sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - } - - if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) - { - clientWidth = mFixedWidth; - clientHeight = mFixedHeight; - sizeDirty = true; - } - - bool wasDirty = (mSwapIntervalDirty || sizeDirty); - - if (mSwapIntervalDirty) - { - resetSwapChain(clientWidth, clientHeight); - } - else if (sizeDirty) - { - resizeSwapChain(clientWidth, clientHeight); - } - - if (wasDirty) - { - if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this) - { - glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this); - } - - return true; - } - - return false; -} - -Error Surface::swap() -{ - return swapRect(0, 0, abs(mWidth), abs(mHeight)); -} - -Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mPostSubBufferSupported) - { - // Spec is not clear about how this should be handled. - return Error(EGL_SUCCESS); - } - - return swapRect(x, y, width, height); -} - -EGLint Surface::isPostSubBufferSupported() const -{ - return mPostSubBufferSupported; -} - -rx::SwapChain *Surface::getSwapChain() const -{ - return mSwapChain; -} - -void Surface::setSwapInterval(EGLint interval) -{ - if (mSwapInterval == interval) - { - return; - } - - mSwapInterval = interval; - mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval()); - mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval()); - - mSwapIntervalDirty = true; -} - -EGLint Surface::getConfigID() const -{ - return mConfig->mConfigID; -} - -EGLint Surface::getWidth() const -{ - return mWidth; -} - -EGLint Surface::getHeight() const -{ - return mHeight; -} - -EGLint Surface::getPixelAspectRatio() const -{ - return mPixelAspectRatio; -} - -EGLenum Surface::getRenderBuffer() const -{ - return mRenderBuffer; -} - -EGLenum Surface::getSwapBehavior() const -{ - return mSwapBehavior; -} - -EGLenum Surface::getTextureFormat() const -{ - return mTextureFormat; -} - -EGLenum Surface::getTextureTarget() const -{ - return mTextureTarget; -} - -void Surface::setBoundTexture(gl::Texture2D *texture) -{ - mTexture = texture; -} - -gl::Texture2D *Surface::getBoundTexture() const -{ - return mTexture; -} - -EGLint Surface::isFixedSize() const -{ - return mFixedSize; -} - -void Surface::setFixedWidth(EGLint width) -{ - mFixedWidth = width; -} - -void Surface::setFixedHeight(EGLint height) -{ - mFixedHeight = height; -} - -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 deleted file mode 100644 index 46382d06e1..0000000000 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Surface.h: Defines the egl::Surface class, representing a drawing surface -// such as the client area of a window, including any back buffers. -// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. - -#ifndef LIBEGL_SURFACE_H_ -#define LIBEGL_SURFACE_H_ - -#include "libEGL/Error.h" - -#include <EGL/egl.h> - -#include "common/angleutils.h" -#include "common/NativeWindow.h" - -namespace gl -{ -class Texture2D; -} -namespace rx -{ -class SwapChain; -class RendererD3D; //TODO(jmadill): remove this -} - -namespace egl -{ -class Display; -class Config; - -class Surface -{ - public: - Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported); - Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); - - virtual ~Surface(); - - Error initialize(); - void release(); - Error resetSwapChain(); - - EGLNativeWindowType getWindowHandle(); - Error swap(); - Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); - - virtual EGLint isPostSubBufferSupported() const; - - virtual rx::SwapChain *getSwapChain() const; - - void setSwapInterval(EGLint interval); - bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update - - virtual EGLint getConfigID() const; - virtual EGLint getWidth() const; - virtual EGLint getHeight() const; - virtual EGLint getPixelAspectRatio() const; - virtual EGLenum getRenderBuffer() const; - virtual EGLenum getSwapBehavior() const; - virtual EGLenum getTextureFormat() const; - virtual EGLenum getTextureTarget() const; - virtual EGLenum getFormat() const; - - virtual void setBoundTexture(gl::Texture2D *texture); - virtual gl::Texture2D *getBoundTexture() const; - - EGLint isFixedSize() const; - void setFixedWidth(EGLint width); - void setFixedHeight(EGLint height); - - private: - DISALLOW_COPY_AND_ASSIGN(Surface); - - Display *const mDisplay; - rx::RendererD3D *mRenderer; - - HANDLE mShareHandle; - rx::SwapChain *mSwapChain; - - void subclassWindow(); - void unsubclassWindow(); - Error resizeSwapChain(int backbufferWidth, int backbufferHeight); - Error resetSwapChain(int backbufferWidth, int backbufferHeight); - Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - - 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 -// EGLBoolean mipmapTexture; // True if texture has mipmaps -// EGLint mipmapLevel; // Mipmap level to render to -// EGLenum multisampleResolve; // Multisample resolve behavior - EGLint mPixelAspectRatio; // Display aspect ratio - EGLenum mRenderBuffer; // Render buffer - EGLenum mSwapBehavior; // Buffer swap behavior - EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture - EGLenum mTextureTarget; // Type of texture: 2D or no texture -// EGLenum vgAlphaFormat; // Alpha format for OpenVG -// EGLenum vgColorSpace; // Color space for OpenVG - EGLint mSwapInterval; - EGLint mPostSubBufferSupported; - EGLint mFixedSize; - - bool mSwapIntervalDirty; - gl::Texture2D *mTexture; -}; -} - -#endif // LIBEGL_SURFACE_H_ diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 68399d63a4..d09219e308 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -6,1258 +6,245 @@ // libEGL.cpp: Implements the exported EGL functions. -#undef EGLAPI -#define EGLAPI +#include "libGLESv2/entry_points_egl.h" +#include "libGLESv2/entry_points_egl_ext.h" -#include <exception> - -#include "common/debug.h" -#include "common/version.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/SwapChain.h" -#if defined(ANGLE_ENABLE_D3D11) -# include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#endif - -#include "libEGL/main.h" -#include "libEGL/Display.h" -#include "libEGL/Surface.h" - -#include "common/NativeWindow.h" - -bool validateDisplay(egl::Display *display) +extern "C" { - if (display == EGL_NO_DISPLAY) - { - recordError(egl::Error(EGL_BAD_DISPLAY)); - return false; - } - - if (!display->isInitialized()) - { - recordError(egl::Error(EGL_NOT_INITIALIZED)); - return false; - } - return true; +EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + return egl::ChooseConfig(dpy, attrib_list, configs, config_size, num_config); } -bool validateConfig(egl::Display *display, EGLConfig config) +EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { - if (!validateDisplay(display)) - { - return false; - } - - if (!display->isValidConfig(config)) - { - recordError(egl::Error(EGL_BAD_CONFIG)); - return false; - } - - return true; + return egl::CopyBuffers(dpy, surface, target); } -bool validateContext(egl::Display *display, gl::Context *context) +EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { - if (!validateDisplay(display)) - { - return false; - } - - if (!display->isValidContext(context)) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return false; - } - - return true; + return egl::CreateContext(dpy, config, share_context, attrib_list); } -bool validateSurface(egl::Display *display, egl::Surface *surface) +EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { - if (!validateDisplay(display)) - { - return false; - } - - if (!display->isValidSurface(surface)) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return false; - } - - return true; + return egl::CreatePbufferSurface(dpy, config, attrib_list); } -extern "C" -{ -EGLint __stdcall eglGetError(void) +EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) { - EVENT("()"); - - EGLint error = egl::getCurrentError(); - recordError(egl::Error(EGL_SUCCESS)); - return error; + return egl::CreatePixmapSurface(dpy, config, pixmap, attrib_list); } -EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) +EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) { - EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); - - return egl::Display::getDisplay(display_id, egl::AttributeMap()); + return egl::CreateWindowSurface(dpy, config, win, attrib_list); } -EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", - platform, native_display, attrib_list); - - switch (platform) - { - case EGL_PLATFORM_ANGLE_ANGLE: - break; - - default: - recordError(egl::Error(EGL_BAD_CONFIG)); - return EGL_NO_DISPLAY; - } - - EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display); - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - // Validate the display device context - if (WindowFromDC(displayId) == NULL) - { - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } -#endif - - 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) - { - switch (curAttrib[0]) - { - case EGL_PLATFORM_ANGLE_TYPE_ANGLE: - 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: - break; - } - } - } - - if (!majorVersionSpecified && minorVersionSpecified) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_DISPLAY; - } - - if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_DISPLAY; - } - - recordError(egl::Error(EGL_SUCCESS)); - return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list)); + return egl::DestroyContext(dpy, ctx); } -EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", - dpy, major, minor); - - if (dpy == EGL_NO_DISPLAY) - { - recordError(egl::Error(EGL_BAD_DISPLAY)); - return EGL_FALSE; - } - - egl::Display *display = static_cast<egl::Display*>(dpy); - - egl::Error error = display->initialize(); - if (error.isError()) - { - recordError(error); - return EGL_FALSE; - } - - if (major) *major = 1; - if (minor) *minor = 4; - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::DestroySurface(dpy, surface); } -EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) +EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) { - EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); - - if (dpy == EGL_NO_DISPLAY) - { - recordError(egl::Error(EGL_BAD_DISPLAY)); - return EGL_FALSE; - } - - egl::Display *display = static_cast<egl::Display*>(dpy); - - display->terminate(); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetConfigAttrib(dpy, config, attribute, value); } -const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) +EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); - - egl::Display *display = static_cast<egl::Display*>(dpy); - if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display)) - { - return NULL; - } - - const char *result; - switch (name) - { - case EGL_CLIENT_APIS: - result = "OpenGL_ES"; - break; - case EGL_EXTENSIONS: - result = egl::Display::getExtensionString(display); - break; - case EGL_VENDOR: - result = display->getVendorString(); - break; - case EGL_VERSION: - result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")"; - break; - default: - recordError(egl::Error(EGL_BAD_PARAMETER)); - return NULL; - } - - recordError(egl::Error(EGL_SUCCESS)); - return result; + return egl::GetConfigs(dpy, configs, config_size, num_config); } -EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " - "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", - dpy, configs, config_size, num_config); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - if (!num_config) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - const EGLint attribList[] = {EGL_NONE}; - - if (!display->getConfigs(configs, attribList, config_size, num_config)) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetCurrentDisplay(); } -EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { - EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " - "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", - dpy, attrib_list, configs, config_size, num_config); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - if (!num_config) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - const EGLint attribList[] = {EGL_NONE}; - - if (!attrib_list) - { - attrib_list = attribList; - } - - display->getConfigs(configs, attrib_list, config_size, num_config); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetCurrentSurface(readdraw); } -EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", - dpy, config, attribute, value); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateConfig(display, config)) - { - return EGL_FALSE; - } - - if (!display->getConfigAttrib(config, attribute, value)) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetDisplay(display_id); } -EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) +EGLint EGLAPIENTRY eglGetError(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " - "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - if (!rx::IsValidEGLNativeWindowType(win)) - { - recordError(egl::Error(EGL_BAD_NATIVE_WINDOW)); - return EGL_NO_SURFACE; - } - - EGLSurface surface = EGL_NO_SURFACE; - egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface); - if (error.isError()) - { - recordError(error); - return EGL_NO_SURFACE; - } - - return surface; + return egl::GetError(); } -EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", - dpy, config, attrib_list); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - 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; + return egl::Initialize(dpy, major, minor); } -EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " - "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_SURFACE; + return egl::MakeCurrent(dpy, draw, read, ctx); } -EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - display->destroySurface((egl::Surface*)surface); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::QueryContext(dpy, ctx, attribute, value); } -EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", - dpy, surface, attribute, value); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - switch (attribute) - { - case EGL_VG_ALPHA_FORMAT: - UNIMPLEMENTED(); // FIXME - break; - case EGL_VG_COLORSPACE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_CONFIG_ID: - *value = eglSurface->getConfigID(); - break; - case EGL_HEIGHT: - *value = eglSurface->getHeight(); - break; - case EGL_HORIZONTAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_LARGEST_PBUFFER: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_TEXTURE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_LEVEL: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MULTISAMPLE_RESOLVE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_PIXEL_ASPECT_RATIO: - *value = eglSurface->getPixelAspectRatio(); - break; - case EGL_RENDER_BUFFER: - *value = eglSurface->getRenderBuffer(); - break; - case EGL_SWAP_BEHAVIOR: - *value = eglSurface->getSwapBehavior(); - break; - case EGL_TEXTURE_FORMAT: - *value = eglSurface->getTextureFormat(); - break; - case EGL_TEXTURE_TARGET: - *value = eglSurface->getTextureTarget(); - break; - case EGL_VERTICAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_WIDTH: - *value = eglSurface->getWidth(); - break; - case EGL_POST_SUB_BUFFER_SUPPORTED_NV: - *value = eglSurface->isPostSubBufferSupported(); - break; - case EGL_FIXED_SIZE_ANGLE: - *value = eglSurface->isFixedSize(); - break; - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::QueryString(dpy, name); } -EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) { - TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", - dpy, surface, attribute, value); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - switch (attribute) - { - case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - { - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - rx::SwapChain *swapchain = eglSurface->getSwapChain(); - *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); - } - break; -#if defined(ANGLE_ENABLE_D3D11) - case EGL_DEVICE_EXT: - { - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - rx::Renderer *renderer = display->getRenderer(); - if (!renderer) - { - *value = NULL; - break; - } - - if (renderer->getMajorShaderModel() < 4) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return EGL_FALSE; - } - - *value = static_cast<rx::Renderer11*>(renderer)->getDevice(); - } - break; -#endif - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::QuerySurface(dpy, surface, attribute, value); } -EGLBoolean __stdcall eglBindAPI(EGLenum api) +EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { - EVENT("(EGLenum api = 0x%X)", api); - - switch (api) - { - case EGL_OPENGL_API: - case EGL_OPENVG_API: - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; // Not supported by this implementation - case EGL_OPENGL_ES_API: - break; - default: - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - egl::setCurrentAPI(api); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::SwapBuffers(dpy, surface); } -EGLenum __stdcall eglQueryAPI(void) +EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { - EVENT("()"); - - EGLenum API = egl::getCurrentAPI(); - - recordError(egl::Error(EGL_SUCCESS)); - return API; + return egl::Terminate(dpy); } -EGLBoolean __stdcall eglWaitClient(void) +EGLBoolean EGLAPIENTRY eglWaitGL(void) { - EVENT("()"); - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::WaitGL(); } -EGLBoolean __stdcall eglReleaseThread(void) +EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { - EVENT("()"); - - eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::WaitNative(engine); } -EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " - "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", - dpy, buftype, buffer, config, attrib_list); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) - { - 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 surface; + return egl::BindTexImage(dpy, surface, buffer); } -EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", - dpy, surface, attribute, value); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); - - if (!validateSurface(display, eglSurface)) - { - 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 - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::ReleaseTexImage(dpy, surface, buffer); } -EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - if (eglSurface->getBoundTexture()) - { - recordError(egl::Error(EGL_BAD_ACCESS)); - return EGL_FALSE; - } - - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - if (!glBindTexImage(eglSurface)) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::SurfaceAttrib(dpy, surface, attribute, value); } -EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - gl::Texture2D *texture = eglSurface->getBoundTexture(); - - if (texture) - { - texture->releaseTexImage(); - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::SwapInterval(dpy, interval); } -EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) +EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface()); - - if (draw_surface == NULL) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - draw_surface->setSwapInterval(interval); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::BindAPI(api); } -EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) +EGLenum EGLAPIENTRY eglQueryAPI(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " - "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); - - // Get the requested client version (default is 1) and check it is 2 or 3. - EGLint client_version = 1; - bool reset_notification = false; - bool robust_access = false; - - if (attrib_list) - { - for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) - { - switch (attribute[0]) - { - case EGL_CONTEXT_CLIENT_VERSION: - client_version = attribute[1]; - break; - case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: - if (attribute[1] == EGL_TRUE) - { - recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented - return EGL_NO_CONTEXT; - // robust_access = true; - } - else if (attribute[1] != EGL_FALSE) - { - 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) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_CONTEXT; - } - break; - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_CONTEXT; - } - } - } - - if (client_version != 2 && client_version != 3) - { - recordError(egl::Error(EGL_BAD_CONFIG)); - return EGL_NO_CONTEXT; - } - - egl::Display *display = static_cast<egl::Display*>(dpy); - - if (share_context) - { - gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context); - - if (sharedGLContext->isResetNotificationEnabled() != reset_notification) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_NO_CONTEXT; - } - - if (sharedGLContext->getClientVersion() != client_version) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return EGL_NO_CONTEXT; - } - - // Can not share contexts between displays - if (sharedGLContext->getRenderer() != display->getRenderer()) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_NO_CONTEXT; - } - } - - if (!validateConfig(display, config)) - { - return EGL_NO_CONTEXT; - } - - 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; + return egl::QueryAPI(); } -EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); - - egl::Display *display = static_cast<egl::Display*>(dpy); - gl::Context *context = static_cast<gl::Context*>(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - if (ctx == EGL_NO_CONTEXT) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return EGL_FALSE; - } - - display->destroyContext(context); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::CreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list); } -EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +EGLBoolean EGLAPIENTRY eglReleaseThread(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", - dpy, draw, read, ctx); - - egl::Display *display = static_cast<egl::Display*>(dpy); - gl::Context *context = static_cast<gl::Context*>(ctx); - - bool noContext = (ctx == EGL_NO_CONTEXT); - bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); - if (noContext != noSurface) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) - { - return EGL_FALSE; - } - - if (dpy != EGL_NO_DISPLAY && display->isInitialized()) - { - rx::Renderer *renderer = display->getRenderer(); - if (renderer->testDeviceLost(true)) - { - return EGL_FALSE; - } - - if (renderer->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - } - - if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) || - (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read)))) - { - return EGL_FALSE; - } - - if (draw != read) - { - UNIMPLEMENTED(); // FIXME - } - - egl::setCurrentDisplay(dpy); - egl::setCurrentDrawSurface(draw); - egl::setCurrentReadSurface(read); - - glMakeCurrent(context, display, static_cast<egl::Surface*>(draw)); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::ReleaseThread(); } -EGLContext __stdcall eglGetCurrentContext(void) +EGLBoolean EGLAPIENTRY eglWaitClient(void) { - EVENT("()"); - - EGLContext context = glGetCurrentContext(); - - recordError(egl::Error(EGL_SUCCESS)); - return context; + return egl::WaitClient(); } -EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) +EGLContext EGLAPIENTRY eglGetCurrentContext(void) { - EVENT("(EGLint readdraw = %d)", readdraw); - - if (readdraw == EGL_READ) - { - recordError(egl::Error(EGL_SUCCESS)); - return egl::getCurrentReadSurface(); - } - else if (readdraw == EGL_DRAW) - { - recordError(egl::Error(EGL_SUCCESS)); - return egl::getCurrentDrawSurface(); - } - else - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_NO_SURFACE; - } + return egl::GetCurrentContext(); } -EGLDisplay __stdcall eglGetCurrentDisplay(void) +EGLSync EGLAPIENTRY eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) { - EVENT("()"); - - EGLDisplay dpy = egl::getCurrentDisplay(); - - recordError(egl::Error(EGL_SUCCESS)); - return dpy; + return egl::CreateSync(dpy, type, attrib_list); } -EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +EGLBoolean EGLAPIENTRY eglDestroySync(EGLDisplay dpy, EGLSync sync) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", - dpy, ctx, attribute, value); - - egl::Display *display = static_cast<egl::Display*>(dpy); - gl::Context *context = static_cast<gl::Context*>(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::DestroySync(dpy, sync); } -EGLBoolean __stdcall eglWaitGL(void) +EGLint EGLAPIENTRY eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) { - EVENT("()"); - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::ClientWaitSync(dpy, sync, flags, timeout); } -EGLBoolean __stdcall eglWaitNative(EGLint engine) +EGLBoolean EGLAPIENTRY eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) { - EVENT("(EGLint engine = %d)", engine); - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::GetSyncAttrib(dpy, sync, attribute, value); } -EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) +EGLImage EGLAPIENTRY eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - egl::Error error = eglSurface->swap(); - if (error.isError()) - { - recordError(error); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::CreateImage(dpy, ctx, target, buffer, attrib_list); } -EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +EGLBoolean EGLAPIENTRY eglDestroyImage(EGLDisplay dpy, EGLImage image) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::DestroyImage(dpy, image); } -EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) +EGLDisplay EGLAPIENTRY eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); - - if (x < 0 || y < 0 || width < 0 || height < 0) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - egl::Display *display = static_cast<egl::Display*>(dpy); - egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } + return egl::GetPlatformDisplay(platform, native_display, attrib_list); +} - egl::Error error = eglSurface->postSubBuffer(x, y, width, height); - if (error.isError()) - { - recordError(error); - return EGL_FALSE; - } +EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list) +{ + return egl::CreatePlatformWindowSurface(dpy, config, native_window, attrib_list); +} - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; +EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list) +{ + return egl::CreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list); } -__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) +EGLBoolean EGLAPIENTRY eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) { - EVENT("(const char *procname = \"%s\")", procname); + return egl::WaitSync(dpy, sync, flags); +} - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; +EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +{ + return egl::QuerySurfacePointerANGLE(dpy, surface, attribute, value); +} - static const Extension eglExtensions[] = - { - { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE }, - { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV }, - { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT }, - { "", NULL }, - }; +EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) +{ + return egl::PostSubBufferNV(dpy, surface, x, y, width, height); +} - for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) - { - if (strcmp(procname, eglExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; - } - } +EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +{ + return egl::GetPlatformDisplayEXT(platform, native_display, attrib_list); +} - return glGetProcAddress(procname); +__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) +{ + return egl::GetProcAddress(procname); } + } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def index d7949d0354..823cba2f88 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.def +++ b/src/3rdparty/angle/src/libEGL/libEGL.def @@ -39,3 +39,15 @@ EXPORTS eglGetPlatformDisplayEXT @35 eglQuerySurfacePointerANGLE @36 eglPostSubBufferNV @37 + + ; 1.5 entry points + eglCreateSync @38 + eglDestroySync @39 + eglClientWaitSync @40 + eglGetSyncAttrib @41 + eglCreateImage @42 + eglDestroyImage @43 + eglGetPlatformDisplay @44 + eglCreatePlatformWindowSurface @45 + eglCreatePlatformPixmapSurface @46 + eglWaitSync @47 diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc deleted file mode 100644 index 65e0aa50c8..0000000000 --- a/src/3rdparty/angle/src/libEGL/libEGL.rc +++ /dev/null @@ -1,103 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include <windows.h> -#include "../common/version.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "#include ""../common/version.h""\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library" - VALUE "FileVersion", ANGLE_VERSION_STRING - VALUE "InternalName", "libEGL" - VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." - VALUE "OriginalFilename", "libEGL.dll" - VALUE "PrivateBuild", ANGLE_VERSION_STRING - VALUE "ProductName", "ANGLE libEGL Dynamic Link Library" - VALUE "ProductVersion", ANGLE_VERSION_STRING - VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def index 492ad4d0cf..6a771a54b8 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def +++ b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def @@ -39,3 +39,15 @@ EXPORTS eglGetPlatformDisplayEXT@12 @35 eglQuerySurfacePointerANGLE@16 @36 eglPostSubBufferNV@24 @37 + + ; 1.5 entry points + eglCreateSync @38 + eglDestroySync @39 + eglClientWaitSync @40 + eglGetSyncAttrib @41 + eglCreateImage @42 + eglDestroyImage @43 + eglGetPlatformDisplay @44 + eglCreatePlatformWindowSurface @45 + eglCreatePlatformPixmapSurface @46 + eglWaitSync @47 diff --git a/src/3rdparty/angle/src/libEGL/libEGLd.def b/src/3rdparty/angle/src/libEGL/libEGLd.def index 0ebd27d0e1..cab7dc9d24 100644 --- a/src/3rdparty/angle/src/libEGL/libEGLd.def +++ b/src/3rdparty/angle/src/libEGL/libEGLd.def @@ -39,3 +39,15 @@ EXPORTS eglGetPlatformDisplayEXT @35 eglQuerySurfacePointerANGLE @36 eglPostSubBufferNV @37 + + ; 1.5 entry points + eglCreateSync @38 + eglDestroySync @39 + eglClientWaitSync @40 + eglGetSyncAttrib @41 + eglCreateImage @42 + eglDestroyImage @43 + eglGetPlatformDisplay @44 + eglCreatePlatformWindowSurface @45 + eglCreatePlatformPixmapSurface @46 + eglWaitSync @47 diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp deleted file mode 100644 index e88cad775f..0000000000 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// -// Copyright (c) 2002-2012 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. -// - -// main.cpp: DLL entry point and management of thread-local data. - -#include "libEGL/main.h" - -#include "common/debug.h" -#include "common/tls.h" - -static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; - -namespace egl -{ - -Current *AllocateCurrent() -{ - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - if (currentTLS == TLS_OUT_OF_INDEXES) - { - return NULL; - } - - Current *current = new Current(); - current->error = EGL_SUCCESS; - current->API = EGL_OPENGL_ES_API; - current->display = EGL_NO_DISPLAY; - current->drawSurface = EGL_NO_SURFACE; - current->readSurface = EGL_NO_SURFACE; - - if (!SetTLSValue(currentTLS, current)) - { - ERR("Could not set thread local storage."); - return NULL; - } - - return current; -} - -void DeallocateCurrent() -{ - Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); - SafeDelete(current); - SetTLSValue(currentTLS, NULL); -} - -} - -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - -extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - { -#if defined(ANGLE_ENABLE_DEBUG_TRACE) - FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); - - if (debug) - { - fclose(debug); - debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase - - if (debug) - { - fclose(debug); - } - } -#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: - { - egl::AllocateCurrent(); - } - break; - case DLL_THREAD_DETACH: - { - egl::DeallocateCurrent(); - } - break; - case DLL_PROCESS_DETACH: - { - egl::DeallocateCurrent(); - DestroyTLSIndex(currentTLS); - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::UninitializeDebugAnnotations(); -#endif - } - break; - default: - break; - } - - return TRUE; -} - -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC - -namespace egl -{ - -Current *GetCurrentData() -{ -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); - - // ANGLE issue 488: when the dll is loaded after thread initialization, - // thread local storage (current) might not exist yet. - return (current ? current : AllocateCurrent()); -#else - // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; - return ¤t; -#endif -} - -void recordError(const Error &error) -{ - Current *current = GetCurrentData(); - - current->error = error.getCode(); -} - -EGLint getCurrentError() -{ - Current *current = GetCurrentData(); - - return current->error; -} - -void setCurrentAPI(EGLenum API) -{ - Current *current = GetCurrentData(); - - current->API = API; -} - -EGLenum getCurrentAPI() -{ - Current *current = GetCurrentData(); - - return current->API; -} - -void setCurrentDisplay(EGLDisplay dpy) -{ - Current *current = GetCurrentData(); - - current->display = dpy; -} - -EGLDisplay getCurrentDisplay() -{ - Current *current = GetCurrentData(); - - return current->display; -} - -void setCurrentDrawSurface(EGLSurface surface) -{ - Current *current = GetCurrentData(); - - current->drawSurface = surface; -} - -EGLSurface getCurrentDrawSurface() -{ - Current *current = GetCurrentData(); - - return current->drawSurface; -} - -void setCurrentReadSurface(EGLSurface surface) -{ - Current *current = GetCurrentData(); - - current->readSurface = surface; -} - -EGLSurface getCurrentReadSurface() -{ - Current *current = GetCurrentData(); - - return current->readSurface; -} - -} diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h deleted file mode 100644 index e5361a4a5e..0000000000 --- a/src/3rdparty/angle/src/libEGL/main.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) 2002-2010 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. -// - -// main.h: Management of thread-local data. - -#ifndef LIBEGL_MAIN_H_ -#define LIBEGL_MAIN_H_ - -#include "libEGL/Error.h" - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -namespace egl -{ -struct Current -{ - EGLint error; - EGLenum API; - EGLDisplay display; - EGLSurface drawSurface; - EGLSurface readSurface; -}; - -void recordError(const Error &error); -EGLint getCurrentError(); - -void setCurrentAPI(EGLenum API); -EGLenum getCurrentAPI(); - -void setCurrentDisplay(EGLDisplay dpy); -EGLDisplay getCurrentDisplay(); - -void setCurrentDrawSurface(EGLSurface surface); -EGLSurface getCurrentDrawSurface(); - -void setCurrentReadSurface(EGLSurface surface); -EGLSurface getCurrentReadSurface(); - -} - -#endif // LIBEGL_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Error.cpp b/src/3rdparty/angle/src/libGLESv2/Error.cpp deleted file mode 100644 index cc7d17eb37..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Error.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// 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 gl::Error class which encapsulates an OpenGL error -// and optional error message. - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -#include <cstdarg> - -namespace gl -{ - -Error::Error(GLenum errorCode) - : mCode(errorCode), - mMessage() -{ -} - -Error::Error(GLenum 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/libGLESv2/Error.h b/src/3rdparty/angle/src/libGLESv2/Error.h deleted file mode 100644 index b70b5a531c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Error.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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 gl::Error class which encapsulates an OpenGL error -// and optional error message. - -#ifndef LIBGLESV2_ERROR_H_ -#define LIBGLESV2_ERROR_H_ - -#include "angle_gl.h" - -#include <string> - -namespace gl -{ - -class Error -{ - public: - explicit Error(GLenum errorCode); - Error(GLenum errorCode, const char *msg, ...); - Error(const Error &other); - Error &operator=(const Error &other); - - GLenum getCode() const { return mCode; } - bool isError() const { return (mCode != GL_NO_ERROR); } - - const std::string &getMessage() const { return mMessage; } - - private: - GLenum mCode; - std::string mMessage; -}; - -} - -#endif // LIBGLESV2_ERROR_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py deleted file mode 100644 index cf039bfc21..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2012 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. -# - -# This script generates a function that converts 16-bit precision floating -# point numbers to 32-bit. -# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf. - -def convertMantissa(i): - if i == 0: - return 0 - elif i < 1024: - m = i << 13 - e = 0 - while not (m & 0x00800000): - e -= 0x00800000 - m = m << 1 - m &= ~0x00800000 - e += 0x38800000 - return m | e - else: - return 0x38000000 + ((i - 1024) << 13) - -def convertExponent(i): - if i == 0: - return 0 - elif i in range(1, 31): - return i << 23 - elif i == 31: - return 0x47800000 - elif i == 32: - return 0x80000000 - elif i in range(33, 63): - return 0x80000000 + ((i - 32) << 23) - else: - return 0xC7800000 - -def convertOffset(i): - if i == 0 or i == 32: - return 0 - else: - return 1024 - -print """// -// Copyright (c) 2012 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. -// - -// This file is automatically generated. - -namespace gl -{ -""" - -print "const static unsigned g_mantissa[2048] = {" -for i in range(0, 2048): - print " %#010x," % convertMantissa(i) -print "};\n" - -print "const static unsigned g_exponent[64] = {" -for i in range(0, 64): - print " %#010x," % convertExponent(i) -print "};\n" - -print "const static unsigned g_offset[64] = {" -for i in range(0, 64): - print " %#010x," % convertOffset(i) -print "};\n" - -print """float float16ToFloat32(unsigned short h) -{ - unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; - return *(float*) &i32; -} -} -""" diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp deleted file mode 100644 index 3d57262e3c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ /dev/null @@ -1,672 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. - -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Renderbuffer.h" -#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 -{ -// TODO: Move these functions, and the D3D-specific header inclusions above, -// to FramebufferD3D. -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT) -{ - if (attachment->isTexture()) - { - gl::Texture *texture = attachment->getTexture(); - ASSERT(texture); - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - const gl::ImageIndex *index = attachment->getTextureImageIndex(); - ASSERT(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); - } -} - -// Note: RenderTarget serials should ideally be in the RenderTargets themselves. -unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) -{ - if (attachment->isTexture()) - { - gl::Texture *texture = attachment->getTexture(); - ASSERT(texture); - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - const gl::ImageIndex *index = attachment->getTextureImageIndex(); - ASSERT(index); - return textureD3D->getRenderTargetSerial(*index); - } - - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); - return renderbufferD3D->getRenderTargetSerial(); -} - -} - -namespace gl -{ - -Framebuffer::Framebuffer(GLuint id) - : mId(id), - mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), - mDepthbuffer(NULL), - mStencilbuffer(NULL) -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - mColorbuffers[colorAttachment] = NULL; - mDrawBufferStates[colorAttachment] = GL_NONE; - } - mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; -} - -Framebuffer::~Framebuffer() -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - SafeDelete(mColorbuffers[colorAttachment]); - } - SafeDelete(mDepthbuffer); - SafeDelete(mStencilbuffer); -} - -void Framebuffer::detachTexture(GLuint textureId) -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; - - if (attachment && attachment->isTextureWithId(textureId)) - { - SafeDelete(mColorbuffers[colorAttachment]); - } - } - - if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId)) - { - SafeDelete(mDepthbuffer); - } - - if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId)) - { - SafeDelete(mStencilbuffer); - } -} - -void Framebuffer::detachRenderbuffer(GLuint renderbufferId) -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; - - if (attachment && attachment->isRenderbufferWithId(renderbufferId)) - { - SafeDelete(mColorbuffers[colorAttachment]); - } - } - - if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId)) - { - SafeDelete(mDepthbuffer); - } - - if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId)) - { - SafeDelete(mStencilbuffer); - } -} - -FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment]; -} - -FramebufferAttachment *Framebuffer::getDepthbuffer() const -{ - return mDepthbuffer; -} - -FramebufferAttachment *Framebuffer::getStencilbuffer() const -{ - return mStencilbuffer; -} - -FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const -{ - return (hasValidDepthStencil() ? mDepthbuffer : NULL); -} - -FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const -{ - FramebufferAttachment *depthstencilbuffer = mDepthbuffer; - - if (!depthstencilbuffer) - { - depthstencilbuffer = mStencilbuffer; - } - - return depthstencilbuffer; -} - -FramebufferAttachment *Framebuffer::getReadColorbuffer() const -{ - // Will require more logic if glReadBuffers is supported - return mColorbuffers[0]; -} - -GLenum Framebuffer::getReadColorbufferType() const -{ - // Will require more logic if glReadBuffers is supported - return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE); -} - -FramebufferAttachment *Framebuffer::getFirstColorbuffer() const -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (mColorbuffers[colorAttachment]) - { - return mColorbuffers[colorAttachment]; - } - } - - return NULL; -} - -FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const -{ - if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) - { - return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - return getDepthbuffer(); - case GL_STENCIL_ATTACHMENT: - return getStencilbuffer(); - case GL_DEPTH_STENCIL_ATTACHMENT: - return getDepthStencilBuffer(); - default: - UNREACHABLE(); - return NULL; - } - } -} - -GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const -{ - return mDrawBufferStates[colorAttachment]; -} - -void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer) -{ - mDrawBufferStates[colorAttachment] = drawBuffer; -} - -bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const -{ - return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE); -} - -bool Framebuffer::hasEnabledColorAttachment() const -{ - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (isEnabledColorAttachment(colorAttachment)) - { - return true; - } - } - - return false; -} - -bool Framebuffer::hasStencil() const -{ - return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0); -} - -bool Framebuffer::usingExtendedDrawBuffers() const -{ - for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (isEnabledColorAttachment(colorAttachment)) - { - return true; - } - } - - return false; -} - -GLenum Framebuffer::completeness(const gl::Data &data) const -{ - int width = 0; - int height = 0; - unsigned int colorbufferSize = 0; - int samples = -1; - bool missingAttachment = true; - - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; - - if (colorbuffer) - { - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - GLenum internalformat = colorbuffer->getInternalFormat(); - const TextureCaps &formatCaps = data.textureCaps->get(internalformat); - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (colorbuffer->isTexture()) - { - if (!formatCaps.renderable) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else - { - if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - - if (!missingAttachment) - { - // all color attachments must have the same width and height - if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - - // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that - // all color attachments have the same number of samples for the FBO to be complete. - if (colorbuffer->getSamples() != samples) - { - return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; - } - - // 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 (data.clientVersion < 3) - { - if (formatInfo.pixelBytes != colorbufferSize) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - } - - // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness - for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) - { - const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment]; - - if (previousAttachment && - (colorbuffer->id() == previousAttachment->id() && - colorbuffer->type() == previousAttachment->type())) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - } - } - else - { - width = colorbuffer->getWidth(); - height = colorbuffer->getHeight(); - samples = colorbuffer->getSamples(); - colorbufferSize = formatInfo.pixelBytes; - missingAttachment = false; - } - } - } - - if (mDepthbuffer) - { - if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - GLenum internalformat = mDepthbuffer->getInternalFormat(); - const TextureCaps &formatCaps = data.textureCaps->get(internalformat); - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (mDepthbuffer->isTexture()) - { - // depth texture attachments require OES/ANGLE_depth_texture - if (!data.extensions->depthTextures) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (!formatCaps.renderable) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (formatInfo.depthBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else - { - if (!formatCaps.renderable || formatInfo.depthBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - - if (missingAttachment) - { - width = mDepthbuffer->getWidth(); - height = mDepthbuffer->getHeight(); - samples = mDepthbuffer->getSamples(); - missingAttachment = false; - } - else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight()) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - else if (samples != mDepthbuffer->getSamples()) - { - return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; - } - } - - if (mStencilbuffer) - { - if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - GLenum internalformat = mStencilbuffer->getInternalFormat(); - 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 - if (!data.extensions->depthTextures) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (!formatCaps.renderable) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (formatInfo.stencilBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else - { - if (!formatCaps.renderable || formatInfo.stencilBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - - if (missingAttachment) - { - width = mStencilbuffer->getWidth(); - height = mStencilbuffer->getHeight(); - samples = mStencilbuffer->getSamples(); - missingAttachment = false; - } - else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight()) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - else if (samples != mStencilbuffer->getSamples()) - { - return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; - } - } - - // if we have both a depth and stencil buffer, they must refer to the same object - // since we only support packed_depth_stencil and not separate depth and stencil - if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil()) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - // we need to have at least one attachment to be complete - if (missingAttachment) - { - return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; - } - - return GL_FRAMEBUFFER_COMPLETE; -} - -Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) -{ - GLuint maxDimension = caps.maxRenderbufferSize; - return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension); -} - -Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) -{ - for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex) - { - GLenum attachmentTarget = attachments[attachIndex]; - - FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() - : getAttachment(attachmentTarget); - - if (attachment) - { - rx::RenderTarget *renderTarget = NULL; - Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - - renderTarget->invalidate(x, y, width, height); - } - } - - return Error(GL_NO_ERROR); -} - -DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil) - : Framebuffer(0) -{ - Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0); - mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer); - - Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0); - - // Make a new attachment objects to ensure we do not double-delete - // See angle issue 686 - mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL); - mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL); - - mDrawBufferStates[0] = GL_BACK; - mReadBufferState = GL_BACK; -} - -int Framebuffer::getSamples(const gl::Data &data) const -{ - 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 - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (mColorbuffers[colorAttachment]) - { - return mColorbuffers[colorAttachment]->getSamples(); - } - } - } - - return 0; -} - -bool Framebuffer::hasValidDepthStencil() const -{ - // A valid depth-stencil attachment has the same resource bound to both the - // depth and stencil attachment points. - return (mDepthbuffer && mStencilbuffer && - mDepthbuffer->type() == mStencilbuffer->type() && - mDepthbuffer->id() == mStencilbuffer->id()); -} - -ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const -{ - ColorbufferInfo colorbuffersForRender; - - for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment) - { - GLenum drawBufferState = mDrawBufferStates[colorAttachment]; - FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; - - if (colorbuffer != NULL && drawBufferState != GL_NONE) - { - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); - colorbuffersForRender.push_back(colorbuffer); - } - else if (!workarounds.mrtPerfWorkaround) - { - colorbuffersForRender.push_back(NULL); - } - } - - return colorbuffersForRender; -} - -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. - return GL_FRAMEBUFFER_COMPLETE; -} - -FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const -{ - switch (attachment) - { - case GL_COLOR: - case GL_BACK: - return getColorbuffer(0); - case GL_DEPTH: - return getDepthbuffer(); - case GL_STENCIL: - return getStencilbuffer(); - case GL_DEPTH_STENCIL: - return getDepthStencilBuffer(); - default: - UNREACHABLE(); - return NULL; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h deleted file mode 100644 index d0fe8935ea..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ /dev/null @@ -1,126 +0,0 @@ -// -// Copyright (c) 2002-2013 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. -// - -// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. - -#ifndef LIBGLESV2_FRAMEBUFFER_H_ -#define LIBGLESV2_FRAMEBUFFER_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "Constants.h" - -#include <vector> - -namespace rx -{ -class RenderbufferImpl; -struct Workarounds; -} - -namespace gl -{ -class FramebufferAttachment; -class Texture; -class Renderbuffer; -struct ImageIndex; -struct Caps; -struct Extensions; -class TextureCapsMap; -struct Data; - -typedef std::vector<FramebufferAttachment *> ColorbufferInfo; - -class Framebuffer -{ - public: - Framebuffer(GLuint id); - virtual ~Framebuffer(); - - GLuint id() const { return mId; } - - 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); - - FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; - FramebufferAttachment *getDepthbuffer() const; - FramebufferAttachment *getStencilbuffer() const; - FramebufferAttachment *getDepthStencilBuffer() const; - FramebufferAttachment *getDepthOrStencilbuffer() const; - FramebufferAttachment *getReadColorbuffer() const; - GLenum getReadColorbufferType() const; - FramebufferAttachment *getFirstColorbuffer() const; - - virtual FramebufferAttachment *getAttachment(GLenum attachment) const; - - GLenum getDrawBufferState(unsigned int colorAttachment) const; - void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer); - - bool isEnabledColorAttachment(unsigned int colorAttachment) const; - bool hasEnabledColorAttachment() const; - bool hasStencil() const; - int getSamples(const gl::Data &data) const; - bool usingExtendedDrawBuffers() const; - - virtual GLenum completeness(const gl::Data &data) const; - bool hasValidDepthStencil() const; - - 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 rx::Workarounds &workarounds) const; - - protected: - GLuint mId; - - FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - GLenum mReadBufferState; - - FramebufferAttachment *mDepthbuffer; - FramebufferAttachment *mStencilbuffer; - - private: - DISALLOW_COPY_AND_ASSIGN(Framebuffer); - - void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); -}; - -class DefaultFramebuffer : public Framebuffer -{ - public: - DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil); - - GLenum completeness(const gl::Data &data) const override; - virtual FramebufferAttachment *getAttachment(GLenum attachment) const; - - private: - DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer); -}; - -} - -namespace rx -{ -class RenderTarget; - -// TODO: place this in FramebufferD3D.h -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT); -unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment); - -} - -#endif // LIBGLESV2_FRAMEBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp deleted file mode 100644 index c498f8a178..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2002-2011 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. -// - -// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used -// to allocate GL handles. - -#include "libGLESv2/HandleAllocator.h" - -#include "libGLESv2/main.h" - -namespace gl -{ - -HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1) -{ -} - -HandleAllocator::~HandleAllocator() -{ -} - -void HandleAllocator::setBaseHandle(GLuint value) -{ - ASSERT(mBaseValue == mNextValue); - mBaseValue = value; - mNextValue = value; -} - -GLuint HandleAllocator::allocate() -{ - if (mFreeValues.size()) - { - GLuint handle = mFreeValues.back(); - mFreeValues.pop_back(); - return handle; - } - return mNextValue++; -} - -void HandleAllocator::release(GLuint handle) -{ - if (handle == mNextValue - 1) - { - // Don't drop below base value - if(mNextValue > mBaseValue) - { - mNextValue--; - } - } - else - { - // Only free handles that we own - don't drop below the base value - if (handle >= mBaseValue) - { - mFreeValues.push_back(handle); - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h deleted file mode 100644 index a89cc86775..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2002-2011 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. -// - -// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to -// allocate GL handles. - -#ifndef LIBGLESV2_HANDLEALLOCATOR_H_ -#define LIBGLESV2_HANDLEALLOCATOR_H_ - -#include "common/angleutils.h" - -#include "angle_gl.h" - -#include <vector> - -namespace gl -{ - -class HandleAllocator -{ - public: - HandleAllocator(); - virtual ~HandleAllocator(); - - void setBaseHandle(GLuint value); - - GLuint allocate(); - void release(GLuint handle); - - private: - DISALLOW_COPY_AND_ASSIGN(HandleAllocator); - - GLuint mBaseValue; - GLuint mNextValue; - typedef std::vector<GLuint> HandleList; - HandleList mFreeValues; -}; - -} - -#endif // LIBGLESV2_HANDLEALLOCATOR_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp deleted file mode 100644 index 3faa8c56f6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ /dev/null @@ -1,668 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Program.cpp: Implements the gl::Program class. Implements GL program objects -// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. - -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/Renderer.h" - -namespace gl -{ -const char * const g_fakepath = "C:\\fakepath"; - -AttributeBindings::AttributeBindings() -{ -} - -AttributeBindings::~AttributeBindings() -{ -} - -InfoLog::InfoLog() : mInfoLog(NULL) -{ -} - -InfoLog::~InfoLog() -{ - delete[] mInfoLog; -} - - -int InfoLog::getLength() const -{ - if (!mInfoLog) - { - return 0; - } - else - { - return strlen(mInfoLog) + 1; - } -} - -void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) -{ - int index = 0; - - if (bufSize > 0) - { - if (mInfoLog) - { - index = std::min(bufSize - 1, (int)strlen(mInfoLog)); - memcpy(infoLog, mInfoLog, index); - } - - infoLog[index] = '\0'; - } - - if (length) - { - *length = index; - } -} - -// append a santized message to the program info log. -// The D3D compiler includes a fake file path in some of the warning or error -// messages, so lets remove all occurrences of this fake file path from the log. -void InfoLog::appendSanitized(const char *message) -{ - std::string msg(message); - - size_t found; - do - { - found = msg.find(g_fakepath); - if (found != std::string::npos) - { - msg.erase(found, strlen(g_fakepath)); - } - } - while (found != std::string::npos); - - append("%s", msg.c_str()); -} - -void InfoLog::append(const char *format, ...) -{ - if (!format) - { - return; - } - - va_list vararg; - va_start(vararg, format); - size_t infoLength = vsnprintf(NULL, 0, format, vararg); - va_end(vararg); - - char *logPointer = NULL; - - if (!mInfoLog) - { - mInfoLog = new char[infoLength + 2]; - logPointer = mInfoLog; - } - else - { - size_t currentlogLength = strlen(mInfoLog); - char *newLog = new char[currentlogLength + infoLength + 2]; - strcpy(newLog, mInfoLog); - - delete[] mInfoLog; - mInfoLog = newLog; - - logPointer = mInfoLog + currentlogLength; - } - - va_start(vararg, format); - vsnprintf(logPointer, infoLength, format, vararg); - va_end(vararg); - - logPointer[infoLength] = 0; - strcpy(logPointer + infoLength, "\n"); -} - -void InfoLog::reset() -{ - if (mInfoLog) - { - delete [] mInfoLog; - mInfoLog = NULL; - } -} - -Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) -{ - mFragmentShader = NULL; - mVertexShader = NULL; - mProgramBinary.set(NULL); - mDeleteStatus = false; - mLinked = false; - mRefCount = 0; - mRenderer = renderer; - - resetUniformBlockBindings(); -} - -Program::~Program() -{ - unlink(true); - - if (mVertexShader != NULL) - { - mVertexShader->release(); - } - - if (mFragmentShader != NULL) - { - mFragmentShader->release(); - } -} - -bool Program::attachShader(Shader *shader) -{ - if (shader->getType() == GL_VERTEX_SHADER) - { - if (mVertexShader) - { - return false; - } - - mVertexShader = shader; - mVertexShader->addRef(); - } - else if (shader->getType() == GL_FRAGMENT_SHADER) - { - if (mFragmentShader) - { - return false; - } - - mFragmentShader = shader; - mFragmentShader->addRef(); - } - else UNREACHABLE(); - - return true; -} - -bool Program::detachShader(Shader *shader) -{ - if (shader->getType() == GL_VERTEX_SHADER) - { - if (mVertexShader != shader) - { - return false; - } - - mVertexShader->release(); - mVertexShader = NULL; - } - else if (shader->getType() == GL_FRAGMENT_SHADER) - { - if (mFragmentShader != shader) - { - return false; - } - - mFragmentShader->release(); - mFragmentShader = NULL; - } - else UNREACHABLE(); - - return true; -} - -int Program::getAttachedShadersCount() const -{ - return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0); -} - -void AttributeBindings::bindAttributeLocation(GLuint index, const char *name) -{ - if (index < MAX_VERTEX_ATTRIBS) - { - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mAttributeBinding[i].erase(name); - } - - mAttributeBinding[index].insert(name); - } -} - -void Program::bindAttributeLocation(GLuint index, const char *name) -{ - mAttributeBindings.bindAttributeLocation(index, 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 -Error Program::link(const Data &data) -{ - unlink(false); - - mInfoLog.reset(); - resetUniformBlockBindings(); - - mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode); - if (result.error.isError()) - { - return result.error; - } - - mLinked = result.linkSuccess; - return gl::Error(GL_NO_ERROR); -} - -int AttributeBindings::getAttributeBinding(const std::string &name) const -{ - for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++) - { - if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end()) - { - return location; - } - } - - return -1; -} - -// Returns the program object to an unlinked state, before re-linking, or at destruction -void Program::unlink(bool destroy) -{ - if (destroy) // Object being destructed - { - if (mFragmentShader) - { - mFragmentShader->release(); - mFragmentShader = NULL; - } - - if (mVertexShader) - { - mVertexShader->release(); - mVertexShader = NULL; - } - } - - mProgramBinary.set(NULL); - mLinked = false; -} - -bool Program::isLinked() -{ - return mLinked; -} - -ProgramBinary* Program::getProgramBinary() const -{ - return mProgramBinary.get(); -} - -Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) -{ - unlink(false); - - mInfoLog.reset(); - - mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); - if (result.error.isError()) - { - mProgramBinary.set(NULL); - return result.error; - } - - mLinked = result.linkSuccess; - return Error(GL_NO_ERROR); -} - -void Program::release() -{ - mRefCount--; - - if (mRefCount == 0 && mDeleteStatus) - { - mResourceManager->deleteProgram(mHandle); - } -} - -void Program::addRef() -{ - mRefCount++; -} - -unsigned int Program::getRefCount() const -{ - return mRefCount; -} - -GLint Program::getProgramBinaryLength() const -{ - ProgramBinary *programBinary = mProgramBinary.get(); - if (programBinary) - { - return programBinary->getLength(); - } - else - { - return 0; - } -} - -int Program::getInfoLogLength() const -{ - return mInfoLog.getLength(); -} - -void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) -{ - return mInfoLog.getLog(bufSize, length, infoLog); -} - -void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) -{ - int total = 0; - - if (mVertexShader) - { - if (total < maxCount) - { - shaders[total] = mVertexShader->getHandle(); - } - - total++; - } - - if (mFragmentShader) - { - if (total < maxCount) - { - shaders[total] = mFragmentShader->getHandle(); - } - - total++; - } - - if (count) - { - *count = total; - } -} - -void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - programBinary->getActiveAttribute(index, bufsize, length, size, type, name); - } - else - { - if (bufsize > 0) - { - name[0] = '\0'; - } - - if (length) - { - *length = 0; - } - - *type = GL_NONE; - *size = 1; - } -} - -GLint Program::getActiveAttributeCount() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveAttributeCount(); - } - else - { - return 0; - } -} - -GLint Program::getActiveAttributeMaxLength() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveAttributeMaxLength(); - } - else - { - return 0; - } -} - -void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveUniform(index, bufsize, length, size, type, name); - } - else - { - if (bufsize > 0) - { - name[0] = '\0'; - } - - if (length) - { - *length = 0; - } - - *size = 0; - *type = GL_NONE; - } -} - -GLint Program::getActiveUniformCount() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveUniformCount(); - } - else - { - return 0; - } -} - -GLint Program::getActiveUniformMaxLength() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveUniformMaxLength(); - } - else - { - return 0; - } -} - -void Program::flagForDeletion() -{ - mDeleteStatus = true; -} - -bool Program::isFlaggedForDeletion() const -{ - return mDeleteStatus; -} - -void Program::validate(const Caps &caps) -{ - mInfoLog.reset(); - - ProgramBinary *programBinary = getProgramBinary(); - if (isLinked() && programBinary) - { - programBinary->validate(mInfoLog, caps); - } - else - { - mInfoLog.append("Program has not been successfully linked."); - } -} - -bool Program::isValidated() const -{ - ProgramBinary *programBinary = mProgramBinary.get(); - if (programBinary) - { - return programBinary->isValidated(); - } - else - { - return false; - } -} - -GLint Program::getActiveUniformBlockCount() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return static_cast<GLint>(programBinary->getActiveUniformBlockCount()); - } - else - { - return 0; - } -} - -GLint Program::getActiveUniformBlockMaxLength() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength()); - } - else - { - return 0; - } -} - -void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) -{ - mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; -} - -GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const -{ - return mUniformBlockBindings[uniformBlockIndex]; -} - -void Program::resetUniformBlockBindings() -{ - for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++) - { - mUniformBlockBindings[blockId] = 0; - } -} - -void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) -{ - mTransformFeedbackVaryings.resize(count); - for (GLsizei i = 0; i < count; i++) - { - mTransformFeedbackVaryings[i] = varyings[i]; - } - - mTransformFeedbackBufferMode = bufferMode; -} - -void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary && index < programBinary->getTransformFeedbackVaryingCount()) - { - const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index); - GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length())); - if (length) - { - *length = lastNameIdx; - } - if (size) - { - *size = varying.size; - } - if (type) - { - *type = varying.type; - } - if (name) - { - memcpy(name, varying.name.c_str(), lastNameIdx); - name[lastNameIdx] = '\0'; - } - } -} - -GLsizei Program::getTransformFeedbackVaryingCount() const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount()); - } - else - { - return 0; - } -} - -GLsizei Program::getTransformFeedbackVaryingMaxLength() const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - GLsizei maxSize = 0; - for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++) - { - const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i); - maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1)); - } - - return maxSize; - } - else - { - return 0; - } -} - -GLenum Program::getTransformFeedbackBufferMode() const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getTransformFeedbackBufferMode(); - } - else - { - return mTransformFeedbackBufferMode; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h deleted file mode 100644 index b92349eeef..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Program.h: Defines the gl::Program class. Implements GL program objects -// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. - -#ifndef LIBGLESV2_PROGRAM_H_ -#define LIBGLESV2_PROGRAM_H_ - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/ProgramBinary.h" - -#include <GLES2/gl2.h> - -#include <vector> -#include <string> -#include <set> - -namespace rx -{ -class Renderer; -} - -namespace gl -{ -struct Caps; -struct Data; -class ResourceManager; -class Shader; - -extern const char * const g_fakepath; - -class AttributeBindings -{ - public: - AttributeBindings(); - ~AttributeBindings(); - - void bindAttributeLocation(GLuint index, const char *name); - int getAttributeBinding(const std::string &name) const; - - private: - std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS]; -}; - -class InfoLog -{ - public: - InfoLog(); - ~InfoLog(); - - int getLength() const; - void getLog(GLsizei bufSize, GLsizei *length, char *infoLog); - - void appendSanitized(const char *message); - void append(const char *info, ...); - void reset(); - private: - DISALLOW_COPY_AND_ASSIGN(InfoLog); - char *mInfoLog; -}; - -class Program -{ - public: - Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle); - - ~Program(); - - bool attachShader(Shader *shader); - bool detachShader(Shader *shader); - int getAttachedShadersCount() const; - - void bindAttributeLocation(GLuint index, const char *name); - - Error link(const Data &data); - bool isLinked(); - Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); - ProgramBinary *getProgramBinary() const; - - int getInfoLogLength() const; - void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); - void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); - - void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveAttributeCount(); - GLint getActiveAttributeMaxLength(); - - void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveUniformCount(); - GLint getActiveUniformMaxLength(); - - GLint getActiveUniformBlockCount(); - GLint getActiveUniformBlockMaxLength(); - - void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); - GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; - - void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); - void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; - GLsizei getTransformFeedbackVaryingCount() const; - GLsizei getTransformFeedbackVaryingMaxLength() const; - GLenum getTransformFeedbackBufferMode() const; - - void addRef(); - void release(); - unsigned int getRefCount() const; - void flagForDeletion(); - bool isFlaggedForDeletion() const; - - void validate(const Caps &caps); - bool isValidated() const; - - GLint getProgramBinaryLength() const; - - private: - DISALLOW_COPY_AND_ASSIGN(Program); - - void unlink(bool destroy = false); - void resetUniformBlockBindings(); - - Shader *mFragmentShader; - Shader *mVertexShader; - - AttributeBindings mAttributeBindings; - - GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; - - std::vector<std::string> mTransformFeedbackVaryings; - GLuint mTransformFeedbackBufferMode; - - BindingPointer<ProgramBinary> mProgramBinary; - bool mLinked; - bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use - - unsigned int mRefCount; - - ResourceManager *mResourceManager; - rx::Renderer *mRenderer; - const GLuint mHandle; - - InfoLog mInfoLog; -}; -} - -#endif // LIBGLESV2_PROGRAM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp deleted file mode 100644 index cd4fc4e32a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -// -// Copyright (c) 2002-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. -// - -// Texture.cpp: Implements the gl::Texture class and its derived classes -// Texture2D and TextureCubeMap. Implements GL texture objects and related -// functionality. [OpenGL ES 2.0.24] section 3.7 page 63. - -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/ImageIndex.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/Image.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" - -#include "libEGL/Surface.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace gl -{ - -bool IsMipmapFiltered(const gl::SamplerState &samplerState) -{ - switch (samplerState.minFilter) - { - case GL_NEAREST: - case GL_LINEAR: - return false; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return true; - default: UNREACHABLE(); - return false; - } -} - -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), - mImmutableLevelCount(0), - mTarget(target) -{ -} - -Texture::~Texture() -{ - SafeDelete(mTexture); -} - -GLenum Texture::getTarget() const -{ - return mTarget; -} - -void Texture::setUsage(GLenum usage) -{ - mUsage = usage; - getImplementation()->setUsage(usage); -} - -GLenum Texture::getUsage() const -{ - return mUsage; -} - -GLint Texture::getBaseLevelWidth() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getWidth() : 0); -} - -GLint Texture::getBaseLevelHeight() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getHeight() : 0); -} - -GLint Texture::getBaseLevelDepth() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getDepth() : 0); -} - -// Note: "base level image" is loosely defined to be any image from the base level, -// where in the base of 2D array textures and cube maps there are several. Don't use -// the base level image for anything except querying texture format and size. -GLenum Texture::getBaseLevelInternalFormat() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getInternalFormat() : GL_NONE); -} - -GLsizei Texture::getWidth(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getWidth(); -} - -GLsizei Texture::getHeight(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getHeight(); -} - -GLenum Texture::getInternalFormat(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getInternalFormat(); -} - -GLenum Texture::getActualFormat(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getActualFormat(); -} - -Error Texture::generateMipmaps() -{ - return getImplementation()->generateMipmaps(); -} - -Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); -} - -unsigned int Texture::getTextureSerial() const -{ - return mTextureSerial; -} - -unsigned int Texture::issueTextureSerial() -{ - return mCurrentTextureSerial++; -} - -bool Texture::isImmutable() const -{ - return (mImmutableLevelCount > 0); -} - -int Texture::immutableLevelCount() -{ - return mImmutableLevelCount; -} - -int Texture::mipLevels() const -{ - return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; -} - -const rx::Image *Texture::getBaseLevelImage() const -{ - return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL); -} - -Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_2D) -{ - mSurface = NULL; -} - -Texture2D::~Texture2D() -{ - if (mSurface) - { - mSurface->setBoundTexture(NULL); - mSurface = NULL; - } -} - -GLsizei Texture2D::getWidth(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getWidth(); - else - return 0; -} - -GLsizei Texture2D::getHeight(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getHeight(); - else - return 0; -} - -GLenum Texture2D::getInternalFormat(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getInternalFormat(); - else - return GL_NONE; -} - -GLenum Texture2D::getActualFormat(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getActualFormat(); - else - return GL_NONE; -} - -Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - releaseTexImage(); - - return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void Texture2D::bindTexImage(egl::Surface *surface) -{ - releaseTexImage(); - - mTexture->bindTexImage(surface); - - mSurface = surface; - mSurface->setBoundTexture(this); -} - -void Texture2D::releaseTexImage() -{ - if (mSurface) - { - mSurface->setBoundTexture(NULL); - mSurface = NULL; - - mTexture->releaseTexImage(); - } -} - -Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, - const PixelUnpackState &unpack, const void *pixels) -{ - releaseTexImage(); - - return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels); -} - -Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); -} - -Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); -} - -Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, - Framebuffer *source) -{ - releaseTexImage(); - - return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); -} - -Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) -{ - Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - bool npotSupport = extensions.textureNPOT; - - if (!npotSupport) - { - if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) || - (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height))) - { - return false; - } - } - - if (IsMipmapFiltered(samplerState)) - { - if (!npotSupport) - { - if (!gl::isPow2(width) || !gl::isPow2(height)) - { - return false; - } - } - - if (!isMipmapComplete()) - { - return false; - } - } - - // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if: - // The internalformat specified for the texture arrays is a sized internal depth or - // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_- - // MODE is NONE, and either the magnification filter is not NEAREST or the mini- - // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0)); - if (formatInfo.depthBits > 0 && clientVersion > 2) - { - if (samplerState.compareMode == GL_NONE) - { - if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || - samplerState.magFilter != GL_NEAREST) - { - return false; - } - } - } - - return true; -} - -bool Texture2D::isCompressed(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).compressed; -} - -bool Texture2D::isDepth(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -Error Texture2D::generateMipmaps() -{ - releaseTexImage(); - - return mTexture->generateMipmaps(); -} - -// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool Texture2D::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 0; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; -} - -bool Texture2D::isLevelComplete(int level) const -{ - if (isImmutable()) - { - return true; - } - - const rx::Image *baseImage = getBaseLevelImage(); - - GLsizei width = baseImage->getWidth(); - GLsizei height = baseImage->getHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - // The base image level is complete if the width and height are positive - if (level == 0) - { - return true; - } - - ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); - rx::Image *image = mTexture->getImage(level, 0); - - if (image->getInternalFormat() != baseImage->getInternalFormat()) - { - return false; - } - - if (image->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (image->getHeight() != std::max(1, height >> level)) - { - return false; - } - - return true; -} - -TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_CUBE_MAP) -{ -} - -TextureCubeMap::~TextureCubeMap() -{ -} - -GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getWidth(); - else - return 0; -} - -GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getHeight(); - else - return 0; -} - -GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat(); - else - return GL_NONE; -} - -GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat(); - else - return GL_NONE; -} - -Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, 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) -{ - return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, 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) -{ - 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. -bool TextureCubeMap::isCubeComplete() const -{ - int baseWidth = getBaseLevelWidth(); - int baseHeight = getBaseLevelHeight(); - GLenum baseFormat = getBaseLevelInternalFormat(); - - if (baseWidth <= 0 || baseWidth != baseHeight) - { - return false; - } - - for (int faceIndex = 1; faceIndex < 6; faceIndex++) - { - const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex); - - if (faceBaseImage->getWidth() != baseWidth || - faceBaseImage->getHeight() != baseHeight || - faceBaseImage->getInternalFormat() != baseFormat ) - { - return false; - } - } - - return true; -} - -bool TextureCubeMap::isCompressed(GLenum target, GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(target, level)).compressed; -} - -bool TextureCubeMap::isDepth(GLenum target, GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0; -} - -Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, - GLsizei width, GLsizei height, Framebuffer *source) -{ - return mTexture->copyImage(target, level, format, x, y, width, height, source); -} - -Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) -{ - Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -// Tests for texture sampling completeness -bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - int size = getBaseLevelWidth(); - - bool mipmapping = IsMipmapFiltered(samplerState); - - if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - if (!gl::isPow2(size) && !extensions.textureNPOT) - { - if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) - { - return false; - } - } - - if (!mipmapping) - { - if (!isCubeComplete()) - { - return false; - } - } - else - { - if (!isMipmapComplete()) // Also tests for isCubeComplete() - { - return false; - } - } - - return true; -} - -int TextureCubeMap::targetToLayerIndex(GLenum target) -{ - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); - - return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X; -} - -GLenum TextureCubeMap::layerIndexToTarget(GLint layer) -{ - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); - - return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; -} - -bool TextureCubeMap::isMipmapComplete() const -{ - if (isImmutable()) - { - return true; - } - - if (!isCubeComplete()) - { - return false; - } - - int levelCount = mipLevels(); - - for (int face = 0; face < 6; face++) - { - for (int level = 1; level < levelCount; level++) - { - if (!isFaceLevelComplete(face, level)) - { - return false; - } - } - } - - return true; -} - -bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const -{ - ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL); - - if (isImmutable()) - { - return true; - } - - int baseSize = getBaseLevelWidth(); - - if (baseSize <= 0) - { - return false; - } - - // "isCubeComplete" checks for base level completeness and we must call that - // to determine if any face at level 0 is complete. We omit that check here - // to avoid re-checking cube-completeness for every face at level 0. - if (level == 0) - { - return true; - } - - // Check that non-zero levels are consistent with the base level. - const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex); - - if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) - { - return false; - } - - if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) - { - return false; - } - - return true; -} - - -Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_3D) -{ -} - -Texture3D::~Texture3D() -{ -} - -GLsizei Texture3D::getWidth(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0; -} - -GLsizei Texture3D::getHeight(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0; -} - -GLsizei Texture3D::getDepth(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0; -} - -GLenum Texture3D::getInternalFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; -} - -GLenum Texture3D::getActualFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; -} - -bool Texture3D::isCompressed(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).compressed; -} - -bool Texture3D::isDepth(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); -} - -Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, 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) -{ - return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, 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) -{ - return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); -} - -Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) - { - return false; - } - - return true; -} - -bool Texture3D::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 0; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; -} - -bool Texture3D::isLevelComplete(int level) const -{ - ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); - - if (isImmutable()) - { - return true; - } - - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (level == 0) - { - return true; - } - - rx::Image *levelImage = mTexture->getImage(level, 0); - - if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) - { - return false; - } - - if (levelImage->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (levelImage->getHeight() != std::max(1, height >> level)) - { - return false; - } - - if (levelImage->getDepth() != std::max(1, depth >> level)) - { - return false; - } - - return true; -} - -Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_2D_ARRAY) -{ -} - -Texture2DArray::~Texture2DArray() -{ -} - -GLsizei Texture2DArray::getWidth(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0; -} - -GLsizei Texture2DArray::getHeight(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0; -} - -GLsizei Texture2DArray::getLayers(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0; -} - -GLenum Texture2DArray::getInternalFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; -} - -GLenum Texture2DArray::getActualFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; -} - -bool Texture2DArray::isCompressed(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).compressed; -} - -bool Texture2DArray::isDepth(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); -} - -Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, 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) -{ - return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, 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) -{ - return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); -} - -Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayers(0); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) - { - return false; - } - - return true; -} - -bool Texture2DArray::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 1; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; -} - -bool Texture2DArray::isLevelComplete(int level) const -{ - ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (isImmutable()) - { - return true; - } - - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei layers = getLayers(0); - - if (width <= 0 || height <= 0 || layers <= 0) - { - return false; - } - - if (level == 0) - { - return true; - } - - if (getInternalFormat(level) != getInternalFormat(0)) - { - return false; - } - - if (getWidth(level) != std::max(1, width >> level)) - { - return false; - } - - if (getHeight(level) != std::max(1, height >> level)) - { - return false; - } - - if (getLayers(level) != layers) - { - return false; - } - - return true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h deleted file mode 100644 index 66d4df8015..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ /dev/null @@ -1,241 +0,0 @@ -// -// Copyright (c) 2002-2013 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. -// - -// Texture.h: Defines the abstract gl::Texture class and its concrete derived -// classes Texture2D and TextureCubeMap. Implements GL texture objects and -// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63. - -#ifndef LIBGLESV2_TEXTURE_H_ -#define LIBGLESV2_TEXTURE_H_ - -#include "common/debug.h" -#include "common/RefCountObject.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/renderer/TextureImpl.h" -#include "libGLESv2/Caps.h" - -#include "angle_gl.h" - -#include <vector> - -namespace egl -{ -class Surface; -} - -namespace rx -{ -class TextureStorageInterface; -class Image; -} - -namespace gl -{ -class Framebuffer; -class FramebufferAttachment; -struct ImageIndex; - -bool IsMipmapFiltered(const gl::SamplerState &samplerState); - -class Texture : public RefCountObject -{ - public: - Texture(rx::TextureImpl *impl, GLuint id, GLenum target); - - virtual ~Texture(); - - GLenum getTarget() const; - - const SamplerState &getSamplerState() const { return mSamplerState; } - SamplerState &getSamplerState() { return mSamplerState; } - - void setUsage(GLenum usage); - GLenum getUsage() const; - - GLint getBaseLevelWidth() const; - GLint getBaseLevelHeight() const; - GLint getBaseLevelDepth() const; - GLenum getBaseLevelInternalFormat() const; - - GLsizei getWidth(const ImageIndex &index) const; - GLsizei getHeight(const ImageIndex &index) const; - GLenum getInternalFormat(const ImageIndex &index) const; - GLenum getActualFormat(const ImageIndex &index) const; - - virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0; - - virtual Error generateMipmaps(); - - virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - - // 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; - GLsizei immutableLevelCount(); - - rx::TextureImpl *getImplementation() { return mTexture; } - const rx::TextureImpl *getImplementation() const { return mTexture; } - - static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. - - protected: - int mipLevels() const; - const rx::Image *getBaseLevelImage() const; - static unsigned int issueTextureSerial(); - - rx::TextureImpl *mTexture; - - SamplerState mSamplerState; - GLenum mUsage; - - GLsizei mImmutableLevelCount; - - GLenum mTarget; - - const unsigned int mTextureSerial; - static unsigned int mCurrentTextureSerial; - - private: - DISALLOW_COPY_AND_ASSIGN(Texture); -}; - -class Texture2D : public Texture -{ - public: - Texture2D(rx::TextureImpl *impl, GLuint id); - - virtual ~Texture2D(); - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isCompressed(GLint level) const; - bool isDepth(GLint level) const; - - 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 Error generateMipmaps(); - - private: - DISALLOW_COPY_AND_ASSIGN(Texture2D); - - bool isMipmapComplete() const; - bool isLevelComplete(int level) const; - - egl::Surface *mSurface; -}; - -class TextureCubeMap : public Texture -{ - public: - TextureCubeMap(rx::TextureImpl *impl, GLuint id); - - virtual ~TextureCubeMap(); - - GLsizei getWidth(GLenum target, GLint level) const; - GLsizei getHeight(GLenum target, GLint level) const; - GLenum getInternalFormat(GLenum target, GLint level) const; - GLenum getActualFormat(GLenum target, GLint level) const; - bool isCompressed(GLenum target, GLint level) const; - bool isDepth(GLenum target, GLint level) const; - - 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; - - bool isCubeComplete() const; - - static int targetToLayerIndex(GLenum target); - static GLenum layerIndexToTarget(GLint layer); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - - bool isMipmapComplete() const; - bool isFaceLevelComplete(int faceIndex, int level) const; -}; - -class Texture3D : public Texture -{ - public: - Texture3D(rx::TextureImpl *impl, GLuint id); - - virtual ~Texture3D(); - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLsizei getDepth(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isCompressed(GLint level) const; - bool isDepth(GLint level) const; - - 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; - - private: - DISALLOW_COPY_AND_ASSIGN(Texture3D); - - bool isMipmapComplete() const; - bool isLevelComplete(int level) const; -}; - -class Texture2DArray : public Texture -{ - public: - Texture2DArray(rx::TextureImpl *impl, GLuint id); - - virtual ~Texture2DArray(); - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLsizei getLayers(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isCompressed(GLint level) const; - bool isDepth(GLint level) const; - - 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; - - private: - DISALLOW_COPY_AND_ASSIGN(Texture2DArray); - - bool isMipmapComplete() const; - bool isLevelComplete(int level) const; -}; - -} - -#endif // LIBGLESV2_TEXTURE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp new file mode 100644 index 0000000000..a6db1585e7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp @@ -0,0 +1,1127 @@ +// +// 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. +// + +// entry_points_egl.cpp : Implements the EGL entry points. + +#include "libGLESv2/entry_points_egl.h" +#include "libGLESv2/entry_points_egl_ext.h" +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/entry_points_gles_3_0_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Display.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Surface.h" +#include "libANGLE/validationEGL.h" + +#include "common/debug.h" +#include "common/version.h" + +#include <EGL/eglext.h> + +namespace egl +{ + +// EGL 1.0 +EGLint EGLAPIENTRY GetError(void) +{ + EVENT("()"); + + EGLint error = GetGlobalError(); + SetGlobalError(Error(EGL_SUCCESS)); + return error; +} + +EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id) +{ + EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); + + return Display::getDisplay(display_id, AttributeMap()); +} + +EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", + dpy, major, minor); + + if (dpy == EGL_NO_DISPLAY) + { + SetGlobalError(Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; + } + + Display *display = static_cast<Display*>(dpy); + + Error error = display->initialize(); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (major) *major = 1; + if (minor) *minor = 4; + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); + + if (dpy == EGL_NO_DISPLAY) + { + SetGlobalError(Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; + } + + Display *display = static_cast<Display*>(dpy); + gl::Context *context = GetGlobalContext(); + + if (display->isValidContext(context)) + { + SetGlobalContext(NULL); + SetGlobalDisplay(NULL); + } + + display->terminate(); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); + + Display *display = static_cast<Display*>(dpy); + if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)) + { + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return NULL; + } + } + + const char *result; + switch (name) + { + case EGL_CLIENT_APIS: + result = "OpenGL_ES"; + break; + case EGL_EXTENSIONS: + if (display == EGL_NO_DISPLAY) + { + result = Display::getClientExtensionString().c_str(); + } + else + { + result = display->getExtensionString().c_str(); + } + break; + case EGL_VENDOR: + result = display->getVendorString().c_str(); + break; + case EGL_VERSION: + result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")"; + break; + default: + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return NULL; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return result; +} + +EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " + "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", + dpy, configs, config_size, num_config); + + Display *display = static_cast<Display*>(dpy); + + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!num_config) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap()); + if (configs) + { + filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size)); + for (size_t i = 0; i < filteredConfigs.size(); i++) + { + configs[i] = const_cast<Config*>(filteredConfigs[i]); + } + } + *num_config = filteredConfigs.size(); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " + "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", + dpy, attrib_list, configs, config_size, num_config); + + Display *display = static_cast<Display*>(dpy); + + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!num_config) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap(attrib_list)); + if (configs) + { + filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size)); + for (size_t i = 0; i < filteredConfigs.size(); i++) + { + configs[i] = const_cast<Config*>(filteredConfigs[i]); + } + } + *num_config = filteredConfigs.size(); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, config, attribute, value); + + Display *display = static_cast<Display*>(dpy); + Config *configuration = static_cast<Config*>(config); + + Error error = ValidateConfig(display, configuration); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!display->getConfigAttrib(configuration, attribute, value)) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); + + Display *display = static_cast<Display*>(dpy); + Config *configuration = static_cast<Config*>(config); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreateWindowSurface(display, configuration, win, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + egl::Surface *surface = nullptr; + error = display->createWindowSurface(configuration, win, attributes, &surface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + return static_cast<EGLSurface>(surface); +} + +EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", + dpy, config, attrib_list); + + Display *display = static_cast<Display*>(dpy); + Config *configuration = static_cast<Config*>(config); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreatePbufferSurface(display, configuration, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + egl::Surface *surface = nullptr; + error = display->createPbufferSurface(configuration, attributes, &surface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + return static_cast<EGLSurface>(surface); +} + +EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); + + Display *display = static_cast<Display*>(dpy); + Config *configuration = static_cast<Config*>(config); + + Error error = ValidateConfig(display, configuration); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_NO_SURFACE; +} + +EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + display->destroySurface((Surface*)surface); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, surface, attribute, value); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = (Surface*)surface; + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + switch (attribute) + { + case EGL_VG_ALPHA_FORMAT: + UNIMPLEMENTED(); // FIXME + break; + case EGL_VG_COLORSPACE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_CONFIG_ID: + *value = eglSurface->getConfig()->configID; + break; + case EGL_HEIGHT: + *value = eglSurface->getHeight(); + break; + case EGL_HORIZONTAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_LARGEST_PBUFFER: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_TEXTURE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_LEVEL: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MULTISAMPLE_RESOLVE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_PIXEL_ASPECT_RATIO: + *value = eglSurface->getPixelAspectRatio(); + break; + case EGL_RENDER_BUFFER: + *value = eglSurface->getRenderBuffer(); + break; + case EGL_SWAP_BEHAVIOR: + *value = eglSurface->getSwapBehavior(); + break; + case EGL_TEXTURE_FORMAT: + *value = eglSurface->getTextureFormat(); + break; + case EGL_TEXTURE_TARGET: + *value = eglSurface->getTextureTarget(); + break; + case EGL_VERTICAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_WIDTH: + *value = eglSurface->getWidth(); + break; + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + if (!display->getExtensions().postSubBuffer) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + *value = eglSurface->isPostSubBufferSupported(); + break; + case EGL_FIXED_SIZE_ANGLE: + if (!display->getExtensions().windowFixedSize) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + *value = eglSurface->isFixedSize(); + break; + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); + + Display *display = static_cast<Display*>(dpy); + Config *configuration = static_cast<Config*>(config); + gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_CONTEXT; + } + + gl::Context *context = nullptr; + error = display->createContext(configuration, sharedGLContext, attributes, &context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_CONTEXT; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return static_cast<EGLContext>(context); +} + +EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); + + Display *display = static_cast<Display*>(dpy); + gl::Context *context = static_cast<gl::Context*>(ctx); + + Error error = ValidateContext(display, context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (ctx == EGL_NO_CONTEXT) + { + SetGlobalError(Error(EGL_BAD_CONTEXT)); + return EGL_FALSE; + } + + if (context == GetGlobalContext()) + { + SetGlobalDisplay(NULL); + SetGlobalContext(NULL); + } + + display->destroyContext(context); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", + dpy, draw, read, ctx); + + Display *display = static_cast<Display*>(dpy); + gl::Context *context = static_cast<gl::Context*>(ctx); + + bool noContext = (ctx == EGL_NO_CONTEXT); + bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); + if (noContext != noSurface) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + if (ctx != EGL_NO_CONTEXT) + { + Error error = ValidateContext(display, context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + } + + if (dpy != EGL_NO_DISPLAY && display->isInitialized()) + { + if (display->testDeviceLost()) + { + display->notifyDeviceLost(); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + } + + Surface *drawSurface = static_cast<Surface*>(draw); + if (draw != EGL_NO_SURFACE) + { + Error error = ValidateSurface(display, drawSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + } + + Surface *readSurface = static_cast<Surface*>(read); + if (read != EGL_NO_SURFACE) + { + Error error = ValidateSurface(display, readSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + } + + if (draw != read) + { + UNIMPLEMENTED(); // FIXME + } + + SetGlobalDisplay(display); + SetGlobalDrawSurface(drawSurface); + SetGlobalReadSurface(readSurface); + SetGlobalContext(context); + + if (context != nullptr && display != nullptr && drawSurface != nullptr) + { + display->makeCurrent(drawSurface, readSurface, context); + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw) +{ + EVENT("(EGLint readdraw = %d)", readdraw); + + if (readdraw == EGL_READ) + { + SetGlobalError(Error(EGL_SUCCESS)); + return GetGlobalReadSurface(); + } + else if (readdraw == EGL_DRAW) + { + SetGlobalError(Error(EGL_SUCCESS)); + return GetGlobalDrawSurface(); + } + else + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_NO_SURFACE; + } +} + +EGLDisplay EGLAPIENTRY GetCurrentDisplay(void) +{ + EVENT("()"); + + EGLDisplay dpy = GetGlobalDisplay(); + + SetGlobalError(Error(EGL_SUCCESS)); + return dpy; +} + +EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, ctx, attribute, value); + + Display *display = static_cast<Display*>(dpy); + gl::Context *context = static_cast<gl::Context*>(ctx); + + Error error = ValidateContext(display, context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + switch (attribute) + { + case EGL_CONFIG_ID: + *value = context->getConfigID(); + break; + case EGL_CONTEXT_CLIENT_TYPE: + *value = context->getClientType(); + break; + case EGL_CONTEXT_CLIENT_VERSION: + *value = context->getClientVersion(); + break; + case EGL_RENDER_BUFFER: + *value = context->getRenderBuffer(); + break; + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY WaitGL(void) +{ + EVENT("()"); + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +EGLBoolean EGLAPIENTRY WaitNative(EGLint engine) +{ + EVENT("(EGLint engine = %d)", engine); + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = (Surface*)surface; + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + error = eglSurface->swap(); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +// EGL 1.1 +EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + if (eglSurface->getBoundTexture()) + { + SetGlobalError(Error(EGL_BAD_ACCESS)); + return EGL_FALSE; + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + gl::Context *context = GetGlobalContext(); + if (context) + { + gl::Texture *textureObject = context->getTargetTexture(GL_TEXTURE_2D); + ASSERT(textureObject != NULL); + + if (textureObject->isImmutable()) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + eglSurface->bindTexImage(textureObject, buffer); + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", + dpy, surface, attribute, value); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + gl::Texture *texture = eglSurface->getBoundTexture(); + + if (texture) + { + eglSurface->releaseTexImage(buffer); + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); + + Display *display = static_cast<Display*>(dpy); + + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + Surface *draw_surface = static_cast<Surface*>(GetGlobalDrawSurface()); + + if (draw_surface == NULL) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + const egl::Config *surfaceConfig = draw_surface->getConfig(); + EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), surfaceConfig->maxSwapInterval); + + draw_surface->setSwapInterval(clampedInterval); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + + +// EGL 1.2 +EGLBoolean EGLAPIENTRY BindAPI(EGLenum api) +{ + EVENT("(EGLenum api = 0x%X)", api); + + switch (api) + { + case EGL_OPENGL_API: + case EGL_OPENVG_API: + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; // Not supported by this implementation + case EGL_OPENGL_ES_API: + break; + default: + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + SetGlobalAPI(api); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLenum EGLAPIENTRY QueryAPI(void) +{ + EVENT("()"); + + EGLenum API = GetGlobalAPI(); + + SetGlobalError(Error(EGL_SUCCESS)); + return API; +} + +EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " + "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", + dpy, buftype, buffer, config, attrib_list); + + Display *display = static_cast<Display*>(dpy); + Config *configuration = static_cast<Config*>(config); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + egl::Surface *surface = nullptr; + error = display->createPbufferFromClientBuffer(configuration, buffer, attributes, &surface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + return static_cast<EGLSurface>(surface); +} + +EGLBoolean EGLAPIENTRY ReleaseThread(void) +{ + EVENT("()"); + + MakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY WaitClient(void) +{ + EVENT("()"); + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +// EGL 1.4 +EGLContext EGLAPIENTRY GetCurrentContext(void) +{ + EVENT("()"); + + gl::Context *context = GetGlobalContext(); + + SetGlobalError(Error(EGL_SUCCESS)); + return static_cast<EGLContext>(context); +} + +// EGL 1.5 +EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)", dpy, type, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_SYNC; +} + +EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p)", dpy, sync); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X, EGLTime timeout = %d)", dpy, sync, flags, timeout); + + UNIMPLEMENTED(); + return 0; +} + +EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint attribute = 0x%X, EGLAttrib *value = 0x%0.8p)", dpy, sync, attribute, value); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, " + "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)", + dpy, ctx, target, buffer, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_IMAGE; +} + +EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) +{ + EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + platform, native_display, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_DISPLAY; +} + +EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + dpy, config, native_window, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_SURFACE; +} + +EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + dpy, config, native_pixmap, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_SURFACE; +} + +EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync, flags); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +__eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname) +{ + EVENT("(const char *procname = \"%s\")", procname); + + struct Extension + { + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; + + static const Extension extensions[] = + { + { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)QuerySurfacePointerANGLE }, + { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)PostSubBufferNV }, + { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)GetPlatformDisplayEXT }, + { "glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)gl::BlitFramebufferANGLE }, + { "glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)gl::RenderbufferStorageMultisampleANGLE }, + { "glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)gl::DeleteFencesNV }, + { "glGenFencesNV", (__eglMustCastToProperFunctionPointerType)gl::GenFencesNV }, + { "glIsFenceNV", (__eglMustCastToProperFunctionPointerType)gl::IsFenceNV }, + { "glTestFenceNV", (__eglMustCastToProperFunctionPointerType)gl::TestFenceNV }, + { "glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)gl::GetFenceivNV }, + { "glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)gl::FinishFenceNV }, + { "glSetFenceNV", (__eglMustCastToProperFunctionPointerType)gl::SetFenceNV }, + { "glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)gl::GetTranslatedShaderSourceANGLE }, + { "glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)gl::TexStorage2DEXT }, + { "glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)gl::GetGraphicsResetStatusEXT }, + { "glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)gl::ReadnPixelsEXT }, + { "glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)gl::GetnUniformfvEXT }, + { "glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetnUniformivEXT }, + { "glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)gl::GenQueriesEXT }, + { "glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)gl::DeleteQueriesEXT }, + { "glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::IsQueryEXT }, + { "glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::BeginQueryEXT }, + { "glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::EndQueryEXT }, + { "glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetQueryivEXT }, + { "glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetQueryObjectuivEXT }, + { "glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)gl::DrawBuffersEXT }, + { "glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)gl::VertexAttribDivisorANGLE }, + { "glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)gl::DrawArraysInstancedANGLE }, + { "glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)gl::DrawElementsInstancedANGLE }, + { "glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)gl::GetProgramBinaryOES }, + { "glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)gl::ProgramBinaryOES }, + { "glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)gl::GetBufferPointervOES }, + { "glMapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::MapBufferOES }, + { "glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::UnmapBufferOES }, + { "glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::MapBufferRangeEXT }, + { "glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::FlushMappedBufferRangeEXT }, + { "", NULL }, + }; + + for (const Extension *extension = &extensions[0]; extension->address != nullptr; extension++) + { + if (strcmp(procname, extension->name) == 0) + { + return reinterpret_cast<__eglMustCastToProperFunctionPointerType>(extension->address); + } + } + + return NULL; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h new file mode 100644 index 0000000000..259a209684 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h @@ -0,0 +1,74 @@ +// +// 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. +// + +// entry_points_egl.h : Defines the EGL entry points. + +#ifndef LIBGLESV2_ENTRYPOINTSEGL_H_ +#define LIBGLESV2_ENTRYPOINTSEGL_H_ + +#include <EGL/egl.h> +#include <export.h> + +namespace egl +{ + +// EGL 1.0 +ANGLE_EXPORT EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +ANGLE_EXPORT EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetCurrentDisplay(void); +ANGLE_EXPORT EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw); +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id); +ANGLE_EXPORT EGLint EGLAPIENTRY GetError(void); +ANGLE_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +ANGLE_EXPORT const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitGL(void); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitNative(EGLint engine); + +// EGL 1.1 +ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval); + +// EGL 1.2 +ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindAPI(EGLenum api); +ANGLE_EXPORT EGLenum EGLAPIENTRY QueryAPI(void); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseThread(void); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitClient(void); + +// EGL 1.4 +ANGLE_EXPORT EGLContext EGLAPIENTRY GetCurrentContext(void); + +// EGL 1.5 +ANGLE_EXPORT EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync); +ANGLE_EXPORT EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +ANGLE_EXPORT EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image); +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags); + +} + +#endif // LIBGLESV2_ENTRYPOINTSEGL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp new file mode 100644 index 0000000000..ded73dbb48 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp @@ -0,0 +1,271 @@ +// +// 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. +// + +// entry_points_ext.cpp : Implements the EGL extension entry points. + +#include "libGLESv2/entry_points_egl_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/validationEGL.h" + +#include "common/debug.h" + +namespace egl +{ + +// EGL_ANGLE_query_surface_pointer +EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", + dpy, surface, attribute, value); + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!display->getExtensions().querySurfacePointer) + { + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + // validate the attribute parameter + switch (attribute) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + if (!display->getExtensions().surfaceD3DTexture2DShareHandle) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + break; + + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + error = eglSurface->querySurfacePointerANGLE(attribute, value); + SetGlobalError(error); + return (error.isError() ? EGL_FALSE : EGL_TRUE); +} + + +// EGL_NV_post_sub_buffer +EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); + + if (x < 0 || y < 0 || width < 0 || height < 0) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + Display *display = static_cast<Display*>(dpy); + Surface *eglSurface = static_cast<Surface*>(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + if (!display->getExtensions().postSubBuffer) + { + // Spec is not clear about how this should be handled. + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; + } + + error = eglSurface->postSubBuffer(x, y, width, height); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +// EGL_EXT_platform_base +EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +{ + EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + platform, native_display, attrib_list); + + const ClientExtensions &clientExtensions = Display::getClientExtensions(); + + switch (platform) + { + case EGL_PLATFORM_ANGLE_ANGLE: + if (!clientExtensions.platformANGLE) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_NO_DISPLAY; + } + break; + + default: + SetGlobalError(Error(EGL_BAD_CONFIG)); + return EGL_NO_DISPLAY; + } + + EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + EGLint deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE; + bool majorVersionSpecified = false; + bool minorVersionSpecified = false; + bool enableAutoTrimSpecified = false; + + if (attrib_list) + { + for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + switch (curAttrib[0]) + { + case EGL_PLATFORM_ANGLE_TYPE_ANGLE: + 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 (!clientExtensions.platformANGLED3D) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + if (!clientExtensions.platformANGLEOpenGL) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + break; + + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + 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_ENABLE_AUTOMATIC_TRIM_ANGLE: + switch (curAttrib[1]) + { + case EGL_TRUE: + case EGL_FALSE: + break; + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + enableAutoTrimSpecified = true; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE: + if (!clientExtensions.platformANGLED3D) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + + switch (curAttrib[1]) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + break; + + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + deviceType = curAttrib[1]; + break; + + default: + break; + } + } + } + + if (!majorVersionSpecified && minorVersionSpecified) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + + if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE && + platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE, "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a device type of " + "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.")); + return EGL_NO_DISPLAY; + } + + if (enableAutoTrimSpecified && + platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE, "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE requires a device type of " + "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.")); + return EGL_NO_DISPLAY; + } + + SetGlobalError(Error(EGL_SUCCESS)); + + EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display); + return Display::getDisplay(displayId, AttributeMap(attrib_list)); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h new file mode 100644 index 0000000000..9de1027082 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h @@ -0,0 +1,30 @@ +// +// 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. +// + +// entry_points_egl_ext.h : Defines the EGL extension entry points. + +#ifndef LIBGLESV2_ENTRYPOINTSEGLEXT_H_ +#define LIBGLESV2_ENTRYPOINTSEGLEXT_H_ + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <export.h> + +namespace egl +{ + +// EGL_ANGLE_query_surface_pointer +ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); + +// EGL_NV_post_sub_buffer +ANGLE_EXPORT EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); + +// EGL_EXT_platform_base +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list); + +} + +#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp new file mode 100644 index 0000000000..6d3089ba4f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp @@ -0,0 +1,4318 @@ +// +// 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. +// + +// entry_points_gles_2_0.cpp : Implements the GLES 2.0 entry points. + +#include "libGLESv2/entry_points_gles_2_0.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Program.h" +#include "libANGLE/Texture.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/FramebufferAttachment.h" + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/queryconversions.h" + +#include "common/debug.h" +#include "common/utilities.h" +#include "common/version.h" + +namespace gl +{ + +void GL_APIENTRY ActiveTexture(GLenum texture) +{ + EVENT("(GLenum texture = 0x%X)", texture); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setActiveSampler(texture - GL_TEXTURE0); + } +} + +void GL_APIENTRY AttachShader(GLuint program, GLuint shader) +{ + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + Shader *shaderObject = context->getShader(shader); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (!programObject->attachShader(shaderObject)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } +} + +void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name) +{ + EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (strncmp(name, "gl_", 3) == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + programObject->bindAttributeLocation(index, name); + } +} + +void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer) +{ + EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_ARRAY_BUFFER: + context->bindArrayBuffer(buffer); + return; + case GL_ELEMENT_ARRAY_BUFFER: + context->bindElementArrayBuffer(buffer); + return; + case GL_COPY_READ_BUFFER: + context->bindCopyReadBuffer(buffer); + return; + case GL_COPY_WRITE_BUFFER: + context->bindCopyWriteBuffer(buffer); + return; + case GL_PIXEL_PACK_BUFFER: + context->bindPixelPackBuffer(buffer); + return; + case GL_PIXEL_UNPACK_BUFFER: + context->bindPixelUnpackBuffer(buffer); + return; + case GL_UNIFORM_BUFFER: + context->bindGenericUniformBuffer(buffer); + return; + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindGenericTransformFeedbackBuffer(buffer); + return; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer) +{ + EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) + { + context->bindReadFramebuffer(framebuffer); + } + + if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) + { + context->bindDrawFramebuffer(framebuffer); + } + } +} + +void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (target != GL_RENDERBUFFER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->bindRenderbuffer(renderbuffer); + } +} + +void GL_APIENTRY BindTexture(GLenum target, GLuint texture) +{ + EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); + + Context *context = GetValidGlobalContext(); + if (context) + { + Texture *textureObject = context->getTexture(texture); + + if (textureObject && textureObject->getTarget() != target && texture != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + break; + + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->bindTexture(target, texture); + } +} + +void GL_APIENTRY BlendColor(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); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha)); + } +} + +void GL_APIENTRY BlendEquation(GLenum mode) +{ + BlendEquationSeparate(mode, mode); +} + +void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (modeRGB) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (modeAlpha) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setBlendEquation(modeRGB, modeAlpha); + } +} + +void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor) +{ + BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); +} + +void GL_APIENTRY BlendFuncSeparate(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); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (srcRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (dstRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + + case GL_SRC_ALPHA_SATURATE: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (srcAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (dstAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + + case GL_SRC_ALPHA_SATURATE: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || + dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); + + bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || + dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); + + if (constantColorUsed && constantAlphaUsed) + { + ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); + } +} + +void GL_APIENTRY BufferData(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); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (size < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (usage) + { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + + case GL_STREAM_READ: + case GL_STREAM_COPY: + case GL_STATIC_READ: + case GL_STATIC_COPY: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = buffer->bufferData(data, size, usage); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY BufferSubData(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); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (size < 0 || offset < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (data == NULL) + { + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Check for possible overflow of size + offset + if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset)) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return; + } + + if (size + offset > buffer->getSize()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Error error = buffer->bufferSubData(data, size, offset); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return 0; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + return framebuffer->checkStatus(context->getData()); + } + + return 0; +} + +void GL_APIENTRY Clear(GLbitfield mask) +{ + EVENT("(GLbitfield mask = 0x%X)", mask); + + Context *context = GetValidGlobalContext(); + if (context) + { + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return; + } + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Error error = framebufferObject->clear(context->getData(), mask); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearColor(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); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setColorClearValue(red, green, blue, alpha); + } +} + +void GL_APIENTRY ClearDepthf(GLclampf depth) +{ + EVENT("(GLclampf depth = %f)", depth); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setDepthClearValue(depth); + } +} + +void GL_APIENTRY ClearStencil(GLint s) +{ + EVENT("(GLint s = %d)", s); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setStencilClearValue(s); + } +} + +void GL_APIENTRY ColorMask(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); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); + } +} + +void GL_APIENTRY CompileShader(GLuint shader) +{ + EVENT("(GLuint shader = %d)", shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + shaderObject->compile(context->getCompiler()); + } +} + +void GL_APIENTRY CompressedTexImage2D(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, " + "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, border, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, width, height, border, GL_NONE, GL_NONE, data)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) + { + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CompressedTexSubImage2D(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, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " + "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + + Box area(xoffset, yoffset, 0, width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CopyTexImage2D(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)", + target, level, internalformat, x, y, width, height, border); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, x, y, width, height, border)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, 0, x, y, width, height, border)) + { + return; + } + + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->copyImage(target, level, sourceArea, internalformat, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, x, y, width, height, 0)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, 0, x, y, width, height, 0)) + { + return; + } + + Offset destOffset(xoffset, yoffset, 0); + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLuint GL_APIENTRY CreateProgram(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + if (context) + { + return context->createProgram(); + } + + return 0; +} + +GLuint GL_APIENTRY CreateShader(GLenum type) +{ + EVENT("(GLenum type = 0x%X)", type); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (type) + { + case GL_FRAGMENT_SHADER: + case GL_VERTEX_SHADER: + return context->createShader(type); + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return 0; + } + } + + return 0; +} + +void GL_APIENTRY CullFace(GLenum mode) +{ + EVENT("(GLenum mode = 0x%X)", mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (mode) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setCullMode(mode); + } +} + +void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers) +{ + EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteBuffer(buffers[i]); + } + } +} + +void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + if (framebuffers[i] != 0) + { + context->deleteFramebuffer(framebuffers[i]); + } + } + } +} + +void GL_APIENTRY DeleteProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (program == 0) + { + return; + } + + if (!context->getProgram(program)) + { + if(context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + context->deleteProgram(program); + } +} + +void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ + EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteRenderbuffer(renderbuffers[i]); + } + } +} + +void GL_APIENTRY DeleteShader(GLuint shader) +{ + EVENT("(GLuint shader = %d)", shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (shader == 0) + { + return; + } + + if (!context->getShader(shader)) + { + if(context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + context->deleteShader(shader); + } +} + +void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures) +{ + EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + if (textures[i] != 0) + { + context->deleteTexture(textures[i]); + } + } + } +} + +void GL_APIENTRY DepthFunc(GLenum func) +{ + EVENT("(GLenum func = 0x%X)", func); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_NOTEQUAL: + context->getState().setDepthFunc(func); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY DepthMask(GLboolean flag) +{ + EVENT("(GLboolean flag = %u)", flag); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setDepthMask(flag != GL_FALSE); + } +} + +void GL_APIENTRY DepthRangef(GLclampf zNear, GLclampf zFar) +{ + EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setDepthRange(zNear, zFar); + } +} + +void GL_APIENTRY DetachShader(GLuint program, GLuint shader) +{ + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + Shader *shaderObject = context->getShader(shader); + + if (!programObject) + { + Shader *shaderByProgramHandle; + shaderByProgramHandle = context->getShader(program); + if (!shaderByProgramHandle) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + else + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + + if (!shaderObject) + { + Program *programByShaderHandle = context->getProgram(shader); + if (!programByShaderHandle) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + else + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + + if (!programObject->detachShader(shaderObject)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } +} + +void GL_APIENTRY Disable(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidCap(context, cap)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setEnableFeature(cap, false); + } +} + +void GL_APIENTRY DisableVertexAttribArray(GLuint index) +{ + EVENT("(GLuint index = %d)", index); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setEnableVertexAttribArray(index, false); + } +} + +void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateDrawArrays(context, mode, first, count, 0)) + { + return; + } + + Error error = context->drawArrays(mode, first, count, 0); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", + mode, count, type, indices); + + Context *context = GetValidGlobalContext(); + if (context) + { + rx::RangeUI indexRange; + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) + { + return; + } + + Error error = context->drawElements(mode, count, type, indices, 0, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY Enable(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidCap(context, cap)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setEnableFeature(cap, true); + } +} + +void GL_APIENTRY EnableVertexAttribArray(GLuint index) +{ + EVENT("(GLuint index = %d)", index); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setEnableVertexAttribArray(index, true); + } +} + +void GL_APIENTRY Finish(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + if (context) + { + Error error = context->finish(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY Flush(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + if (context) + { + Error error = context->flush(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " + "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (renderbuffer != 0) + { + Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); + framebuffer->setRenderbufferAttachment(attachment, renderbufferObject); + } + else + { + framebuffer->setNULLAttachment(attachment); + } + } +} + +void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " + "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (texture != 0) + { + Texture *textureObj = context->getTexture(texture); + + ImageIndex index = ImageIndex::MakeInvalid(); + + if (textarget == GL_TEXTURE_2D) + { + index = ImageIndex::Make2D(level); + } + else + { + ASSERT(IsCubeMapTextureTarget(textarget)); + index = ImageIndex::MakeCube(textarget, level); + } + + framebuffer->setTextureAttachment(attachment, textureObj, index); + } + else + { + framebuffer->setNULLAttachment(attachment); + } + } +} + +void GL_APIENTRY FrontFace(GLenum mode) +{ + EVENT("(GLenum mode = 0x%X)", mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (mode) + { + case GL_CW: + case GL_CCW: + context->getState().setFrontFace(mode); + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers) +{ + EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + buffers[i] = context->createBuffer(); + } + } +} + +void GL_APIENTRY GenerateMipmap(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidTextureTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Texture *texture = context->getTargetTexture(target); + + if (texture == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target; + GLenum internalFormat = texture->getInternalFormat(baseTarget, 0); + const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat); + + // GenerateMipmap should not generate an INVALID_OPERATION for textures created with + // unsized formats or that are color renderable and filterable. Since we do not track if + // the texture was created with sized or unsized format (only sized formats are stored), + // it is not possible to make sure the the LUMA formats can generate mipmaps (they should + // be able to) because they aren't color renderable. Simply do a special case for LUMA + // textures since they're the only texture format that can be created with unsized formats + // that is not color renderable. New unsized formats are unlikely to be added, since ES2 + // was the last version to use add them. + bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || + internalFormat == GL_LUMINANCE8_ALPHA8_EXT || + internalFormat == GL_ALPHA8_EXT; + + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable || + (!formatCaps.renderable && !isLUMA) || formatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // GL_EXT_sRGB does not support mipmap generation on sRGB textures + if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Non-power of 2 ES2 check + if (!context->getExtensions().textureNPOT && (!isPow2(texture->getWidth(baseTarget, 0)) || !isPow2(texture->getHeight(baseTarget, 0)))) + { + ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Cube completeness check + if (target == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = texture->generateMipmaps(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers) +{ + EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + framebuffers[i] = context->createFramebuffer(); + } + } +} + +void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ + EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + renderbuffers[i] = context->createRenderbuffer(); + } + } +} + +void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures) +{ + EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + textures[i] = context->createTexture(); + } + } +} + +void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, " + "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", + program, index, bufsize, length, size, type, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (index >= (GLuint)programObject->getActiveAttributeCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveAttribute(index, bufsize, length, size, type, name); + } +} + +void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +{ + EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, " + "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufsize, length, size, type, name); + + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (index >= (GLuint)programObject->getActiveUniformCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveUniform(index, bufsize, length, size, type, name); + } +} + +void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ + EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", + program, maxcount, count, shaders); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (maxcount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + return programObject->getAttachedShaders(maxcount, count, shaders); + } +} + +GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name) +{ + EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return -1; + } + } + + if (!programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + return programObject->getAttributeLocation(name); + } + + return -1; +} + +void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params) +{ + EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_BOOL) + { + context->getBooleanv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferParameter(context, pname)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast<GLint>(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = clampCast<GLint>(buffer->getSize()); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = buffer->getAccessFlags(); + break; + case GL_BUFFER_MAPPED: + *params = static_cast<GLint>(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = clampCast<GLint>(buffer->getMapOffset()); + break; + case GL_BUFFER_MAP_LENGTH: + *params = clampCast<GLint>(buffer->getMapLength()); + break; + default: UNREACHABLE(); break; + } + } +} + +GLenum GL_APIENTRY GetError(void) +{ + EVENT("()"); + + Context *context = GetGlobalContext(); + + if (context) + { + return context->getError(); + } + + return GL_NO_ERROR; +} + +void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params) +{ + EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_FLOAT) + { + context->getFloatv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + target, attachment, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + int clientVersion = context->getClientVersion(); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + if (clientVersion < 3 && !context->getExtensions().sRGB) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + // Determine if the attachment is a valid enum + switch (attachment) + { + case GL_BACK: + case GL_FRONT: + case GL_DEPTH: + case GL_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + default: + if (attachment < GL_COLOR_ATTACHMENT0_EXT || + (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->id() == 0) + { + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (attachment) + { + case GL_BACK: + case GL_DEPTH: + case GL_STENCIL: + break; + + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + else + { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + // Valid attachment query + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (framebuffer->hasValidDepthStencil()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + + const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); + if (attachmentObject) + { + ASSERT(attachmentObject->type() == GL_RENDERBUFFER || + attachmentObject->type() == GL_TEXTURE || + attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObject->type(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (attachmentObject->type() != GL_RENDERBUFFER && attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->id(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + if (attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->mipLevel(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->cubeMapFace(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + *params = attachmentObject->getRedSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + *params = attachmentObject->getGreenSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + *params = attachmentObject->getBlueSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + *params = attachmentObject->getAlphaSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + *params = attachmentObject->getDepthSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + *params = attachmentObject->getStencilSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + *params = attachmentObject->getComponentType(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + *params = attachmentObject->getColorEncoding(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->layer(); + break; + + default: + UNREACHABLE(); + break; + } + } + else + { + // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE + // is NONE, then querying any other pname will generate INVALID_ENUM. + + // ES 3.0.2 spec pg 235 states that if the attachment type is none, + // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an + // INVALID_OPERATION for all other pnames + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = GL_NONE; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = 0; + break; + + default: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + else + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + } +} + +void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params) +{ + EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT) + { + context->getIntegerv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (context->getClientVersion() < 3) + { + switch (pname) + { + case GL_ACTIVE_UNIFORM_BLOCKS: + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + case GL_TRANSFORM_FEEDBACK_VARYINGS: + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } + + switch (pname) + { + case GL_DELETE_STATUS: + *params = programObject->isFlaggedForDeletion(); + return; + case GL_LINK_STATUS: + *params = programObject->isLinked(); + return; + case GL_VALIDATE_STATUS: + *params = programObject->isValidated(); + return; + case GL_INFO_LOG_LENGTH: + *params = programObject->getInfoLogLength(); + return; + case GL_ATTACHED_SHADERS: + *params = programObject->getAttachedShadersCount(); + return; + case GL_ACTIVE_ATTRIBUTES: + *params = programObject->getActiveAttributeCount(); + return; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = programObject->getActiveAttributeMaxLength(); + return; + case GL_ACTIVE_UNIFORMS: + *params = programObject->getActiveUniformCount(); + return; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = programObject->getActiveUniformMaxLength(); + return; + case GL_PROGRAM_BINARY_LENGTH_OES: + *params = programObject->getBinaryLength(); + return; + case GL_ACTIVE_UNIFORM_BLOCKS: + *params = programObject->getActiveUniformBlockCount(); + return; + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + *params = programObject->getActiveUniformBlockMaxLength(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + *params = programObject->getTransformFeedbackBufferMode(); + break; + case GL_TRANSFORM_FEEDBACK_VARYINGS: + *params = programObject->getTransformFeedbackVaryingCount(); + break; + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + *params = programObject->getTransformFeedbackVaryingMaxLength(); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ + EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", + program, bufsize, length, infolog); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getInfoLog(bufsize, length, infolog); + } +} + +void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (target != GL_RENDERBUFFER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (context->getState().getRenderbufferId() == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); + + switch (pname) + { + case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; + case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; + case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; + + case GL_RENDERBUFFER_SAMPLES_ANGLE: + if (!context->getExtensions().framebufferMultisample) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = renderbuffer->getSamples(); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ + EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_SHADER_TYPE: + *params = shaderObject->getType(); + return; + case GL_DELETE_STATUS: + *params = shaderObject->isFlaggedForDeletion(); + return; + case GL_COMPILE_STATUS: + *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; + return; + case GL_INFO_LOG_LENGTH: + *params = shaderObject->getInfoLogLength(); + return; + case GL_SHADER_SOURCE_LENGTH: + *params = shaderObject->getSourceLength(); + return; + case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: + *params = shaderObject->getTranslatedSourceLength(); + return; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", + shader, bufsize, length, infolog); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + shaderObject->getInfoLog(bufsize, length, infolog); + } +} + +void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", + shadertype, precisiontype, range, precision); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (shadertype) + { + case GL_VERTEX_SHADER: + switch (precisiontype) + { + case GL_LOW_FLOAT: + context->getCaps().vertexLowpFloat.get(range, precision); + break; + case GL_MEDIUM_FLOAT: + context->getCaps().vertexMediumpFloat.get(range, precision); + break; + case GL_HIGH_FLOAT: + context->getCaps().vertexHighpFloat.get(range, precision); + break; + + case GL_LOW_INT: + context->getCaps().vertexLowpInt.get(range, precision); + break; + case GL_MEDIUM_INT: + context->getCaps().vertexMediumpInt.get(range, precision); + break; + case GL_HIGH_INT: + context->getCaps().vertexHighpInt.get(range, precision); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + case GL_FRAGMENT_SHADER: + switch (precisiontype) + { + case GL_LOW_FLOAT: + context->getCaps().fragmentLowpFloat.get(range, precision); + break; + case GL_MEDIUM_FLOAT: + context->getCaps().fragmentMediumpFloat.get(range, precision); + break; + case GL_HIGH_FLOAT: + context->getCaps().fragmentHighpFloat.get(range, precision); + break; + + case GL_LOW_INT: + context->getCaps().fragmentLowpInt.get(range, precision); + break; + case GL_MEDIUM_INT: + context->getCaps().fragmentMediumpInt.get(range, precision); + break; + case GL_HIGH_INT: + context->getCaps().fragmentHighpInt.get(range, precision); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + } +} + +void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", + shader, bufsize, length, source); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + shaderObject->getSource(bufsize, length, source); + } +} + +const GLubyte *GL_APIENTRY GetString(GLenum name) +{ + EVENT("(GLenum name = 0x%X)", name); + + Context *context = GetValidGlobalContext(); + + switch (name) + { + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + + case GL_RENDERER: + return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); + + case GL_VERSION: + if (context->getClientVersion() == 2) + { + return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + else + { + return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + + case GL_SHADING_LANGUAGE_VERSION: + if (context->getClientVersion() == 2) + { + return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + else + { + return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + + case GL_EXTENSIONS: + return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); + + default: + if (context) + { + context->recordError(Error(GL_INVALID_ENUM)); + } + return NULL; + } +} + +void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat)texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat)texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat)texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat)texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = (GLfloat)texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLod; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = static_cast<GLint>(texture->immutableLevelCount()); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().maxLod; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetUniformfv(context, program, location, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformfv(location, params); + } +} + +void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetUniformiv(context, program, location, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformiv(location, params); + } +} + +GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name) +{ + EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (strstr(name, "gl_") == name) + { + return -1; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return -1; + } + } + + if (!programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + return programObject->getUniformLocation(name); + } + + return -1; +} + +void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.FloatValues[i]; + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname); + } + } +} + +void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + float currentValue = currentValueData.FloatValues[i]; + params[i] = iround<GLint>(currentValue); + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname); + } + } +} + +void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index)); + } +} + +void GL_APIENTRY Hint(GLenum target, GLenum mode) +{ + EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (mode) + { + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_GENERATE_MIPMAP_HINT: + context->getState().setGenerateMipmapHint(mode); + break; + + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + context->getState().setFragmentShaderDerivativeHint(mode); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +GLboolean GL_APIENTRY IsBuffer(GLuint buffer) +{ + EVENT("(GLuint buffer = %d)", buffer); + + Context *context = GetValidGlobalContext(); + if (context && buffer) + { + Buffer *bufferObject = context->getBuffer(buffer); + + if (bufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsEnabled(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidCap(context, cap)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return GL_FALSE; + } + + return context->getState().getEnableFeature(cap); + } + + return false; +} + +GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer) +{ + EVENT("(GLuint framebuffer = %d)", framebuffer); + + Context *context = GetValidGlobalContext(); + if (context && framebuffer) + { + Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); + + if (framebufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context && program) + { + Program *programObject = context->getProgram(program); + + if (programObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer) +{ + EVENT("(GLuint renderbuffer = %d)", renderbuffer); + + Context *context = GetValidGlobalContext(); + if (context && renderbuffer) + { + Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); + + if (renderbufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsShader(GLuint shader) +{ + EVENT("(GLuint shader = %d)", shader); + + Context *context = GetValidGlobalContext(); + if (context && shader) + { + Shader *shaderObject = context->getShader(shader); + + if (shaderObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsTexture(GLuint texture) +{ + EVENT("(GLuint texture = %d)", texture); + + Context *context = GetValidGlobalContext(); + if (context && texture) + { + Texture *textureObject = context->getTexture(texture); + + if (textureObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +void GL_APIENTRY LineWidth(GLfloat width) +{ + EVENT("(GLfloat width = %f)", width); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width <= 0.0f) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setLineWidth(width); + } +} + +void GL_APIENTRY LinkProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + Error error = programObject->link(context->getData()); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY PixelStorei(GLenum pname, GLint param) +{ + EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + switch (pname) + { + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_IMAGES: + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_PIXELS: + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_ROWS: + case GL_PACK_SKIP_PIXELS: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } + + if (param < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei")); + return; + } + + State &state = context->getState(); + + switch (pname) + { + case GL_UNPACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + state.setUnpackAlignment(param); + break; + + case GL_PACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + state.setPackAlignment(param); + break; + + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + state.setPackReverseRowOrder(param != 0); + break; + + case GL_UNPACK_ROW_LENGTH: + ASSERT(context->getClientVersion() >= 3); + state.setUnpackRowLength(param); + break; + + case GL_UNPACK_IMAGE_HEIGHT: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().imageHeight = param; + break; + + case GL_UNPACK_SKIP_IMAGES: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().skipImages = param; + break; + + case GL_UNPACK_SKIP_ROWS: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().skipRows = param; + break; + + case GL_UNPACK_SKIP_PIXELS: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().skipPixels = param; + break; + + case GL_PACK_ROW_LENGTH: + ASSERT(context->getClientVersion() >= 3); + state.getPackState().rowLength = param; + break; + + case GL_PACK_SKIP_ROWS: + ASSERT(context->getClientVersion() >= 3); + state.getPackState().skipRows = param; + break; + + case GL_PACK_SKIP_PIXELS: + ASSERT(context->getClientVersion() >= 3); + state.getPackState().skipPixels = param; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units) +{ + EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setPolygonOffsetParams(factor, units); + } +} + +void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid* pixels) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", + x, y, width, height, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateReadPixelsParameters(context, x, y, width, height, + format, type, NULL, pixels)) + { + return; + } + + Framebuffer *framebufferObject = context->getState().getReadFramebuffer(); + ASSERT(framebufferObject); + + Rectangle area(x, y, width, height); + Error error = framebufferObject->readPixels(context->getState(), area, format, type, pixels); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ReleaseShaderCompiler(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + + if (context) + { + Compiler *compiler = context->getCompiler(); + Error error = compiler->release(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateRenderbufferStorageParametersANGLE(context, target, 0, internalformat, + width, height)) + { + return; + } + + Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + Error error = renderbuffer->setStorage(internalformat, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY SampleCoverage(GLclampf value, GLboolean invert) +{ + EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); + + Context* context = GetValidGlobalContext(); + + if (context) + { + context->getState().setSampleCoverageParams(clamp01(value), invert == GL_TRUE); + } +} + +void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + Context* context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setScissorParams(x, y, width, height); + } +} + +void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +{ + EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " + "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + n, shaders, binaryformat, binary, length); + + Context* context = GetValidGlobalContext(); + if (context) + { + const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats; + if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end()) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + // No binary shader formats are supported. + UNIMPLEMENTED(); + } +} + +void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) +{ + EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", + shader, count, string, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + shaderObject->setSource(count, string, length); + } +} + +void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask) +{ + StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); +} + +void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilParams(func, ref, mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackParams(func, ref, mask); + } + } +} + +void GL_APIENTRY StencilMask(GLuint mask) +{ + StencilMaskSeparate(GL_FRONT_AND_BACK, mask); +} + +void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask) +{ + EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilWritemask(mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackWritemask(mask); + } + } +} + +void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); +} + +void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", + face, fail, zfail, zpass); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (fail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (zfail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (zpass) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilOperations(fail, zfail, zpass); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackOperations(fail, zfail, zpass); + } + } +} + +void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " + "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, border, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, width, height, border, format, type, pixels)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, 1, border, format, type, pixels)) + { + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param))) + { + return; + } + + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = uiround<GLenum>(param); break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = uiround<GLenum>(param); break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = uiround<GLenum>(param); break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = uiround<GLenum>(param); break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = uiround<GLenum>(param); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(uiround<GLenum>(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = uiround<GLenum>(param); break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = uiround<GLenum>(param); break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = iround<GLint>(param); break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = iround<GLint>(param); break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; + default: UNREACHABLE(); break; + } + } +} + +void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +{ + TexParameterf(target, pname, (GLfloat)*params); +} + +void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateTexParamParameters(context, pname, param)) + { + return; + } + + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; + default: UNREACHABLE(); break; + } + } +} + +void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + TexParameteri(target, pname, *params); +} + +void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " + "const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, width, height, 0, format, type, pixels)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + Box area(xoffset, yoffset, 0, width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY Uniform1f(GLint location, GLfloat x) +{ + Uniform1fv(location, 1, &x); +} + +void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform1fv(location, count, v); + } +} + +void GL_APIENTRY Uniform1i(GLint location, GLint x) +{ + Uniform1iv(location, 1, &x); +} + +void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform1iv(location, count, v); + } +} + +void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y) +{ + GLfloat xy[2] = {x, y}; + + Uniform2fv(location, 1, xy); +} + +void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform2fv(location, count, v); + } +} + +void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y) +{ + GLint xy[2] = {x, y}; + + Uniform2iv(location, 1, xy); +} + +void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC2, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform2iv(location, count, v); + } +} + +void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat xyz[3] = {x, y, z}; + + Uniform3fv(location, 1, xyz); +} + +void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform3fv(location, count, v); + } +} + +void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z) +{ + GLint xyz[3] = {x, y, z}; + + Uniform3iv(location, 1, xyz); +} + +void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC3, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform3iv(location, count, v); + } +} + +void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GLfloat xyzw[4] = {x, y, z, w}; + + Uniform4fv(location, 1, xyzw); +} + +void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform4fv(location, count, v); + } +} + +void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + GLint xyzw[4] = {x, y, z, w}; + + Uniform4iv(location, 1, xyzw); +} + +void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC4, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform4iv(location, count, v); + } +} + +void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix2fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix3fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix4fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UseProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject && program != 0) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (program != 0 && !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->useProgram(program); + } +} + +void GL_APIENTRY ValidateProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + programObject->validate(context->getCaps()); + } +} + +void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x) +{ + EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { values[0], 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, y, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { values[0], values[1], 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, y, z, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { values[0], values[1], values[2], 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, y, z, w }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribf(index, values); + } +} + +void GL_APIENTRY VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ + EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " + "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", + index, size, type, normalized, stride, ptr); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (size < 1 || size > 4) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + + case GL_HALF_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (stride < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, + normalized == GL_TRUE, false, stride, ptr); + } +} + +void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setViewportParams(x, y, width, height); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h new file mode 100644 index 0000000000..eee5fb5468 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h @@ -0,0 +1,163 @@ +// +// 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. +// + +// entry_points_gles_2_0.h : Defines the GLES 2.0 entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES20_H_ +#define LIBGLESV2_ENTRYPOINTGLES20_H_ + +#include <GLES2/gl2.h> +#include <export.h> + +namespace gl +{ + +ANGLE_EXPORT void GL_APIENTRY ActiveTexture(GLenum texture); +ANGLE_EXPORT void GL_APIENTRY AttachShader(GLuint program, GLuint shader); +ANGLE_EXPORT void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name); +ANGLE_EXPORT void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer); +ANGLE_EXPORT void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer); +ANGLE_EXPORT void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer); +ANGLE_EXPORT void GL_APIENTRY BindTexture(GLenum target, GLuint texture); +ANGLE_EXPORT void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +ANGLE_EXPORT void GL_APIENTRY BlendEquation(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); +ANGLE_EXPORT void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor); +ANGLE_EXPORT void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +ANGLE_EXPORT void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +ANGLE_EXPORT void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +ANGLE_EXPORT GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target); +ANGLE_EXPORT void GL_APIENTRY Clear(GLbitfield mask); +ANGLE_EXPORT void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +ANGLE_EXPORT void GL_APIENTRY ClearDepthf(GLfloat depth); +ANGLE_EXPORT void GL_APIENTRY ClearStencil(GLint s); +ANGLE_EXPORT void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +ANGLE_EXPORT void GL_APIENTRY CompileShader(GLuint shader); +ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT GLuint GL_APIENTRY CreateProgram(void); +ANGLE_EXPORT GLuint GL_APIENTRY CreateShader(GLenum type); +ANGLE_EXPORT void GL_APIENTRY CullFace(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers); +ANGLE_EXPORT void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers); +ANGLE_EXPORT void GL_APIENTRY DeleteProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); +ANGLE_EXPORT void GL_APIENTRY DeleteShader(GLuint shader); +ANGLE_EXPORT void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures); +ANGLE_EXPORT void GL_APIENTRY DepthFunc(GLenum func); +ANGLE_EXPORT void GL_APIENTRY DepthMask(GLboolean flag); +ANGLE_EXPORT void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f); +ANGLE_EXPORT void GL_APIENTRY DetachShader(GLuint program, GLuint shader); +ANGLE_EXPORT void GL_APIENTRY Disable(GLenum cap); +ANGLE_EXPORT void GL_APIENTRY DisableVertexAttribArray(GLuint index); +ANGLE_EXPORT void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count); +ANGLE_EXPORT void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +ANGLE_EXPORT void GL_APIENTRY Enable(GLenum cap); +ANGLE_EXPORT void GL_APIENTRY EnableVertexAttribArray(GLuint index); +ANGLE_EXPORT void GL_APIENTRY Finish(void); +ANGLE_EXPORT void GL_APIENTRY Flush(void); +ANGLE_EXPORT void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +ANGLE_EXPORT void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +ANGLE_EXPORT void GL_APIENTRY FrontFace(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers); +ANGLE_EXPORT void GL_APIENTRY GenerateMipmap(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers); +ANGLE_EXPORT void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers); +ANGLE_EXPORT void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures); +ANGLE_EXPORT void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); +ANGLE_EXPORT GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params); +ANGLE_EXPORT void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT GLenum GL_APIENTRY GetError(void); +ANGLE_EXPORT void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); +ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); +ANGLE_EXPORT void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); +ANGLE_EXPORT void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); +ANGLE_EXPORT const GLubyte *GL_APIENTRY GetString(GLenum name); +ANGLE_EXPORT void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params); +ANGLE_EXPORT GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer); +ANGLE_EXPORT void GL_APIENTRY Hint(GLenum target, GLenum mode); +ANGLE_EXPORT GLboolean GL_APIENTRY IsBuffer(GLuint buffer); +ANGLE_EXPORT GLboolean GL_APIENTRY IsEnabled(GLenum cap); +ANGLE_EXPORT GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer); +ANGLE_EXPORT GLboolean GL_APIENTRY IsProgram(GLuint program); +ANGLE_EXPORT GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer); +ANGLE_EXPORT GLboolean GL_APIENTRY IsShader(GLuint shader); +ANGLE_EXPORT GLboolean GL_APIENTRY IsTexture(GLuint texture); +ANGLE_EXPORT void GL_APIENTRY LineWidth(GLfloat width); +ANGLE_EXPORT void GL_APIENTRY LinkProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY PixelStorei(GLenum pname, GLint param); +ANGLE_EXPORT void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units); +ANGLE_EXPORT void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY ReleaseShaderCompiler(void); +ANGLE_EXPORT void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert); +ANGLE_EXPORT void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); +ANGLE_EXPORT void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); +ANGLE_EXPORT void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilMask(GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass); +ANGLE_EXPORT void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +ANGLE_EXPORT void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param); +ANGLE_EXPORT void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param); +ANGLE_EXPORT void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params); +ANGLE_EXPORT void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY Uniform1f(GLint location, GLfloat x); +ANGLE_EXPORT void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform1i(GLint location, GLint x); +ANGLE_EXPORT void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y); +ANGLE_EXPORT void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y); +ANGLE_EXPORT void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z); +ANGLE_EXPORT void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z); +ANGLE_EXPORT void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +ANGLE_EXPORT void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w); +ANGLE_EXPORT void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UseProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY ValidateProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib1f(GLuint indx, GLfloat x); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib1fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib2fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib3fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib4fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); +ANGLE_EXPORT void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height); + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES20_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp new file mode 100644 index 0000000000..8be6ae7d2f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp @@ -0,0 +1,1058 @@ +// +// 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. +// + +// entry_points_gles_2_0_ext.cpp : Implements the GLES 2.0 extension entry points. + +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" +#include "libANGLE/Fence.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Query.h" + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES3.h" + +#include "common/debug.h" +#include "common/utilities.h" + +namespace gl +{ + +void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + + Error error = context->beginQuery(target, id); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences) +{ + EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteFenceNV(fences[i]); + } + } +} + +void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids) +{ + EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); + } + } +} + +void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) + { + return; + } + + Error error = context->drawArrays(mode, first, count, primcount); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", + mode, count, type, indices, primcount); + + Context *context = GetValidGlobalContext(); + if (context) + { + rx::RangeUI indexRange; + if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange)) + { + return; + } + + Error error = context->drawElements(mode, count, type, indices, primcount, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY EndQueryEXT(GLenum target) +{ + EVENT("GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateEndQuery(context, target)) + { + return; + } + + Error error = context->endQuery(target); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY FinishFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + fenceObject->finishFence(); + } +} + +void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences) +{ + EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + fences[i] = context->createFenceNV(); + } + } +} + +void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); + } + } +} + +void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + 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. + GLboolean status = GL_TRUE; + if (fenceObject->getStatus() != GL_TRUE) + { + Error error = fenceObject->testFence(&status); + if (error.isError()) + { + context->recordError(error); + return; + } + } + *params = status; + break; + } + + case GL_FENCE_CONDITION_NV: + { + *params = static_cast<GLint>(fenceObject->getCondition()); + break; + } + + default: + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } + } +} + +GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void) +{ + EVENT("()"); + + Context *context = GetGlobalContext(); + + if (context) + { + return context->getResetStatus(); + } + + return GL_NO_ERROR; +} + +void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params) +{ + EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidQueryType(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_CURRENT_QUERY_EXT: + params[0] = context->getState().getActiveQueryId(target); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) +{ + EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch(pname) + { + case GL_QUERY_RESULT_EXT: + { + Error error = queryObject->getResult(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + case GL_QUERY_RESULT_AVAILABLE_EXT: + { + Error error = queryObject->isResultAvailable(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", + shader, bufsize, length, source); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined + shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source); + } +} + +void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", + program, location, bufSize, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformfv(location, params); + } +} + +void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", + program, location, bufSize, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformiv(location, params); + } +} + +GLboolean GL_APIENTRY IsFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + return GL_FALSE; + } + + return fenceObject->isFence(); + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsQueryEXT(GLuint id) +{ + EVENT("(GLuint id = %d)", id); + + Context *context = GetValidGlobalContext(); + if (context) + { + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; + } + + return GL_FALSE; +} + +void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei bufSize, + GLvoid *data) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)", + x, y, width, height, format, type, bufSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0 || bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateReadPixelsParameters(context, x, y, width, height, + format, type, &bufSize, data)) + { + return; + } + + Framebuffer *framebufferObject = context->getState().getReadFramebuffer(); + ASSERT(framebufferObject); + + Rectangle area(x, y, width, height); + Error error = framebufferObject->readPixels(context->getState(), area, format, type, data); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateRenderbufferStorageParametersANGLE(context, target, samples, internalformat, + width, height)) + { + return; + } + + Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + Error error = renderbuffer->setStorageMultisample(samples, internalformat, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition) +{ + EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (condition != GL_ALL_COMPLETED_NV) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = fenceObject->setFence(condition); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLboolean GL_APIENTRY TestFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_TRUE; + } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_TRUE; + } + + GLboolean result; + Error error = fenceObject->testFence(&result); + if (error.isError()) + { + context->recordError(error); + return GL_TRUE; + } + + return result; + } + + return GL_TRUE; +} + +void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!context->getExtensions().textureStorage) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getClientVersion() < 3 && + !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setStorage(target, levels, internalformat, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->setVertexAttribDivisor(index, divisor); + } +} + +void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " + "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " + "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + true)) + { + return; + } + + Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + ASSERT(readFramebuffer); + + Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + ASSERT(drawFramebuffer); + + Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + + Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " + "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + UNIMPLEMENTED(); // FIXME +} + +void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) +{ + EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length) +{ + EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", + program, binaryFormat, binary, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats; + if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end()) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Program *programObject = context->getProgram(program); + if (!programObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = programObject->loadBinary(binaryFormat, binary, length); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs) +{ + EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + ASSERT(context->getState().getDrawFramebuffer()); + + if (context->getState().getDrawFramebuffer()->id() == 0) + { + if (n != 1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + else + { + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + + Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); + ASSERT(framebuffer); + + framebuffer->setDrawBuffers(n, bufs); + } +} + +void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void** params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (pname != GL_BUFFER_MAP_POINTER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer || !buffer->isMapped()) + { + *params = NULL; + } + else + { + *params = buffer->getMapPointer(); + } + } +} + +void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access) +{ + EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + if (access != GL_WRITE_ONLY_OES) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + if (buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); + if (error.isError()) + { + context->recordError(error); + return NULL; + } + + return buffer->getMapPointer(); + } + + return NULL; +} + +GLboolean GL_APIENTRY UnmapBufferOES(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return GL_FALSE; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL || !buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + // TODO: detect if we had corruption. if so, throw an error and return false. + + Error error = buffer->unmap(); + if (error.isError()) + { + context->recordError(error); + return GL_FALSE; + } + + return GL_TRUE; + } + + return GL_FALSE; +} + +void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + if (offset < 0 || length < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + // Check for buffer overflow + size_t offsetSize = static_cast<size_t>(offset); + size_t lengthSize = static_cast<size_t>(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast<size_t>(buffer->getSize())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + // Check for invalid bits in the mask + GLbitfield allAccessBits = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if (access & ~(allAccessBits)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + if (length == 0 || buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + // Check for invalid bit combinations + if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + Error error = buffer->mapRange(offset, length, access); + if (error.isError()) + { + context->recordError(error); + return NULL; + } + + return buffer->getMapPointer(); + } + + return NULL; +} + +void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (offset < 0 || length < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Check for buffer overflow + size_t offsetSize = static_cast<size_t>(offset); + size_t lengthSize = static_cast<size_t>(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // We do not currently support a non-trivial implementation of FlushMappedBufferRange + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h new file mode 100644 index 0000000000..816519fe1f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h @@ -0,0 +1,78 @@ +// +// 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. +// + +// entry_points_gles_2_0_ext.h : Defines the GLES 2.0 extension entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES20EXT_H_ +#define LIBGLESV2_ENTRYPOINTGLES20EXT_H_ + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <export.h> + +namespace gl +{ + +// GL_ANGLE_framebuffer_blit +ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +// GL_ANGLE_framebuffer_multisample +ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +// GL_NV_fence +ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences); +ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences); +ANGLE_EXPORT GLboolean GL_APIENTRY IsFenceNV(GLuint fence); +ANGLE_EXPORT GLboolean GL_APIENTRY TestFenceNV(GLuint fence); +ANGLE_EXPORT void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params); +ANGLE_EXPORT void GL_APIENTRY FinishFenceNV(GLuint fence); +ANGLE_EXPORT void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition); + +// GL_ANGLE_translated_shader_source +ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); + +// GL_EXT_texture_storage +ANGLE_EXPORT void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + +// GL_EXT_robustness +ANGLE_EXPORT GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void); +ANGLE_EXPORT void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +ANGLE_EXPORT void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params); +ANGLE_EXPORT void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params); + +// GL_EXT_occlusion_query_boolean +ANGLE_EXPORT void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids); +ANGLE_EXPORT void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids); +ANGLE_EXPORT GLboolean GL_APIENTRY IsQueryEXT(GLuint id); +ANGLE_EXPORT void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id); +ANGLE_EXPORT void GL_APIENTRY EndQueryEXT(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params); +ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params); + +// GL_EXT_draw_buffers +ANGLE_EXPORT void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs); + +// GL_ANGLE_instanced_arrays +ANGLE_EXPORT void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); +ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor); + +// GL_OES_get_program_binary +ANGLE_EXPORT void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); +ANGLE_EXPORT void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); + +// GL_OES_mapbuffer +ANGLE_EXPORT void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access); +ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBufferOES(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params); + +// GL_EXT_map_buffer_range +ANGLE_EXPORT void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length); + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp new file mode 100644 index 0000000000..d8bdcd2e50 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp @@ -0,0 +1,3394 @@ +// +// 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. +// + +// entry_points_gles_3_0.cpp : Implements the GLES 3.0 entry points. + +#include "libGLESv2/entry_points_gles_3_0.h" +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" +#include "libANGLE/Fence.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/queryconversions.h" + +#include "common/debug.h" + +namespace gl +{ + +void GL_APIENTRY ReadBuffer(GLenum mode) +{ + EVENT("(GLenum mode = 0x%X)", mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateReadBuffer(context, mode)) + { + return; + } + + Framebuffer *readFBO = context->getState().getReadFramebuffer(); + readFBO->setReadBuffer(mode); + } +} + +void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) +{ + EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " + "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + rx::RangeUI indexRange; + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) + { + return; + } + if (indexRange.end > end || indexRange.start < start) + { + // GL spec says that behavior in this case is undefined - generating an error is fine. + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // As long as index validation is done, it doesn't matter whether the context receives a drawElements or + // a drawRangeElements call - the GL back-end is free to choose to call drawRangeElements based on the + // validated index range. If index validation is removed, adding drawRangeElements to the context interface + // should be reconsidered. + Error error = context->drawElements(mode, count, type, indices, 0, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " + "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, depth, border, format, type, pixels)) + { + return; + } + + Extents size(width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, zoffset, width, height, depth, 0, + format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0 || depth == 0) + { + return; + } + + Box area(xoffset, yoffset, zoffset, width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, zoffset, x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, + x, y, width, height, 0)) + { + return; + } + + Offset destOffset(xoffset, yoffset, zoffset); + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + Texture *texture = context->getTargetTexture(target); + Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " + "const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) + { + return; + } + + Extents size(width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!data) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + Box area(xoffset, yoffset, zoffset, width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(), + reinterpret_cast<const uint8_t *>(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); + } + } +} + +void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); + } + } +} + +GLboolean GL_APIENTRY IsQuery(GLuint id) +{ + EVENT("(GLuint id = %u)", id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; + } + + return GL_FALSE; +} + +void GL_APIENTRY BeginQuery(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + + Error error = context->beginQuery(target, id); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY EndQuery(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateEndQuery(context, target)) + { + return; + } + + Error error = context->endQuery(target); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidQueryType(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_CURRENT_QUERY: + params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target)); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) +{ + EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch(pname) + { + case GL_QUERY_RESULT_EXT: + { + Error error = queryObject->getResult(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + case GL_QUERY_RESULT_AVAILABLE_EXT: + { + Error error = queryObject->isResultAvailable(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +GLboolean GL_APIENTRY UnmapBuffer(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return UnmapBufferOES(target); + } + + return GL_FALSE; +} + +void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + GetBufferPointervOES(target, pname, params); + } +} + +void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs) +{ + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + DrawBuffersEXT(n, bufs); + } +} + +void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix2x3fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix3x2fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix2x4fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix4x2fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix3x4fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix4x3fv(location, count, transpose, value); + } +} + +void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " + "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + false)) + { + return; + } + + Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + ASSERT(readFramebuffer); + + Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + ASSERT(drawFramebuffer); + + Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + + Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3RenderbufferStorageParameters(context, target, samples, internalformat, width, height)) + { + return; + } + + Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + renderbuffer->setStorageMultisample(samples, internalformat, width, height); + } +} + +void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", + target, attachment, texture, level, layer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, + level, layer)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (texture != 0) + { + Texture *textureObject = context->getTexture(texture); + + ImageIndex index = ImageIndex::MakeInvalid(); + + if (textureObject->getTarget() == GL_TEXTURE_3D) + { + index = ImageIndex::Make3D(level, layer); + } + else + { + ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY); + index = ImageIndex::Make2DArray(level, layer); + } + + framebuffer->setTextureAttachment(attachment, textureObject, index); + } + else + { + framebuffer->setNULLAttachment(attachment); + } + } +} + +GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + return MapBufferRangeEXT(target, offset, length, access); + } + + return NULL; +} + +void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + FlushMappedBufferRangeEXT(target, offset, length); + } +} + +void GL_APIENTRY BindVertexArray(GLuint array) +{ + EVENT("(GLuint array = %u)", array); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + VertexArray *vao = context->getVertexArray(array); + + if (!vao) + { + // The default VAO should always exist + ASSERT(array != 0); + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindVertexArray(array); + } +} + +void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays) +{ + EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + if (arrays[arrayIndex] != 0) + { + context->deleteVertexArray(arrays[arrayIndex]); + } + } + } +} + +void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays) +{ + EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + arrays[arrayIndex] = context->createVertexArray(); + } + } +} + +GLboolean GL_APIENTRY IsVertexArray(GLuint array) +{ + EVENT("(GLuint array = %u)", array); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + if (array == 0) + { + return GL_FALSE; + } + + VertexArray *vao = context->getVertexArray(array); + + return (vao != NULL ? GL_TRUE : GL_FALSE); + } + + return GL_FALSE; +} + +void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", + target, index, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= caps.maxCombinedUniformBlocks) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!(context->getIndexedIntegerv(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (numParams == 0) + { + return; // it is known that pname is valid, but there are no parameters to return + } + + if (nativeType == GL_INT_64_ANGLEX) + { + GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min()); + GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max()); + GLint64 *int64Params = new GLint64[numParams]; + + context->getIndexedInteger64v(target, index, int64Params); + + for (unsigned int i = 0; i < numParams; ++i) + { + GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); + data[i] = static_cast<GLint>(clampedValue); + } + + delete [] int64Params; + } + else + { + UNREACHABLE(); + } + } + } +} + +void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode) +{ + EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (primitiveMode) + { + case GL_TRIANGLES: + case GL_LINES: + case GL_POINTS: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (transformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (transformFeedback->isPaused()) + { + transformFeedback->resume(); + } + else + { + transformFeedback->start(primitiveMode); + } + } +} + +void GL_APIENTRY EndTransformFeedback(void) +{ + EVENT("(void)"); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (!transformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->stop(); + } +} + +void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", + target, index, buffer, offset, size); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (buffer != 0 && size <= 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + { + // size and offset must be a multiple of 4 + if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2) + TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + } + + case GL_UNIFORM_BUFFER: + + // it is an error to bind an offset not a multiple of the alignment + if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->bindIndexedUniformBuffer(buffer, index, offset, size); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", + target, index, buffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + { + // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2) + TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + } + case GL_UNIFORM_BUFFER: + context->bindIndexedUniformBuffer(buffer, index, 0, 0); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) +{ + EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", + program, count, varyings, bufferMode); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + const Caps &caps = context->getCaps(); + switch (bufferMode) + { + case GL_INTERLEAVED_ATTRIBS: + break; + case GL_SEPARATE_ATTRIBS: + if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidProgram(context, program)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); + } +} + +void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) +{ + EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " + "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufSize, length, size, type, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidProgram(context, program)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); + } +} + +void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", + index, size, type, stride, pointer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (size < 1 || size > 4) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (stride < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, + stride, pointer); + } +} + +void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.IntValues[i]; + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname); + } + } +} + +void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", + index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.UnsignedIntValues[i]; + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter<GLuint>(attribState, pname); + } + } +} + +void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) +{ + EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", + index, x, y, z, w); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribi(index, vals); + } +} + +void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) +{ + EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", + index, x, y, z, w); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLuint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribu(index, vals); + } +} + +void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v) +{ + EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribi(index, v); + } +} + +void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v) +{ + EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribu(index, v); + } +} + +void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params) +{ + EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", + program, location, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetUniformuiv(context, program, location, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformuiv(location, params); + } +} + +GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name) +{ + EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", + program, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + if (program == 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return -1; + } + + Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + return programObject->getFragDataLocation(name); + } + + return 0; +} + +void GL_APIENTRY Uniform1ui(GLint location, GLuint v0) +{ + Uniform1uiv(location, 1, &v0); +} + +void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1) +{ + const GLuint xy[] = { v0, v1 }; + Uniform2uiv(location, 1, xy); +} + +void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) +{ + const GLuint xyz[] = { v0, v1, v2 }; + Uniform3uiv(location, 1, xyz); +} + +void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + const GLuint xyzw[] = { v0, v1, v2, v3 }; + Uniform4uiv(location, 1, xyzw); +} + +void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform1uiv(location, count, value); + } +} + +void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform2uiv(location, count, value); + } +} + +void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform3uiv(location, count, value); + } +} + +void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform4uiv(location, count, value); + } +} + +void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_STENCIL: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferiv(context->getState(), buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferuiv(context->getState(), buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", + buffer, drawbuffer, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_DEPTH: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferfv(context->getState(), buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", + buffer, drawbuffer, depth, stencil); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_DEPTH_STENCIL: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferfi(context->getState(), buffer, drawbuffer, depth, stencil); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index) +{ + EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + if (name != GL_EXTENSIONS) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + if (index >= context->getExtensionStringCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str()); + } + + return NULL; +} + +void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) +{ + EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", + readTarget, writeTarget, readOffset, writeOffset, size); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); + Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); + + if (!readBuffer || !writeBuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Verify that readBuffer and writeBuffer are not currently mapped + if (readBuffer->isMapped() || writeBuffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (readOffset < 0 || writeOffset < 0 || size < 0 || + static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() || + static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // if size is zero, the copy is a successful no-op + if (size > 0) + { + Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } + } +} + +void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) +{ + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", + program, uniformCount, uniformNames, uniformIndices); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformCount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (!programObject->isLinked()) + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = GL_INVALID_INDEX; + } + } + else + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]); + } + } + } +} + +void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformCount, uniformIndices, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformCount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + switch (pname) + { + case GL_UNIFORM_TYPE: + case GL_UNIFORM_SIZE: + case GL_UNIFORM_NAME_LENGTH: + case GL_UNIFORM_BLOCK_INDEX: + case GL_UNIFORM_OFFSET: + case GL_UNIFORM_ARRAY_STRIDE: + case GL_UNIFORM_MATRIX_STRIDE: + case GL_UNIFORM_IS_ROW_MAJOR: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (uniformCount > programObject->getActiveUniformCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + + if (index >= static_cast<GLuint>(programObject->getActiveUniformCount())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + params[uniformId] = programObject->getActiveUniformi(index, pname); + } + } +} + +GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return GL_INVALID_INDEX; + } + } + + return programObject->getUniformBlockIndex(uniformBlockName); + } + + return 0; +} + +void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformBlockIndex, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (uniformBlockIndex >= programObject->getActiveUniformBlockCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_UNIFORM_BLOCK_BINDING: + *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex)); + break; + + case GL_UNIFORM_BLOCK_DATA_SIZE: + case GL_UNIFORM_BLOCK_NAME_LENGTH: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", + program, uniformBlockIndex, bufSize, length, uniformBlockName); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (uniformBlockIndex >= programObject->getActiveUniformBlockCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); + } +} + +void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", + program, uniformBlockIndex, uniformBlockBinding); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + // if never linked, there won't be any uniform blocks + if (uniformBlockIndex >= programObject->getActiveUniformBlockCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); + } +} + +void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", + mode, first, count, instanceCount); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount)) + { + return; + } + + Error error = context->drawArrays(mode, first, count, instanceCount); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", + mode, count, type, indices, instanceCount); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + rx::RangeUI indexRange; + if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange)) + { + return; + } + + Error error = context->drawElements(mode, count, type, indices, instanceCount, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags) +{ + EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return 0; + } + + if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return 0; + } + + if (flags != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return 0; + } + + GLsync fenceSync = context->createFenceSync(); + + FenceSync *fenceSyncObject = context->getFenceSync(fenceSync); + Error error = fenceSyncObject->set(condition); + if (error.isError()) + { + context->deleteFenceSync(fenceSync); + context->recordError(error); + return NULL; + } + + return fenceSync; + } + + return NULL; +} + +GLboolean GL_APIENTRY IsSync(GLsync sync) +{ + EVENT("(GLsync sync = 0x%0.8p)", sync); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return (context->getFenceSync(sync) != NULL); + } + + return GL_FALSE; +} + +void GL_APIENTRY DeleteSync(GLsync sync) +{ + EVENT("(GLsync sync = 0x%0.8p)", sync); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->deleteFenceSync(sync); + } +} + +GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_WAIT_FAILED; + } + + if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; + } + + FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; + } + + GLenum result = GL_WAIT_FAILED; + Error error = fenceSync->clientWait(flags, timeout, &result); + if (error.isError()) + { + context->recordError(error); + return GL_WAIT_FAILED; + } + + return result; + } + + return GL_FALSE; +} + +void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (flags != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (timeout != GL_TIMEOUT_IGNORED) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Error error = fenceSync->serverWait(flags, timeout); + if (error.isError()) + { + context->recordError(error); + } + } +} + +void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params) +{ + EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT_64_ANGLEX) + { + context->getInteger64v(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) +{ + EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", + sync, pname, bufSize, length, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break; + case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break; + case GL_SYNC_FLAGS: values[0] = 0; break; + + case GL_SYNC_STATUS: + { + Error error = fenceSync->getStatus(values); + if (error.isError()) + { + context->recordError(error); + return; + } + break; + } + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", + target, index, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!(context->getIndexedInteger64v(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT) + { + GLint *intParams = new GLint[numParams]; + + context->getIndexedIntegerv(target, index, intParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + data[i] = static_cast<GLint64>(intParams[i]); + } + + delete [] intParams; + } + else + { + UNREACHABLE(); + } + } + } +} + +void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferParameter(context, pname)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast<GLint64>(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = buffer->getSize(); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = static_cast<GLint64>(buffer->getAccessFlags()); + break; + case GL_BUFFER_MAPPED: + *params = static_cast<GLint64>(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = buffer->getMapOffset(); + break; + case GL_BUFFER_MAP_LENGTH: + *params = buffer->getMapLength(); + break; + default: UNREACHABLE(); break; + } + } +} + +void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers) +{ + EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < count; i++) + { + samplers[i] = context->createSampler(); + } + } +} + +void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers) +{ + EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < count; i++) + { + context->deleteSampler(samplers[i]); + } + } +} + +GLboolean GL_APIENTRY IsSampler(GLuint sampler) +{ + EVENT("(GLuint sampler = %u)", sampler); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return context->isSampler(sampler); + } + + return GL_FALSE; +} + +void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler) +{ + EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (sampler != 0 && !context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (unit >= context->getCaps().maxCombinedTextureImageUnits) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->bindSampler(unit, sampler); + } +} + +void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!ValidateTexParamParameters(context, pname, param)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->samplerParameteri(sampler, pname, param); + } +} + +void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) +{ + SamplerParameteri(sampler, pname, *param); +} + +void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param))) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->samplerParameterf(sampler, pname, param); + } +} + +void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) +{ + SamplerParameterf(sampler, pname, *param); +} + +void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + *params = context->getSamplerParameteri(sampler, pname); + } +} + +void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +{ + EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + *params = context->getSamplerParameterf(sampler, pname); + } +} + +void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor) +{ + EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->setVertexAttribDivisor(index, divisor); + } +} + +void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK: + { + // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) + TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) + if (context->getTransformFeedback(id) == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindTransformFeedback(id); + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +{ + EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteTransformFeedback(ids[i]); + } + } +} + +void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + for (int i = 0; i < n; i++) + { + ids[i] = context->createTransformFeedback(); + } + } +} + +GLboolean GL_APIENTRY IsTransformFeedback(GLuint id) +{ + EVENT("(GLuint id = %u)", id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); + } + + return GL_FALSE; +} + +void GL_APIENTRY PauseTransformFeedback(void) +{ + EVENT("(void)"); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) + if (!transformFeedback->isStarted() || transformFeedback->isPaused()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->pause(); + } +} + +void GL_APIENTRY ResumeTransformFeedback(void) +{ + EVENT("(void)"); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) + if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->resume(); + } +} + +void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +{ + EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // TODO: Pipe through to the OES extension for now, needs proper validation + return GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary); + } +} + +void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) +{ + EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + program, binaryFormat, binary, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // TODO: Pipe through to the OES extension for now, needs proper validation + return ProgramBinaryOES(program, binaryFormat, binary, length); + } +} + +void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value) +{ + EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", + program, pname, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // glProgramParameteri + UNIMPLEMENTED(); + } +} + +void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +{ + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", + target, numAttachments, attachments); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE) + { + Error error = framebuffer->invalidate(numAttachments, attachments); + if (error.isError()) + { + context->recordError(error); + return; + } + } + } +} + +void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " + "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, numAttachments, attachments, x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE) + { + Rectangle area(x, y, width, height); + Error error = framebuffer->invalidateSub(numAttachments, attachments, area); + if (error.isError()) + { + context->recordError(error); + return; + } + } + } +} + +void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setStorage(target, levels, internalformat, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d)", + target, levels, internalformat, width, height, depth); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) + { + return; + } + + Extents size(width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setStorage(target, levels, internalformat, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " + "GLint* params = 0x%0.8p)", + target, internalformat, pname, bufSize, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (target != GL_RENDERBUFFER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_NUM_SAMPLE_COUNTS: + if (bufSize != 0) + { + *params = formatCaps.sampleCounts.size(); + } + break; + + case GL_SAMPLES: + { + size_t returnCount = std::min<size_t>(bufSize, formatCaps.sampleCounts.size()); + auto sampleReverseIt = formatCaps.sampleCounts.rbegin(); + for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex) + { + params[sampleIndex] = *sampleReverseIt++;; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h new file mode 100644 index 0000000000..09ca0e4641 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h @@ -0,0 +1,125 @@ +// +// 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. +// + +// entry_points_gles_3_0.h : Defines the GLES 3.0 entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES30_H_ +#define LIBGLESV2_ENTRYPOINTGLES30_H_ + +#include <GLES3/gl3.h> +#include <export.h> + +namespace gl +{ + +ANGLE_EXPORT void GL_APIENTRY ReadBuffer(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); +ANGLE_EXPORT void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids); +ANGLE_EXPORT void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids); +ANGLE_EXPORT GLboolean GL_APIENTRY IsQuery(GLuint id); +ANGLE_EXPORT void GL_APIENTRY BeginQuery(GLenum target, GLuint id); +ANGLE_EXPORT void GL_APIENTRY EndQuery(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params); +ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBuffer(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params); +ANGLE_EXPORT void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +ANGLE_EXPORT GLvoid* GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); +ANGLE_EXPORT void GL_APIENTRY BindVertexArray(GLuint array); +ANGLE_EXPORT void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays); +ANGLE_EXPORT void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays); +ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArray(GLuint array); +ANGLE_EXPORT void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data); +ANGLE_EXPORT void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode); +ANGLE_EXPORT void GL_APIENTRY EndTransformFeedback(void); +ANGLE_EXPORT void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +ANGLE_EXPORT void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer); +ANGLE_EXPORT void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); +ANGLE_EXPORT void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); +ANGLE_EXPORT void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v); +ANGLE_EXPORT void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params); +ANGLE_EXPORT GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name); +ANGLE_EXPORT void GL_APIENTRY Uniform1ui(GLint location, GLuint v0); +ANGLE_EXPORT void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1); +ANGLE_EXPORT void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2); +ANGLE_EXPORT void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +ANGLE_EXPORT void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +ANGLE_EXPORT const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index); +ANGLE_EXPORT void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +ANGLE_EXPORT void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +ANGLE_EXPORT GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); +ANGLE_EXPORT void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +ANGLE_EXPORT void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +ANGLE_EXPORT void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount); +ANGLE_EXPORT GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags); +ANGLE_EXPORT GLboolean GL_APIENTRY IsSync(GLsync sync); +ANGLE_EXPORT void GL_APIENTRY DeleteSync(GLsync sync); +ANGLE_EXPORT GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); +ANGLE_EXPORT void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); +ANGLE_EXPORT void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params); +ANGLE_EXPORT void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); +ANGLE_EXPORT void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data); +ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params); +ANGLE_EXPORT void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers); +ANGLE_EXPORT void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers); +ANGLE_EXPORT GLboolean GL_APIENTRY IsSampler(GLuint sampler); +ANGLE_EXPORT void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler); +ANGLE_EXPORT void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param); +ANGLE_EXPORT void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param); +ANGLE_EXPORT void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param); +ANGLE_EXPORT void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param); +ANGLE_EXPORT void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor); +ANGLE_EXPORT void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id); +ANGLE_EXPORT void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids); +ANGLE_EXPORT void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids); +ANGLE_EXPORT GLboolean GL_APIENTRY IsTransformFeedback(GLuint id); +ANGLE_EXPORT void GL_APIENTRY PauseTransformFeedback(void); +ANGLE_EXPORT void GL_APIENTRY ResumeTransformFeedback(void); +ANGLE_EXPORT void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary); +ANGLE_EXPORT void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length); +ANGLE_EXPORT void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value); +ANGLE_EXPORT void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments); +ANGLE_EXPORT void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +ANGLE_EXPORT void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES30_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp new file mode 100644 index 0000000000..6f6983fd91 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp @@ -0,0 +1,14 @@ +// +// 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. +// + +// entry_points_gles_3_0_ext.cpp : Implements the GLES 3.0 extension entry points. + +#include "libGLESv2/entry_points_gles_3_0_ext.h" +#include "libGLESv2/global_state.h" + +namespace gl +{ +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h new file mode 100644 index 0000000000..fec4c1298a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h @@ -0,0 +1,23 @@ +// +// 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. +// + +// entry_points_gles_3_0_ext.h : Defines the GLES 3.0 extension entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES30EXT_H_ +#define LIBGLESV2_ENTRYPOINTGLES30EXT_H_ + +#include <GLES3/gl3.h> +#include <GLES3/gl3ext.h> +#include <export.h> + +namespace gl +{ + +// No GLES 3.0 extensions yet + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES30EXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.h b/src/3rdparty/angle/src/libGLESv2/formatutils.h deleted file mode 100644 index 25106a52e5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/formatutils.h +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright (c) 2013 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. -// - -// formatutils.h: Queries for GL image formats. - -#ifndef LIBGLESV2_FORMATUTILS_H_ -#define LIBGLESV2_FORMATUTILS_H_ - -#include "libGLESv2/Caps.h" -#include "libGLESv2/angletypes.h" - -#include "angle_gl.h" - -#include <cstddef> -#include <cstdint> - -typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - -typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest); -typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest); -typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest); - -typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -namespace gl -{ - -struct FormatType -{ - FormatType(); - - GLenum internalFormat; - ColorWriteFunction colorWriteFunction; -}; -const FormatType &GetFormatTypeInfo(GLenum format, GLenum type); - -struct Type -{ - Type(); - - GLuint bytes; - bool specialInterpretation; -}; -const Type &GetTypeInfo(GLenum type); - -struct InternalFormat -{ - InternalFormat(); - - GLuint redBits; - GLuint greenBits; - GLuint blueBits; - - GLuint luminanceBits; - - GLuint alphaBits; - GLuint sharedBits; - - GLuint depthBits; - GLuint stencilBits; - - GLuint pixelBytes; - - GLuint componentCount; - - bool compressed; - GLuint compressedBlockWidth; - GLuint compressedBlockHeight; - - GLenum format; - GLenum type; - - GLenum componentType; - GLenum colorEncoding; - - typedef bool (*SupportCheckFunction)(GLuint, const Extensions &); - SupportCheckFunction textureSupport; - SupportCheckFunction renderSupport; - SupportCheckFunction filterSupport; - - GLuint computeRowPitch(GLenum type, GLsizei width, GLint alignment) const; - GLuint computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const; - GLuint computeBlockSize(GLenum type, GLsizei width, GLsizei height) const; -}; -const InternalFormat &GetInternalFormatInfo(GLenum internalFormat); - -GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); - -typedef std::set<GLenum> FormatSet; -const FormatSet &GetAllSizedInternalFormats(); - -} - -#endif // LIBGLESV2_FORMATUTILS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp new file mode 100644 index 0000000000..686f0bf49b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp @@ -0,0 +1,235 @@ +// +// 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. +// + +// global_state.cpp : Implements functions for querying the thread-local GL and EGL state. + +#include "libGLESv2/global_state.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" + +#include "common/debug.h" +#include "common/platform.h" +#include "common/tls.h" + +namespace +{ + +static TLSIndex currentTLS = TLS_INVALID_INDEX; + +struct Current +{ + EGLint error; + EGLenum API; + egl::Display *display; + egl::Surface *drawSurface; + egl::Surface *readSurface; + gl::Context *context; +}; + +Current *AllocateCurrent() +{ + ASSERT(currentTLS != TLS_INVALID_INDEX); + if (currentTLS == TLS_INVALID_INDEX) + { + return NULL; + } + + Current *current = new Current(); + current->error = EGL_SUCCESS; + current->API = EGL_OPENGL_ES_API; + current->display = reinterpret_cast<egl::Display*>(EGL_NO_DISPLAY); + current->drawSurface = reinterpret_cast<egl::Surface*>(EGL_NO_SURFACE); + current->readSurface = reinterpret_cast<egl::Surface*>(EGL_NO_SURFACE); + current->context = reinterpret_cast<gl::Context*>(EGL_NO_CONTEXT); + + if (!SetTLSValue(currentTLS, current)) + { + ERR("Could not set thread local storage."); + return NULL; + } + + return current; +} + +void DeallocateCurrent() +{ + Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); + SafeDelete(current); + SetTLSValue(currentTLS, NULL); +} + +Current *GetCurrentData() +{ + // Create a TLS index if one has not been created for this DLL + if (currentTLS == TLS_INVALID_INDEX) + { + currentTLS = CreateTLSIndex(); + } + + Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrent()); +} + +#ifdef ANGLE_PLATFORM_WINDOWS +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + currentTLS = CreateTLSIndex(); + if (currentTLS == TLS_INVALID_INDEX) + { + return FALSE; + } + AllocateCurrent(); + break; + + case DLL_THREAD_ATTACH: + AllocateCurrent(); + break; + + case DLL_THREAD_DETACH: + DeallocateCurrent(); + break; + + case DLL_PROCESS_DETACH: + DeallocateCurrent(); + if (currentTLS != TLS_INVALID_INDEX) + { + DestroyTLSIndex(currentTLS); + currentTLS = TLS_INVALID_INDEX; + } + break; + } + + return TRUE; +} +#endif + +} + +namespace gl +{ + +Context *GetGlobalContext() +{ + Current *current = GetCurrentData(); + + return current->context; +} + +Context *GetValidGlobalContext() +{ + gl::Context *context = GetGlobalContext(); + if (context) + { + if (context->isContextLost()) + { + context->recordError(gl::Error(GL_OUT_OF_MEMORY, "Context has been lost.")); + return nullptr; + } + else + { + return context; + } + } + return nullptr; +} + +} + +namespace egl +{ + +void SetGlobalError(const Error &error) +{ + Current *current = GetCurrentData(); + + current->error = error.getCode(); +} + +EGLint GetGlobalError() +{ + Current *current = GetCurrentData(); + + return current->error; +} + +EGLenum GetGlobalAPI() +{ + Current *current = GetCurrentData(); + + return current->API; +} + +void SetGlobalAPI(EGLenum API) +{ + Current *current = GetCurrentData(); + + current->API = API; +} + +void SetGlobalDisplay(Display *dpy) +{ + Current *current = GetCurrentData(); + + current->display = dpy; +} + +Display *GetGlobalDisplay() +{ + Current *current = GetCurrentData(); + + return current->display; +} + +void SetGlobalDrawSurface(Surface *surface) +{ + Current *current = GetCurrentData(); + + current->drawSurface = surface; +} + +Surface *GetGlobalDrawSurface() +{ + Current *current = GetCurrentData(); + + return current->drawSurface; +} + +void SetGlobalReadSurface(Surface *surface) +{ + Current *current = GetCurrentData(); + + current->readSurface = surface; +} + +Surface *GetGlobalReadSurface() +{ + Current *current = GetCurrentData(); + + return current->readSurface; +} + +void SetGlobalContext(gl::Context *context) +{ + Current *current = GetCurrentData(); + + current->context = context; +} + +gl::Context *GetGlobalContext() +{ + Current *current = GetCurrentData(); + + return current->context; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.h b/src/3rdparty/angle/src/libGLESv2/global_state.h new file mode 100644 index 0000000000..db202539cb --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/global_state.h @@ -0,0 +1,49 @@ +// +// 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. +// + +// global_state.h : Defines functions for querying the thread-local GL and EGL state. + +#ifndef LIBGLESV2_GLOBALSTATE_H_ +#define LIBGLESV2_GLOBALSTATE_H_ + +#include <EGL/egl.h> + +namespace gl +{ +class Context; + +Context *GetGlobalContext(); +Context *GetValidGlobalContext(); + +} + +namespace egl +{ +class Error; +class Display; +class Surface; + +void SetGlobalError(const Error &error); +EGLint GetGlobalError(); + +void SetGlobalAPI(EGLenum API); +EGLenum GetGlobalAPI(); + +void SetGlobalDisplay(Display *dpy); +Display *GetGlobalDisplay(); + +void SetGlobalDrawSurface(Surface *surface); +Surface *GetGlobalDrawSurface(); + +void SetGlobalReadSurface(Surface *surface); +Surface *GetGlobalReadSurface(); + +void SetGlobalContext(gl::Context *context); +gl::Context *GetGlobalContext(); + +} + +#endif // LIBGLESV2_GLOBALSTATE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 587950a139..e69e04aa60 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -6,8977 +6,1416 @@ // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. -#undef GL_APICALL -#define GL_APICALL -#define GL_GLEXT_PROTOTYPES - -#include "common/version.h" -#include "common/utilities.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Fence.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/FramebufferAttachment.h" - -#include "libGLESv2/validationES.h" -#include "libGLESv2/validationES2.h" -#include "libGLESv2/validationES3.h" -#include "libGLESv2/queryconversions.h" +#include "libGLESv2/entry_points_gles_2_0.h" +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/entry_points_gles_3_0.h" +#include "libGLESv2/entry_points_gles_3_0_ext.h" + +#include "common/event_tracer.h" extern "C" { -// OpenGL ES 2.0 functions - void GL_APIENTRY glActiveTexture(GLenum texture) { - EVENT("(GLenum texture = 0x%X)", texture); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setActiveSampler(texture - GL_TEXTURE0); - } + return gl::ActiveTexture(texture); } void GL_APIENTRY glAttachShader(GLuint program, GLuint shader) { - EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (!shaderObject) - { - if (context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (!programObject->attachShader(shaderObject)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } -} - -void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id) -{ - EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateBeginQuery(context, target, id)) - { - return; - } - - gl::Error error = context->beginQuery(target, id); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::AttachShader(program, shader); } 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); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (strncmp(name, "gl_", 3) == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - programObject->bindAttributeLocation(index, name); - } + return gl::BindAttribLocation(program, index, name); } void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) { - EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (target) - { - case GL_ARRAY_BUFFER: - context->bindArrayBuffer(buffer); - return; - case GL_ELEMENT_ARRAY_BUFFER: - context->bindElementArrayBuffer(buffer); - return; - case GL_COPY_READ_BUFFER: - context->bindCopyReadBuffer(buffer); - return; - case GL_COPY_WRITE_BUFFER: - context->bindCopyWriteBuffer(buffer); - return; - case GL_PIXEL_PACK_BUFFER: - context->bindPixelPackBuffer(buffer); - return; - case GL_PIXEL_UNPACK_BUFFER: - context->bindPixelUnpackBuffer(buffer); - return; - case GL_UNIFORM_BUFFER: - context->bindGenericUniformBuffer(buffer); - return; - case GL_TRANSFORM_FEEDBACK_BUFFER: - context->bindGenericTransformFeedbackBuffer(buffer); - return; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::BindBuffer(target, buffer); } void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) { - EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindReadFramebuffer(framebuffer); - } - - if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindDrawFramebuffer(framebuffer); - } - } + return gl::BindFramebuffer(target, framebuffer); } void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer) { - EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (target != GL_RENDERBUFFER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->bindRenderbuffer(renderbuffer); - } + return gl::BindRenderbuffer(target, renderbuffer); } void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) { - EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject && textureObject->getTarget() != target && texture != 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP: - break; - - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->bindTexture(target, texture); - } + return gl::BindTexture(target, texture); } -void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", - red, green, blue, alpha); - - gl::Context* context = gl::getNonLostContext(); - - if (context) - { - context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); - } + return gl::BlendColor(red, green, blue, alpha); } void GL_APIENTRY glBlendEquation(GLenum mode) { - glBlendEquationSeparate(mode, mode); + return gl::BlendEquation(mode); } void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { - EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (modeRGB) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - case GL_MIN: - case GL_MAX: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (modeAlpha) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - case GL_MIN: - case GL_MAX: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setBlendEquation(modeRGB, modeAlpha); - } + return gl::BlendEquationSeparate(modeRGB, modeAlpha); } void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { - glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); + return gl::BlendFunc(sfactor, dfactor); } 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); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (srcRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (dstRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - - case GL_SRC_ALPHA_SATURATE: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (srcAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (dstAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - - case GL_SRC_ALPHA_SATURATE: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || - dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); - - bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || - dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); - - if (constantColorUsed && constantAlphaUsed) - { - ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); - } + return gl::BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); } 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); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (size < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (usage) - { - case GL_STREAM_DRAW: - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - break; - - case GL_STREAM_READ: - case GL_STREAM_COPY: - case GL_STATIC_READ: - case GL_STATIC_COPY: - case GL_DYNAMIC_READ: - case GL_DYNAMIC_COPY: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = buffer->bufferData(data, size, usage); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BufferData(target, size, data, usage); } 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); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (size < 0 || offset < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (data == NULL) - { - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Check for possible overflow of size + offset - if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset)) - { - context->recordError(gl::Error(GL_OUT_OF_MEMORY)); - return; - } - - if (size + offset > buffer->getSize()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Error error = buffer->bufferSubData(data, size, offset); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BufferSubData(target, offset, size, data); } GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return 0; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - return framebuffer->completeness(context->getData()); - } - - return 0; + return gl::CheckFramebufferStatus(target); } void GL_APIENTRY glClear(GLbitfield mask) { - EVENT("(GLbitfield mask = 0x%X)", mask); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); - ASSERT(framebufferObject); - - if (framebufferObject->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return; - } - - if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Error error = context->clear(mask); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::Clear(mask); } -void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", - red, green, blue, alpha); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setClearColor(red, green, blue, alpha); - } + return gl::ClearColor(red, green, blue, alpha); } -void GL_APIENTRY glClearDepthf(GLclampf depth) +void GL_APIENTRY glClearDepthf(GLfloat depth) { - EVENT("(GLclampf depth = %f)", depth); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setClearDepth(depth); - } + return gl::ClearDepthf(depth); } void GL_APIENTRY glClearStencil(GLint s) { - EVENT("(GLint s = %d)", s); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setClearStencil(s); - } + return gl::ClearStencil(s); } 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); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); - } + return gl::ColorMask(red, green, blue, alpha); } void GL_APIENTRY glCompileShader(GLuint shader) { - EVENT("(GLuint shader = %d)", shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - if (context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - shaderObject->compile(context->getData()); - } -} - -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, " - "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", - target, level, internalformat, width, height, border, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, width, height, border, GL_NONE, GL_NONE, data)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) - { - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->setCompressedImage(level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - 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: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->setCompressedImage(target, level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -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, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " - "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", - target, level, xoffset, yoffset, width, height, format, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, - xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, - xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - 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: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - 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; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CompileShader(shader); +} + +void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) +{ + return gl::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + return gl::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); } 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)", - target, level, internalformat, x, y, width, height, border); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, - 0, 0, x, y, width, height, border)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, - 0, 0, 0, x, y, width, height, border)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->copyImage(level, internalformat, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - 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: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CopyTexImage2D(target, level, internalformat, x, y, width, height, border); } void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, level, xoffset, yoffset, x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, - xoffset, yoffset, x, y, width, height, 0)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, - xoffset, yoffset, 0, x, y, width, height, 0)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - 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: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); } GLuint GL_APIENTRY glCreateProgram(void) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - return context->createProgram(); - } - - return 0; + return gl::CreateProgram(); } GLuint GL_APIENTRY glCreateShader(GLenum type) { - EVENT("(GLenum type = 0x%X)", type); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (type) - { - case GL_FRAGMENT_SHADER: - case GL_VERTEX_SHADER: - return context->createShader(type); - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return 0; - } - } - - return 0; + return gl::CreateShader(type); } void GL_APIENTRY glCullFace(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (mode) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setCullMode(mode); - } + return gl::CullFace(mode); } void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) { - EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteBuffer(buffers[i]); - } - } -} - -void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences) -{ - EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteFenceNV(fences[i]); - } - } + return gl::DeleteBuffers(n, buffers); } void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { - EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - if (framebuffers[i] != 0) - { - context->deleteFramebuffer(framebuffers[i]); - } - } - } + return gl::DeleteFramebuffers(n, framebuffers); } void GL_APIENTRY glDeleteProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (program == 0) - { - return; - } - - if (!context->getProgram(program)) - { - if(context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - context->deleteProgram(program); - } -} - -void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids) -{ - EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } - } + return gl::DeleteProgram(program); } void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { - EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteRenderbuffer(renderbuffers[i]); - } - } + return gl::DeleteRenderbuffers(n, renderbuffers); } void GL_APIENTRY glDeleteShader(GLuint shader) { - EVENT("(GLuint shader = %d)", shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (shader == 0) - { - return; - } - - if (!context->getShader(shader)) - { - if(context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - context->deleteShader(shader); - } + return gl::DeleteShader(shader); } void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures) { - EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - if (textures[i] != 0) - { - context->deleteTexture(textures[i]); - } - } - } + return gl::DeleteTextures(n, textures); } void GL_APIENTRY glDepthFunc(GLenum func) { - EVENT("(GLenum func = 0x%X)", func); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_NOTEQUAL: - context->getState().setDepthFunc(func); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::DepthFunc(func); } void GL_APIENTRY glDepthMask(GLboolean flag) { - EVENT("(GLboolean flag = %u)", flag); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setDepthMask(flag != GL_FALSE); - } + return gl::DepthMask(flag); } -void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar) +void GL_APIENTRY glDepthRangef(GLfloat n, GLfloat f) { - EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setDepthRange(zNear, zFar); - } + return gl::DepthRangef(n, f); } void GL_APIENTRY glDetachShader(GLuint program, GLuint shader) { - EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) - { - gl::Shader *shaderByProgramHandle; - shaderByProgramHandle = context->getShader(program); - if (!shaderByProgramHandle) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - - if (!shaderObject) - { - gl::Program *programByShaderHandle = context->getProgram(shader); - if (!programByShaderHandle) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - - if (!programObject->detachShader(shaderObject)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } + return gl::DetachShader(program, shader); } void GL_APIENTRY glDisable(GLenum cap) { - EVENT("(GLenum cap = 0x%X)", cap); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidCap(context, cap)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setEnableFeature(cap, false); - } + return gl::Disable(cap); } void GL_APIENTRY glDisableVertexAttribArray(GLuint index) { - EVENT("(GLuint index = %d)", index); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setEnableVertexAttribArray(index, false); - } + return gl::DisableVertexAttribArray(index); } void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) { - EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateDrawArrays(context, mode, first, count, 0)) - { - return; - } - - gl::Error error = context->drawArrays(mode, first, count, 0); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) -{ - EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) - { - return; - } - - gl::Error error = context->drawArrays(mode, first, count, primcount); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::DrawArrays(mode, first, count); } void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { - EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", - mode, count, type, indices); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - rx::RangeUI indexRange; - if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) - { - return; - } - - gl::Error error = context->drawElements(mode, count, type, indices, 0, indexRange); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) -{ - EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", - mode, count, type, indices, primcount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - rx::RangeUI indexRange; - if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange)) - { - return; - } - - gl::Error error = context->drawElements(mode, count, type, indices, primcount, indexRange); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::DrawElements(mode, count, type, indices); } void GL_APIENTRY glEnable(GLenum cap) { - EVENT("(GLenum cap = 0x%X)", cap); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidCap(context, cap)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setEnableFeature(cap, true); - } + return gl::Enable(cap); } void GL_APIENTRY glEnableVertexAttribArray(GLuint index) { - EVENT("(GLuint index = %d)", index); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setEnableVertexAttribArray(index, true); - } -} - -void GL_APIENTRY glEndQueryEXT(GLenum target) -{ - EVENT("GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateEndQuery(context, target)) - { - return; - } - - gl::Error error = context->endQuery(target); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glFinishFenceNV(GLuint fence) -{ - EVENT("(GLuint fence = %d)", fence); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (fenceObject->isFence() != GL_TRUE) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - fenceObject->finishFence(); - } + return gl::EnableVertexAttribArray(index); } void GL_APIENTRY glFinish(void) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Error error = context->sync(true); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::Finish(); } void GL_APIENTRY glFlush(void) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Error error = context->sync(false); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::Flush(); } void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " - "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (renderbuffer != 0) - { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - framebuffer->setRenderbufferAttachment(attachment, renderbufferObject); - } - else - { - framebuffer->setNULLAttachment(attachment); - } - } + return gl::FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); } void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " - "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (texture != 0) - { - gl::Texture *textureObj = context->getTexture(texture); - gl::ImageIndex index(textarget, level, gl::ImageIndex::ENTIRE_LEVEL); - framebuffer->setTextureAttachment(attachment, textureObj, index); - } - else - { - framebuffer->setNULLAttachment(attachment); - } - } + return gl::FramebufferTexture2D(target, attachment, textarget, texture, level); } void GL_APIENTRY glFrontFace(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (mode) - { - case GL_CW: - case GL_CCW: - context->getState().setFrontFace(mode); - break; - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::FrontFace(mode); } void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers) { - EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - buffers[i] = context->createBuffer(); - } - } + return gl::GenBuffers(n, buffers); } void GL_APIENTRY glGenerateMipmap(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidTextureTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (texture == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - GLenum internalFormat = texture->getBaseLevelInternalFormat(); - const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - - // GenerateMipmap should not generate an INVALID_OPERATION for textures created with - // unsized formats or that are color renderable and filterable. Since we do not track if - // the texture was created with sized or unsized format (only sized formats are stored), - // it is not possible to make sure the the LUMA formats can generate mipmaps (they should - // be able to) because they aren't color renderable. Simply do a special case for LUMA - // textures since they're the only texture format that can be created with unsized formats - // that is not color renderable. New unsized formats are unlikely to be added, since ES2 - // was the last version to use add them. - bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || - internalFormat == GL_LUMINANCE8_ALPHA8_EXT || - internalFormat == GL_ALPHA8_EXT; - - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable || - (!formatCaps.renderable && !isLUMA) || formatInfo.compressed) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // GL_EXT_sRGB does not support mipmap generation on sRGB textures - if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Non-power of 2 ES2 check - if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight()))) - { - ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Cube completeness check - if (target == GL_TEXTURE_CUBE_MAP) - { - gl::TextureCubeMap *textureCube = static_cast<gl::TextureCubeMap *>(texture); - if (!textureCube->isCubeComplete()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - - gl::Error error = texture->generateMipmaps(); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences) -{ - EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - fences[i] = context->createFenceNV(); - } - } + return gl::GenerateMipmap(target); } void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers) { - EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - framebuffers[i] = context->createFramebuffer(); - } - } + return gl::GenFramebuffers(n, framebuffers); } -void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids) +void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (GLsizei i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } - } + return gl::GenRenderbuffers(n, renderbuffers); } -void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) { - EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - renderbuffers[i] = context->createRenderbuffer(); - } - } + return gl::GenTextures(n, textures); } -void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) +void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) { - EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - textures[i] = context->createTexture(); - } - } -} - -void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) -{ - EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, " - "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", - program, index, bufsize, length, size, type, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (index >= (GLuint)programObject->getActiveAttributeCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getActiveAttribute(index, bufsize, length, size, type, name); - } + return gl::GetActiveAttrib(program, index, bufsize, length, size, type, name); } void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) { - EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, " - "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", - program, index, bufsize, length, size, type, name); - - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (index >= (GLuint)programObject->getActiveUniformCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getActiveUniform(index, bufsize, length, size, type, name); - } + return gl::GetActiveUniform(program, index, bufsize, length, size, type, name); } void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { - EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", - program, maxcount, count, shaders); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (maxcount < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - return programObject->getAttachedShaders(maxcount, count, shaders); - } + return gl::GetAttachedShaders(program, maxcount, count, shaders); } GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name) { - EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return -1; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - return programBinary->getAttributeLocation(name); - } - - return -1; + return gl::GetAttribLocation(program, name); } void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params) { - EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_BOOL) - { - context->getBooleanv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetBooleanv(pname, params); } void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidBufferParameter(context, pname)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (pname) - { - case GL_BUFFER_USAGE: - *params = static_cast<GLint>(buffer->getUsage()); - break; - case GL_BUFFER_SIZE: - *params = gl::clampCast<GLint>(buffer->getSize()); - break; - case GL_BUFFER_ACCESS_FLAGS: - *params = buffer->getAccessFlags(); - break; - case GL_BUFFER_MAPPED: - *params = static_cast<GLint>(buffer->isMapped()); - break; - case GL_BUFFER_MAP_OFFSET: - *params = gl::clampCast<GLint>(buffer->getMapOffset()); - break; - case GL_BUFFER_MAP_LENGTH: - *params = gl::clampCast<GLint>(buffer->getMapLength()); - break; - default: UNREACHABLE(); break; - } - } + return gl::GetBufferParameteriv(target, pname, params); } GLenum GL_APIENTRY glGetError(void) { - EVENT("()"); - - gl::Context *context = gl::getContext(); - - if (context) - { - return context->getError(); - } - - return GL_NO_ERROR; -} - -void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) -{ - EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (fenceObject->isFence() != GL_TRUE) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - 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. - GLboolean status = GL_TRUE; - if (fenceObject->getStatus() != GL_TRUE) - { - gl::Error error = fenceObject->testFence(&status); - if (error.isError()) - { - context->recordError(error); - return; - } - } - *params = status; - break; - } - - case GL_FENCE_CONDITION_NV: - { - *params = fenceObject->getCondition(); - break; - } - - default: - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } - } + return gl::GetError(); } void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params) { - EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_FLOAT) - { - context->getFloatv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetFloatv(pname, params); } void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - target, attachment, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - int clientVersion = context->getClientVersion(); - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - if (clientVersion < 3 && !context->getExtensions().sRGB) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - // Determine if the attachment is a valid enum - switch (attachment) - { - case GL_BACK: - case GL_FRONT: - case GL_DEPTH: - case GL_STENCIL: - case GL_DEPTH_STENCIL_ATTACHMENT: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - - default: - if (attachment < GL_COLOR_ATTACHMENT0_EXT || - (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - } - - GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); - gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); - ASSERT(framebuffer); - - if (framebufferHandle == 0) - { - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (attachment) - { - case GL_BACK: - case GL_DEPTH: - case GL_STENCIL: - break; - - default: - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - else - { - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - // Valid attachment query - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - - case GL_DEPTH_STENCIL_ATTACHMENT: - if (framebuffer->hasValidDepthStencil()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - } - - GLenum attachmentType = GL_NONE; - GLuint attachmentHandle = 0; - GLuint attachmentLevel = 0; - GLuint attachmentLayer = 0; - - const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); - - if (attachmentObject) - { - attachmentType = attachmentObject->type(); - attachmentHandle = attachmentObject->id(); - attachmentLevel = attachmentObject->mipLevel(); - attachmentLayer = attachmentObject->layer(); - } - - GLenum attachmentObjectType; // Type category - if (framebufferHandle == 0) - { - attachmentObjectType = GL_FRAMEBUFFER_DEFAULT; - } - else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) - { - attachmentObjectType = attachmentType; - } - else if (gl::ValidTexture2DDestinationTarget(context, attachmentType)) - { - attachmentObjectType = GL_TEXTURE; - } - else - { - UNREACHABLE(); - return; - } - - if (attachmentObjectType == GL_NONE) - { - // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE - // is NONE, then querying any other pname will generate INVALID_ENUM. - - // ES 3.0.2 spec pg 235 states that if the attachment type is none, - // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an - // INVALID_OPERATION for all other pnames - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - *params = attachmentObjectType; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = 0; - break; - - default: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - } - else - { - ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE || - attachmentObjectType == GL_FRAMEBUFFER_DEFAULT); - ASSERT(attachmentObject != NULL); - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - *params = attachmentObjectType; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = attachmentHandle; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - if (attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = attachmentLevel; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - if (attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - *params = attachmentObject->getRedSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - *params = attachmentObject->getGreenSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - *params = attachmentObject->getBlueSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - *params = attachmentObject->getAlphaSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - *params = attachmentObject->getDepthSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - *params = attachmentObject->getStencilSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - *params = attachmentObject->getComponentType(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - *params = attachmentObject->getColorEncoding(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = attachmentLayer; - break; - - default: - UNREACHABLE(); - break; - } - } - } -} - -GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void) -{ - EVENT("()"); - - gl::Context *context = gl::getContext(); - - if (context) - { - return context->getResetStatus(); - } - - return GL_NO_ERROR; + return gl::GetFramebufferAttachmentParameteriv(target, attachment, pname, params); } void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params) { - EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - GLenum nativeType; - unsigned int numParams = 0; - - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_INT) - { - context->getIntegerv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetIntegerv(pname, params); } void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params) { - EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (context->getClientVersion() < 3) - { - switch (pname) - { - case GL_ACTIVE_UNIFORM_BLOCKS: - case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: - case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: - case GL_TRANSFORM_FEEDBACK_VARYINGS: - case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } - - switch (pname) - { - case GL_DELETE_STATUS: - *params = programObject->isFlaggedForDeletion(); - return; - case GL_LINK_STATUS: - *params = programObject->isLinked(); - return; - case GL_VALIDATE_STATUS: - *params = programObject->isValidated(); - return; - case GL_INFO_LOG_LENGTH: - *params = programObject->getInfoLogLength(); - return; - case GL_ATTACHED_SHADERS: - *params = programObject->getAttachedShadersCount(); - return; - case GL_ACTIVE_ATTRIBUTES: - *params = programObject->getActiveAttributeCount(); - return; - case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = programObject->getActiveAttributeMaxLength(); - return; - case GL_ACTIVE_UNIFORMS: - *params = programObject->getActiveUniformCount(); - return; - case GL_ACTIVE_UNIFORM_MAX_LENGTH: - *params = programObject->getActiveUniformMaxLength(); - return; - case GL_PROGRAM_BINARY_LENGTH_OES: - *params = programObject->getProgramBinaryLength(); - return; - case GL_ACTIVE_UNIFORM_BLOCKS: - *params = programObject->getActiveUniformBlockCount(); - return; - case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: - *params = programObject->getActiveUniformBlockMaxLength(); - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: - *params = programObject->getTransformFeedbackBufferMode(); - break; - case GL_TRANSFORM_FEEDBACK_VARYINGS: - *params = programObject->getTransformFeedbackVaryingCount(); - break; - case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - *params = programObject->getTransformFeedbackVaryingMaxLength(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetProgramiv(program, pname, params); } void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) { - EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", - program, bufsize, length, infolog); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getInfoLog(bufsize, length, infolog); - } -} - -void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) -{ - EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidQueryType(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_CURRENT_QUERY_EXT: - params[0] = context->getState().getActiveQueryId(target); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) -{ - EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (context->getState().getActiveQueryId(queryObject->getType()) == id) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - { - gl::Error error = queryObject->getResult(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_QUERY_RESULT_AVAILABLE_EXT: - { - gl::Error error = queryObject->isResultAvailable(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetProgramInfoLog(program, bufsize, length, infolog); } void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (target != GL_RENDERBUFFER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (context->getState().getRenderbufferId() == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); - - switch (pname) - { - case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; - case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; - case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; - case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; - case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; - case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; - case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; - case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; - case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; - - case GL_RENDERBUFFER_SAMPLES_ANGLE: - if (!context->getExtensions().framebufferMultisample) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = renderbuffer->getSamples(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetRenderbufferParameteriv(target, pname, params); } void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params) { - EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_SHADER_TYPE: - *params = shaderObject->getType(); - return; - case GL_DELETE_STATUS: - *params = shaderObject->isFlaggedForDeletion(); - return; - case GL_COMPILE_STATUS: - *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; - return; - case GL_INFO_LOG_LENGTH: - *params = shaderObject->getInfoLogLength(); - return; - case GL_SHADER_SOURCE_LENGTH: - *params = shaderObject->getSourceLength(); - return; - case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: - *params = shaderObject->getTranslatedSourceLength(); - return; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetShaderiv(shader, pname, params); } void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) { - EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", - shader, bufsize, length, infolog); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - shaderObject->getInfoLog(bufsize, length, infolog); - } + return gl::GetShaderInfoLog(shader, bufsize, length, infolog); } void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { - EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", - shadertype, precisiontype, range, precision); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (shadertype) - { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (precisiontype) - { - case GL_LOW_FLOAT: - case GL_MEDIUM_FLOAT: - case GL_HIGH_FLOAT: - // Assume IEEE 754 precision - range[0] = 127; - range[1] = 127; - *precision = 23; - break; - - case GL_LOW_INT: - case GL_MEDIUM_INT: - case GL_HIGH_INT: - // Some (most) hardware only supports single-precision floating-point numbers, - // which can accurately represent integers up to +/-16777216 - range[0] = 24; - range[1] = 24; - *precision = 0; - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetShaderPrecisionFormat(shadertype, precisiontype, range, precision); } void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) { - EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", - shader, bufsize, length, source); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - shaderObject->getSource(bufsize, length, source); - } -} - -void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) -{ - EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", - shader, bufsize, length, source); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined - shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source); - } + return gl::GetShaderSource(shader, bufsize, length, source); } const GLubyte* GL_APIENTRY glGetString(GLenum name) { - EVENT("(GLenum name = 0x%X)", name); - - gl::Context *context = gl::getNonLostContext(); - - switch (name) - { - case GL_VENDOR: - return (GLubyte*)"Google Inc."; - - case GL_RENDERER: - return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); - - case GL_VERSION: - if (context->getClientVersion() == 2) - { - return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; - } - else - { - return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; - } - - case GL_SHADING_LANGUAGE_VERSION: - if (context->getClientVersion() == 2) - { - return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; - } - else - { - return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; - } - - case GL_EXTENSIONS: - return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); - - default: - if (context) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - } - return NULL; - } + return gl::GetString(name); } void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = (GLfloat)texture->getSamplerState().magFilter; - break; - case GL_TEXTURE_MIN_FILTER: - *params = (GLfloat)texture->getSamplerState().minFilter; - break; - case GL_TEXTURE_WRAP_S: - *params = (GLfloat)texture->getSamplerState().wrapS; - break; - case GL_TEXTURE_WRAP_T: - *params = (GLfloat)texture->getSamplerState().wrapT; - break; - case GL_TEXTURE_WRAP_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().wrapR; - break; - case GL_TEXTURE_IMMUTABLE_FORMAT: - // Exposed to ES2.0 through EXT_texture_storage, no client version validation. - *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); - break; - case GL_TEXTURE_IMMUTABLE_LEVELS: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->immutableLevelCount(); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = (GLfloat)texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->getExtensions().textureFilterAnisotropic) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().maxAnisotropy; - break; - case GL_TEXTURE_SWIZZLE_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleRed; - break; - case GL_TEXTURE_SWIZZLE_G: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleGreen; - break; - case GL_TEXTURE_SWIZZLE_B: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleBlue; - break; - case GL_TEXTURE_SWIZZLE_A: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleAlpha; - break; - case GL_TEXTURE_BASE_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().baseLevel; - break; - case GL_TEXTURE_MAX_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().maxLevel; - break; - case GL_TEXTURE_MIN_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().minLod; - break; - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().maxLod; - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetTexParameterfv(target, pname, params); } void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = texture->getSamplerState().magFilter; - break; - case GL_TEXTURE_MIN_FILTER: - *params = texture->getSamplerState().minFilter; - break; - case GL_TEXTURE_WRAP_S: - *params = texture->getSamplerState().wrapS; - break; - case GL_TEXTURE_WRAP_T: - *params = texture->getSamplerState().wrapT; - break; - case GL_TEXTURE_WRAP_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().wrapR; - break; - case GL_TEXTURE_IMMUTABLE_FORMAT: - // Exposed to ES2.0 through EXT_texture_storage, no client version validation. - *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; - break; - case GL_TEXTURE_IMMUTABLE_LEVELS: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = static_cast<GLint>(texture->immutableLevelCount()); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->getExtensions().textureFilterAnisotropic) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLint)texture->getSamplerState().maxAnisotropy; - break; - case GL_TEXTURE_SWIZZLE_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleRed; - break; - case GL_TEXTURE_SWIZZLE_G: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleGreen; - break; - case GL_TEXTURE_SWIZZLE_B: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleBlue; - break; - case GL_TEXTURE_SWIZZLE_A: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleAlpha; - break; - case GL_TEXTURE_BASE_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().baseLevel; - break; - case GL_TEXTURE_MAX_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().maxLevel; - break; - case GL_TEXTURE_MIN_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLint)texture->getSamplerState().minLod; - break; - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLint)texture->getSamplerState().maxLod; - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) -{ - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", - program, location, bufSize, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformfv(location, params); - } + return gl::GetTexParameteriv(target, pname, params); } void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetUniformfv(context, program, location, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformfv(location, params); - } -} - -void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) -{ - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", - program, location, bufSize, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformiv(location, params); - } + return gl::GetUniformfv(program, location, params); } void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetUniformiv(context, program, location, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformiv(location, params); - } + return gl::GetUniformiv(program, location, params); } GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name) { - EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (strstr(name, "gl_") == name) - { - return -1; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return -1; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - return programBinary->getUniformLocation(name); - } - - return -1; + return gl::GetUniformLocation(program, name); } void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { - EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.FloatValues[i]; - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname); - } - } + return gl::GetVertexAttribfv(index, pname, params); } void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { - EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - float currentValue = currentValueData.FloatValues[i]; - params[i] = gl::iround<GLint>(currentValue); - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname); - } - } + return gl::GetVertexAttribiv(index, pname, params); } void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) { - EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index)); - } + return gl::GetVertexAttribPointerv(index, pname, pointer); } void GL_APIENTRY glHint(GLenum target, GLenum mode) { - EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (mode) - { - case GL_FASTEST: - case GL_NICEST: - case GL_DONT_CARE: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (target) - { - case GL_GENERATE_MIPMAP_HINT: - context->getState().setGenerateMipmapHint(mode); - break; - - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - context->getState().setFragmentShaderDerivativeHint(mode); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::Hint(target, mode); } GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) { - EVENT("(GLuint buffer = %d)", buffer); - - gl::Context *context = gl::getNonLostContext(); - if (context && buffer) - { - gl::Buffer *bufferObject = context->getBuffer(buffer); - - if (bufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsBuffer(buffer); } GLboolean GL_APIENTRY glIsEnabled(GLenum cap) { - EVENT("(GLenum cap = 0x%X)", cap); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidCap(context, cap)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return GL_FALSE; - } - - return context->getState().getEnableFeature(cap); - } - - return false; -} - -GLboolean GL_APIENTRY glIsFenceNV(GLuint fence) -{ - EVENT("(GLuint fence = %d)", fence); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return GL_FALSE; - } - - return fenceObject->isFence(); - } - - return GL_FALSE; + return gl::IsEnabled(cap); } GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer) { - EVENT("(GLuint framebuffer = %d)", framebuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context && framebuffer) - { - gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - - if (framebufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsFramebuffer(framebuffer); } GLboolean GL_APIENTRY glIsProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context && program) - { - gl::Program *programObject = context->getProgram(program); - - if (programObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; -} - -GLboolean GL_APIENTRY glIsQueryEXT(GLuint id) -{ - EVENT("(GLuint id = %d)", id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; - } - - return GL_FALSE; + return gl::IsProgram(program); } GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer) { - EVENT("(GLuint renderbuffer = %d)", renderbuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context && renderbuffer) - { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - - if (renderbufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsRenderbuffer(renderbuffer); } GLboolean GL_APIENTRY glIsShader(GLuint shader) { - EVENT("(GLuint shader = %d)", shader); - - gl::Context *context = gl::getNonLostContext(); - if (context && shader) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (shaderObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsShader(shader); } GLboolean GL_APIENTRY glIsTexture(GLuint texture) { - EVENT("(GLuint texture = %d)", texture); - - gl::Context *context = gl::getNonLostContext(); - if (context && texture) - { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsTexture(texture); } void GL_APIENTRY glLineWidth(GLfloat width) { - EVENT("(GLfloat width = %f)", width); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width <= 0.0f) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setLineWidth(width); - } + return gl::LineWidth(width); } void GL_APIENTRY glLinkProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::Error error = context->linkProgram(program); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::LinkProgram(program); } void GL_APIENTRY glPixelStorei(GLenum pname, GLint param) { - EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (pname) - { - case GL_UNPACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setUnpackAlignment(param); - break; - - case GL_PACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setPackAlignment(param); - break; - - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - context->getState().setPackReverseRowOrder(param != 0); - break; - - case GL_UNPACK_IMAGE_HEIGHT: - case GL_UNPACK_SKIP_IMAGES: - case GL_UNPACK_ROW_LENGTH: - case GL_UNPACK_SKIP_ROWS: - case GL_UNPACK_SKIP_PIXELS: - case GL_PACK_ROW_LENGTH: - case GL_PACK_SKIP_ROWS: - case GL_PACK_SKIP_PIXELS: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - UNIMPLEMENTED(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::PixelStorei(pname, param); } void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units) { - EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setPolygonOffsetParams(factor, units); - } -} - -void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei bufSize, - GLvoid *data) -{ - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)", - x, y, width, height, format, type, bufSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0 || bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, - format, type, &bufSize, data)) - { - return; - } - - gl::Error error = context->readPixels(x, y, width, height, format, type, &bufSize, data); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid* pixels) -{ - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", - x, y, width, height, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, - format, type, NULL, pixels)) - { - return; - } - - gl::Error error = context->readPixels(x, y, width, height, format, type, NULL, pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::PolygonOffset(factor, units); } -void GL_APIENTRY glReleaseShaderCompiler(void) +void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->releaseShaderCompiler(); - } + return gl::ReadPixels(x, y, width, height, format, type, pixels); } -void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glReleaseShaderCompiler(void) { - EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, samples, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, - width, height, true)) - { - return; - } - - gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); - gl::Error error = renderbuffer->setStorage(width, height, internalformat, samples); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ReleaseShaderCompiler(); } void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { - glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height); + return gl::RenderbufferStorage(target, internalformat, width, height); } -void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert) +void GL_APIENTRY glSampleCoverage(GLfloat value, GLboolean invert) { - EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); - - gl::Context* context = gl::getNonLostContext(); - - if (context) - { - context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); - } -} - -void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition) -{ - EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (condition != GL_ALL_COMPLETED_NV) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = fenceObject->setFence(condition); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::SampleCoverage(value, invert); } void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - - gl::Context* context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setScissorParams(x, y, width, height); - } + return gl::Scissor(x, y, width, height); } void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) { - EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " - "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", - n, shaders, binaryformat, binary, length); - - gl::Context* context = gl::getNonLostContext(); - if (context) - { - const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats; - if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end()) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - // No binary shader formats are supported. - UNIMPLEMENTED(); - } + return gl::ShaderBinary(n, shaders, binaryformat, binary, length); } void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) { - EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", - shader, count, string, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - if (context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - shaderObject->setSource(count, string, length); - } + return gl::ShaderSource(shader, count, string, length); } void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask) { - glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); + return gl::StencilFunc(func, ref, mask); } void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) { - EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GEQUAL: - case GL_GREATER: - case GL_NOTEQUAL: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilParams(func, ref, mask); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilBackParams(func, ref, mask); - } - } + return gl::StencilFuncSeparate(face, func, ref, mask); } void GL_APIENTRY glStencilMask(GLuint mask) { - glStencilMaskSeparate(GL_FRONT_AND_BACK, mask); + return gl::StencilMask(mask); } void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask) { - EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilWritemask(mask); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilBackWritemask(mask); - } - } + return gl::StencilMaskSeparate(face, mask); } void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) { - glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); + return gl::StencilOp(fail, zfail, zpass); } void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { - EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", - face, fail, zfail, zpass); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (fail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (zfail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (zpass) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilOperations(fail, zfail, zpass); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilBackOperations(fail, zfail, zpass); - } - } + return gl::StencilOpSeparate(face, fail, zfail, zpass); } -GLboolean GL_APIENTRY glTestFenceNV(GLuint fence) +void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLuint fence = %d)", fence); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_TRUE; - } - - if (fenceObject->isFence() != GL_TRUE) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_TRUE; - } - - GLboolean result; - gl::Error error = fenceObject->testFence(&result); - if (error.isError()) - { - context->recordError(error); - return GL_TRUE; - } - - return result; - } - - return GL_TRUE; -} - -void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " - "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, border, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, width, height, border, format, type, pixels)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, 0, width, height, 1, border, format, type, pixels)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - 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: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->setImage(target, level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: UNREACHABLE(); - } - } + return gl::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels); } void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param))) - { - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround<GLenum>(param)); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; - case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround<GLenum>(param); break; - case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround<GLint>(param); break; - case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround<GLint>(param); break; - case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; - case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; - default: UNREACHABLE(); break; - } - } + return gl::TexParameterf(target, pname, param); } void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) { - glTexParameterf(target, pname, (GLfloat)*params); + return gl::TexParameterfv(target, pname, params); } void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateTexParamParameters(context, pname, param)) - { - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; - case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; - case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; - case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; - case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; - case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; - case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; - case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; - case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; - case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; - case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; - case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; - default: UNREACHABLE(); break; - } - } + return gl::TexParameteri(target, pname, param); } void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) { - glTexParameteri(target, pname, *params); + return gl::TexParameteriv(target, pname, params); } -void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, levels, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!context->getExtensions().textureStorage) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (context->getClientVersion() < 3 && - !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - gl::Error error = texture2d->storage(levels, internalformat, width, height); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - gl::Error error = textureCube->storage(levels, internalformat, width); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " - "const GLvoid* pixels = 0x%0.8p)", - target, level, xoffset, yoffset, width, height, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, width, height, 0, format, type, pixels)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - 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: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - UNREACHABLE(); - } - } + return gl::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); } void GL_APIENTRY glUniform1f(GLint location, GLfloat x) { - glUniform1fv(location, 1, &x); + return gl::Uniform1f(location, x); } void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform1fv(location, count, v); - } + return gl::Uniform1fv(location, count, v); } void GL_APIENTRY glUniform1i(GLint location, GLint x) { - glUniform1iv(location, 1, &x); + return gl::Uniform1i(location, x); } void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform1iv(location, count, v); - } + return gl::Uniform1iv(location, count, v); } void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y) { - GLfloat xy[2] = {x, y}; - - glUniform2fv(location, 1, xy); + return gl::Uniform2f(location, x, y); } void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform2fv(location, count, v); - } + return gl::Uniform2fv(location, count, v); } void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y) { - GLint xy[2] = {x, y}; - - glUniform2iv(location, 1, xy); + return gl::Uniform2i(location, x, y); } void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform2iv(location, count, v); - } + return gl::Uniform2iv(location, count, v); } void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) { - GLfloat xyz[3] = {x, y, z}; - - glUniform3fv(location, 1, xyz); + return gl::Uniform3f(location, x, y, z); } void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform3fv(location, count, v); - } + return gl::Uniform3fv(location, count, v); } void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z) { - GLint xyz[3] = {x, y, z}; - - glUniform3iv(location, 1, xyz); + return gl::Uniform3i(location, x, y, z); } void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform3iv(location, count, v); - } + return gl::Uniform3iv(location, count, v); } void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - GLfloat xyzw[4] = {x, y, z, w}; - - glUniform4fv(location, 1, xyzw); + return gl::Uniform4f(location, x, y, z, w); } void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform4fv(location, count, v); - } + return gl::Uniform4fv(location, count, v); } void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) { - GLint xyzw[4] = {x, y, z, w}; - - glUniform4iv(location, 1, xyzw); + return gl::Uniform4i(location, x, y, z, w); } void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform4iv(location, count, v); - } + return gl::Uniform4iv(location, count, v); } void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix2fv(location, count, transpose, value); - } + return gl::UniformMatrix2fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix3fv(location, count, transpose, value); - } + return gl::UniformMatrix3fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix4fv(location, count, transpose, value); - } + return gl::UniformMatrix4fv(location, count, transpose, value); } void GL_APIENTRY glUseProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject && program != 0) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (program != 0 && !programObject->isLinked()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->useProgram(program); - } + return gl::UseProgram(program); } void GL_APIENTRY glValidateProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - programObject->validate(context->getCaps()); - } + return gl::ValidateProgram(program); } -void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x) +void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x) { - EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, 0, 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib1f(indx, x); } -void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { values[0], 0, 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib1fv(indx, values); } -void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, y, 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib2f(indx, x, y); } -void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { values[0], values[1], 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib2fv(indx, values); } -void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, y, z, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib3f(indx, x, y, z); } -void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { values[0], values[1], values[2], 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib3fv(indx, values); } -void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, y, z, w }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib4f(indx, x, y, z, w); } -void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setVertexAttribf(index, values); - } + return gl::VertexAttrib4fv(indx, values); } -void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) { - EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->setVertexAttribDivisor(index, divisor); - } -} - -void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) -{ - EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " - "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", - index, size, type, normalized, stride, ptr); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (size < 1 || size > 4) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (type) - { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - - case GL_HALF_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_INT_2_10_10_10_REV: - case GL_UNSIGNED_INT_2_10_10_10_REV: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (stride < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // [OpenGL ES 3.0.2] Section 2.8 page 24: - // An INVALID_OPERATION error is generated when a non-zero vertex array object - // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, - // and the pointer argument is not NULL. - if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, - normalized == GL_TRUE, false, stride, ptr); - } + return gl::VertexAttribPointer(indx, size, type, normalized, stride, ptr); } void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setViewportParams(x, y, width, height); - } + return gl::Viewport(x, y, width, height); } -// OpenGL ES 3.0 functions - void GL_APIENTRY glReadBuffer(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glReadBuffer - UNIMPLEMENTED(); - } + return gl::ReadBuffer(mode); } void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) { - EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " - "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glDrawRangeElements - UNIMPLEMENTED(); - } + return gl::DrawRangeElements(mode, start, end, count, type, indices); } void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " - "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " - "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, 0, width, height, depth, border, format, type, pixels)) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); } void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, zoffset, width, height, depth, 0, - format, type, pixels)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0 || depth == 0) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); } void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, level, xoffset, yoffset, zoffset, x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, - x, y, width, height, 0)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - gl::Texture *texture = NULL; - switch (target) - { - case GL_TEXTURE_3D: - texture = context->getTexture3D(); - break; - - case GL_TEXTURE_2D_ARRAY: - texture = context->getTexture2DArray(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); } void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " - "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " - "const GLvoid* data = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); } void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " - "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", - target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!data) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, - 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); } void GL_APIENTRY glGenQueries(GLsizei n, GLuint* ids) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (GLsizei i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } - } + return gl::GenQueries(n, ids); } void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint* ids) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (GLsizei i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } - } + return gl::DeleteQueries(n, ids); } GLboolean GL_APIENTRY glIsQuery(GLuint id) { - EVENT("(GLuint id = %u)", id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; - } - - return GL_FALSE; + return gl::IsQuery(id); } void GL_APIENTRY glBeginQuery(GLenum target, GLuint id) { - EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateBeginQuery(context, target, id)) - { - return; - } - - gl::Error error = context->beginQuery(target, id); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BeginQuery(target, id); } void GL_APIENTRY glEndQuery(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateEndQuery(context, target)) - { - return; - } - - gl::Error error = context->endQuery(target); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::EndQuery(target); } void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidQueryType(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_CURRENT_QUERY: - params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target)); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetQueryiv(target, pname, params); } void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) { - EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (context->getState().getActiveQueryId(queryObject->getType()) == id) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - { - gl::Error error = queryObject->getResult(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_QUERY_RESULT_AVAILABLE_EXT: - { - gl::Error error = queryObject->isResultAvailable(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetQueryObjectuiv(id, pname, params); } GLboolean GL_APIENTRY glUnmapBuffer(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return glUnmapBufferOES(target); - } - - return GL_FALSE; + return gl::UnmapBuffer(target); } void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - glGetBufferPointervOES(target, pname, params); - } + return gl::GetBufferPointerv(target, pname, params); } void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum* bufs) { - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - glDrawBuffersEXT(n, bufs); - } + return gl::DrawBuffers(n, bufs); } void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix2x3fv(location, count, transpose, value); - } + return gl::UniformMatrix2x3fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix3x2fv(location, count, transpose, value); - } + return gl::UniformMatrix3x2fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix2x4fv(location, count, transpose, value); - } + return gl::UniformMatrix2x4fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix4x2fv(location, count, transpose, value); - } + return gl::UniformMatrix4x2fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix3x4fv(location, count, transpose, value); - } + return gl::UniformMatrix3x4fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix4x3fv(location, count, transpose, value); - } + return gl::UniformMatrix4x3fv(location, count, transpose, value); } void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " - "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - false)) - { - return; - } - - gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, samples, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, - width, height, false)) - { - return; - } - - gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); - renderbuffer->setStorage(width, height, internalformat, samples); - } + return gl::RenderbufferStorageMultisample(target, samples, internalformat, width, height); } void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", - target, attachment, texture, level, layer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, - level, layer)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (texture != 0) - { - gl::Texture *textureObject = context->getTexture(texture); - gl::ImageIndex index(textureObject->getTarget(), level, layer); - framebuffer->setTextureAttachment(attachment, textureObject, index); - } - else - { - framebuffer->setNULLAttachment(attachment); - } - } + return gl::FramebufferTextureLayer(target, attachment, texture, level, layer); } GLvoid* GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", - target, offset, length, access); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - return glMapBufferRangeEXT(target, offset, length, access); - } - - return NULL; + return gl::MapBufferRange(target, offset, length, access); } void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) { - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - glFlushMappedBufferRangeEXT(target, offset, length); - } + return gl::FlushMappedBufferRange(target, offset, length); } void GL_APIENTRY glBindVertexArray(GLuint array) { - EVENT("(GLuint array = %u)", array); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::VertexArray *vao = context->getVertexArray(array); - - if (!vao) - { - // The default VAO should always exist - ASSERT(array != 0); - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->bindVertexArray(array); - } + return gl::BindVertexArray(array); } void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint* arrays) { - EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) - { - if (arrays[arrayIndex] != 0) - { - context->deleteVertexArray(arrays[arrayIndex]); - } - } - } + return gl::DeleteVertexArrays(n, arrays); } void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays) { - EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) - { - arrays[arrayIndex] = context->createVertexArray(); - } - } + return gl::GenVertexArrays(n, arrays); } GLboolean GL_APIENTRY glIsVertexArray(GLuint array) { - EVENT("(GLuint array = %u)", array); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - if (array == 0) - { - return GL_FALSE; - } - - gl::VertexArray *vao = context->getVertexArray(array); - - return (vao != NULL ? GL_TRUE : GL_FALSE); - } - - return GL_FALSE; + return gl::IsVertexArray(array); } void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint* data) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", - target, index, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_BINDING: - if (index >= caps.maxCombinedUniformBlocks) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!(context->getIndexedIntegerv(target, index, data))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (numParams == 0) - { - return; // it is known that pname is valid, but there are no parameters to return - } - - if (nativeType == GL_INT_64_ANGLEX) - { - GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min()); - GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max()); - GLint64 *int64Params = new GLint64[numParams]; - - context->getIndexedInteger64v(target, index, int64Params); - - for (unsigned int i = 0; i < numParams; ++i) - { - GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); - data[i] = static_cast<GLint>(clampedValue); - } - - delete [] int64Params; - } - else - { - UNREACHABLE(); - } - } - } + return gl::GetIntegeri_v(target, index, data); } void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode) { - EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (primitiveMode) - { - case GL_TRIANGLES: - case GL_LINES: - case GL_POINTS: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - if (transformFeedback->isStarted()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (transformFeedback->isPaused()) - { - transformFeedback->resume(); - } - else - { - transformFeedback->start(primitiveMode); - } - } + return gl::BeginTransformFeedback(primitiveMode); } void GL_APIENTRY glEndTransformFeedback(void) { - EVENT("(void)"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - if (!transformFeedback->isStarted()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - transformFeedback->stop(); - } + return gl::EndTransformFeedback(); } void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", - target, index, buffer, offset, size); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER: - if (index >= caps.maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (buffer != 0 && size <= 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - - // size and offset must be a multiple of 4 - if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); - context->bindGenericTransformFeedbackBuffer(buffer); - break; - - case GL_UNIFORM_BUFFER: - - // it is an error to bind an offset not a multiple of the alignment - if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->bindIndexedUniformBuffer(buffer, index, offset, size); - context->bindGenericUniformBuffer(buffer); - break; - - default: - UNREACHABLE(); - } - } + return gl::BindBufferRange(target, index, buffer, offset, size); } void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", - target, index, buffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER: - if (index >= caps.maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); - context->bindGenericTransformFeedbackBuffer(buffer); - break; - - case GL_UNIFORM_BUFFER: - context->bindIndexedUniformBuffer(buffer, index, 0, 0); - context->bindGenericUniformBuffer(buffer); - break; - - default: - UNREACHABLE(); - } - } + return gl::BindBufferBase(target, index, buffer); } void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) { - EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", - program, count, varyings, bufferMode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (bufferMode) - { - case GL_INTERLEAVED_ATTRIBS: - break; - case GL_SEPARATE_ATTRIBS: - if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidProgram(context, program)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - - programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); - } + return gl::TransformFeedbackVaryings(program, count, varyings, bufferMode); } void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) { - EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " - "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", - program, index, bufSize, length, size, type, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidProgram(context, program)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - - if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount())) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); - } + return gl::GetTransformFeedbackVarying(program, index, bufSize, length, size, type, name); } void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) { - EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", - index, size, type, stride, pointer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (size < 1 || size > 4) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (type) - { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_INT_2_10_10_10_REV: - case GL_UNSIGNED_INT_2_10_10_10_REV: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (stride < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // [OpenGL ES 3.0.2] Section 2.8 page 24: - // An INVALID_OPERATION error is generated when a non-zero vertex array object - // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, - // and the pointer argument is not NULL. - if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, - stride, pointer); - } + return gl::VertexAttribIPointer(index, size, type, stride, pointer); } void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) { - EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.IntValues[i]; - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname); - } - } + return gl::GetVertexAttribIiv(index, pname, params); } void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) { - EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", - index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.UnsignedIntValues[i]; - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter<GLuint>(attribState, pname); - } - } + return gl::GetVertexAttribIuiv(index, pname, params); } void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) { - EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", - index, x, y, z, w); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLint vals[4] = { x, y, z, w }; - context->getState().setVertexAttribi(index, vals); - } + return gl::VertexAttribI4i(index, x, y, z, w); } void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) { - EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", - index, x, y, z, w); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLuint vals[4] = { x, y, z, w }; - context->getState().setVertexAttribu(index, vals); - } + return gl::VertexAttribI4ui(index, x, y, z, w); } void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint* v) { - EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setVertexAttribi(index, v); - } + return gl::VertexAttribI4iv(index, v); } void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint* v) { - EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setVertexAttribu(index, v); - } + return gl::VertexAttribI4uiv(index, v); } void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint* params) { - EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", - program, location, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetUniformuiv(context, program, location, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformuiv(location, params); - } + return gl::GetUniformuiv(program, location, params); } GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name) { - EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", - program, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - if (program == 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return -1; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - return programBinary->getFragDataLocation(name); - } - - return 0; + return gl::GetFragDataLocation(program, name); } void GL_APIENTRY glUniform1ui(GLint location, GLuint v0) { - glUniform1uiv(location, 1, &v0); + return gl::Uniform1ui(location, v0); } void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1) { - const GLuint xy[] = { v0, v1 }; - glUniform2uiv(location, 1, xy); + return gl::Uniform2ui(location, v0, v1); } void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { - const GLuint xyz[] = { v0, v1, v2 }; - glUniform3uiv(location, 1, xyz); + return gl::Uniform3ui(location, v0, v1, v2); } void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { - const GLuint xyzw[] = { v0, v1, v2, v3 }; - glUniform4uiv(location, 1, xyzw); + return gl::Uniform4ui(location, v0, v1, v2, v3); } void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform1uiv(location, count, value); - } + return gl::Uniform1uiv(location, count, value); } void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform2uiv(location, count, value); - } + return gl::Uniform2uiv(location, count, value); } void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform3uiv(location, count, value); - } + return gl::Uniform3uiv(location, count, value); } void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform4uiv(location, count, value); - } + return gl::Uniform4uiv(location, count, value); } void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", - buffer, drawbuffer, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_STENCIL: - if (drawbuffer != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferiv(buffer, drawbuffer, value); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferiv(buffer, drawbuffer, value); } void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", - buffer, drawbuffer, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferuiv(buffer, drawbuffer, value); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferuiv(buffer, drawbuffer, value); } void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", - buffer, drawbuffer, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_DEPTH: - if (drawbuffer != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferfv(buffer, drawbuffer, value); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferfv(buffer, drawbuffer, value); } void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", - buffer, drawbuffer, depth, stencil); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_DEPTH_STENCIL: - if (drawbuffer != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferfi(buffer, drawbuffer, depth, stencil); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferfi(buffer, drawbuffer, depth, stencil); } const GLubyte* GL_APIENTRY glGetStringi(GLenum name, GLuint index) { - EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - if (name != GL_EXTENSIONS) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - if (index >= context->getExtensionStringCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str()); - } - - return NULL; + return gl::GetStringi(name, index); } void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { - EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", - readTarget, writeTarget, readOffset, writeOffset, size); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, writeTarget)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); - gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); - - if (!readBuffer || !writeBuffer) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Verify that readBuffer and writeBuffer are not currently mapped - if (readBuffer->isMapped() || writeBuffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (readOffset < 0 || writeOffset < 0 || size < 0 || - static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() || - static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // if size is zero, the copy is a successful no-op - if (size > 0) - { - gl::Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); - if (error.isError()) - { - context->recordError(error); - return; - } - } - } + return gl::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); } void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) { - EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", - program, uniformCount, uniformNames, uniformIndices); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (uniformCount < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - uniformIndices[uniformId] = GL_INVALID_INDEX; - } - } - else - { - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]); - } - } - } + return gl::GetUniformIndices(program, uniformCount, uniformNames, uniformIndices); } void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) { - EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - program, uniformCount, uniformIndices, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (uniformCount < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - switch (pname) - { - case GL_UNIFORM_TYPE: - case GL_UNIFORM_SIZE: - case GL_UNIFORM_NAME_LENGTH: - case GL_UNIFORM_BLOCK_INDEX: - case GL_UNIFORM_OFFSET: - case GL_UNIFORM_ARRAY_STRIDE: - case GL_UNIFORM_MATRIX_STRIDE: - case GL_UNIFORM_IS_ROW_MAJOR: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary && uniformCount > 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - const GLuint index = uniformIndices[uniformId]; - - if (index >= (GLuint)programBinary->getActiveUniformCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - const GLuint index = uniformIndices[uniformId]; - params[uniformId] = programBinary->getActiveUniformi(index, pname); - } - } + return gl::GetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params); } GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { - EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_INVALID_INDEX; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_INVALID_INDEX; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return GL_INVALID_INDEX; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return GL_INVALID_INDEX; - } - - return programBinary->getUniformBlockIndex(uniformBlockName); - } - - return 0; + return gl::GetUniformBlockIndex(program, uniformBlockName); } void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { - EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - program, uniformBlockIndex, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_UNIFORM_BLOCK_BINDING: - *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex)); - break; - - case GL_UNIFORM_BLOCK_DATA_SIZE: - case GL_UNIFORM_BLOCK_NAME_LENGTH: - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetActiveUniformBlockiv(program, uniformBlockIndex, pname, params); } void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) { - EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", - program, uniformBlockIndex, bufSize, length, uniformBlockName); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); - } + return gl::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName); } void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { - EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", - program, uniformBlockIndex, uniformBlockBinding); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - // if never linked, there won't be any uniform blocks - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); - } + return gl::UniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); } void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) { - EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", - mode, first, count, instanceCount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glDrawArraysInstanced - UNIMPLEMENTED(); - } + return gl::DrawArraysInstanced(mode, first, count, instanceCount); } void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) { - EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", - mode, count, type, indices, instanceCount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glDrawElementsInstanced - UNIMPLEMENTED(); - } + return gl::DrawElementsInstanced(mode, count, type, indices, instanceCount); } GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags) { - EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return 0; - } - - if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return 0; - } - - if (flags != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return 0; - } - - GLsync fenceSync = context->createFenceSync(); - - gl::FenceSync *fenceSyncObject = context->getFenceSync(fenceSync); - gl::Error error = fenceSyncObject->set(condition); - if (error.isError()) - { - context->deleteFenceSync(fenceSync); - context->recordError(error); - return NULL; - } - - return fenceSync; - } - - return NULL; + return gl::FenceSync_(condition, flags); } GLboolean GL_APIENTRY glIsSync(GLsync sync) { - EVENT("(GLsync sync = 0x%0.8p)", sync); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return (context->getFenceSync(sync) != NULL); - } - - return GL_FALSE; + return gl::IsSync(sync); } void GL_APIENTRY glDeleteSync(GLsync sync) { - EVENT("(GLsync sync = 0x%0.8p)", sync); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->deleteFenceSync(sync); - } + return gl::DeleteSync(sync); } GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", - sync, flags, timeout); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_WAIT_FAILED; - } - - if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return GL_WAIT_FAILED; - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return GL_WAIT_FAILED; - } - - GLenum result = GL_WAIT_FAILED; - gl::Error error = fenceSync->clientWait(flags, timeout, &result); - if (error.isError()) - { - context->recordError(error); - return GL_WAIT_FAILED; - } - - return result; - } - - return GL_FALSE; + return gl::ClientWaitSync(sync, flags, timeout); } void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", - sync, flags, timeout); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (flags != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (timeout != GL_TIMEOUT_IGNORED) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Error error = fenceSync->serverWait(flags, timeout); - if (error.isError()) - { - context->recordError(error); - } - } + return gl::WaitSync(sync, flags, timeout); } void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64* params) { - EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", - pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_INT_64_ANGLEX) - { - context->getInteger64v(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetInteger64v(pname, params); } void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) { - EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", - sync, pname, bufSize, length, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break; - case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break; - case GL_SYNC_FLAGS: values[0] = 0; break; - - case GL_SYNC_STATUS: - { - gl::Error error = fenceSync->getStatus(values); - if (error.isError()) - { - context->recordError(error); - return; - } - break; - } - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetSynciv(sync, pname, bufSize, length, values); } void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", - target, index, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_BINDING: - if (index >= caps.maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!(context->getIndexedInteger64v(target, index, data))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (numParams == 0) - return; // it is known that pname is valid, but there are no parameters to return - - if (nativeType == GL_INT) - { - GLint *intParams = new GLint[numParams]; - - context->getIndexedIntegerv(target, index, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - data[i] = static_cast<GLint64>(intParams[i]); - } - - delete [] intParams; - } - else - { - UNREACHABLE(); - } - } - } + return gl::GetInteger64i_v(target, index, data); } void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", - target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidBufferParameter(context, pname)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (pname) - { - case GL_BUFFER_USAGE: - *params = static_cast<GLint64>(buffer->getUsage()); - break; - case GL_BUFFER_SIZE: - *params = buffer->getSize(); - break; - case GL_BUFFER_ACCESS_FLAGS: - *params = static_cast<GLint64>(buffer->getAccessFlags()); - break; - case GL_BUFFER_MAPPED: - *params = static_cast<GLint64>(buffer->isMapped()); - break; - case GL_BUFFER_MAP_OFFSET: - *params = buffer->getMapOffset(); - break; - case GL_BUFFER_MAP_LENGTH: - *params = buffer->getMapLength(); - break; - default: UNREACHABLE(); break; - } - } + return gl::GetBufferParameteri64v(target, pname, params); } void GL_APIENTRY glGenSamplers(GLsizei count, GLuint* samplers) { - EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < count; i++) - { - samplers[i] = context->createSampler(); - } - } + return gl::GenSamplers(count, samplers); } void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint* samplers) { - EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < count; i++) - { - context->deleteSampler(samplers[i]); - } - } + return gl::DeleteSamplers(count, samplers); } GLboolean GL_APIENTRY glIsSampler(GLuint sampler) { - EVENT("(GLuint sampler = %u)", sampler); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return context->isSampler(sampler); - } - - return GL_FALSE; + return gl::IsSampler(sampler); } void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler) { - EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (sampler != 0 && !context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (unit >= context->getCaps().maxCombinedTextureImageUnits) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->bindSampler(unit, sampler); - } + return gl::BindSampler(unit, sampler); } void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) { - EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } - - if (!gl::ValidateTexParamParameters(context, pname, param)) - { - return; - } - - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->samplerParameteri(sampler, pname, param); - } + return gl::SamplerParameteri(sampler, pname, param); } void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) { - glSamplerParameteri(sampler, pname, *param); + return gl::SamplerParameteriv(sampler, pname, param); } void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { - EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } - - if (!gl::ValidateTexParamParameters(context, pname, static_cast<GLint>(param))) - { - return; - } - - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->samplerParameterf(sampler, pname, param); - } + return gl::SamplerParameterf(sampler, pname, param); } void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) { - glSamplerParameterf(sampler, pname, *param); + return gl::SamplerParameterfv(sampler, pname, param); } void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) { - EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); + return gl::GetSamplerParameteriv(sampler, pname, params); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +{ + return gl::GetSamplerParameterfv(sampler, pname, params); +} - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } +void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) +{ + return gl::VertexAttribDivisor(index, divisor); +} - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) +{ + return gl::BindTransformFeedback(target, id); +} - *params = context->getSamplerParameteri(sampler, pname); - } +void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +{ + return gl::DeleteTransformFeedbacks(n, ids); } -void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids) { - EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); + return gl::GenTransformFeedbacks(n, ids); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) +{ + return gl::IsTransformFeedback(id); +} - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } +void GL_APIENTRY glPauseTransformFeedback(void) +{ + return gl::PauseTransformFeedback(); +} - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glResumeTransformFeedback(void) +{ + return gl::ResumeTransformFeedback(); +} - *params = context->getSamplerParameterf(sampler, pname); - } +void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +{ + return gl::GetProgramBinary(program, bufSize, length, binaryFormat, binary); } -void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) +void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) { - EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); + return gl::ProgramBinary(program, binaryFormat, binary, length); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) +{ + return gl::ProgramParameteri(program, pname, value); +} - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } +void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +{ + return gl::InvalidateFramebuffer(target, numAttachments, attachments); +} - context->setVertexAttribDivisor(index, divisor); - } +void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +{ + return gl::InvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height); } -void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) +void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK: - { - // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) - gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) - if (context->getTransformFeedback(id) == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->bindTransformFeedback(id); - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::TexStorage2D(target, levels, internalformat, width, height); } -void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); + return gl::TexStorage3D(target, levels, internalformat, width, height, depth); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +{ + return gl::GetInternalformativ(target, internalformat, pname, bufSize, params); +} - for (int i = 0; i < n; i++) - { - context->deleteTransformFeedback(ids[i]); - } - } +void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) +{ + return gl::BlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } -void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids) +void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + return gl::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences) +{ + return gl::DeleteFencesNV(n, fences); +} - for (int i = 0; i < n; i++) - { - ids[i] = context->createTransformFeedback(); - } - } +void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences) +{ + return gl::GenFencesNV(n, fences); } -GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) +GLboolean GL_APIENTRY glIsFenceNV(GLuint fence) { - EVENT("(GLuint id = %u)", id); + return gl::IsFenceNV(fence); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } +GLboolean GL_APIENTRY glTestFenceNV(GLuint fence) +{ + return gl::TestFenceNV(fence); +} - return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); - } +void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + return gl::GetFenceivNV(fence, pname, params); +} - return GL_FALSE; +void GL_APIENTRY glFinishFenceNV(GLuint fence) +{ + return gl::FinishFenceNV(fence); } -void GL_APIENTRY glPauseTransformFeedback(void) +void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition) { - EVENT("(void)"); + return gl::SetFenceNV(fence, condition); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source) +{ + return gl::GetTranslatedShaderSourceANGLE(shader, bufsize, length, source); +} - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); +void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + return gl::TexStorage2DEXT(target, levels, internalformat, width, height); +} - // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) - if (!transformFeedback->isStarted() || transformFeedback->isPaused()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void) +{ + return gl::GetGraphicsResetStatusEXT(); +} - transformFeedback->pause(); - } +void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) +{ + return gl::ReadnPixelsEXT(x, y, width, height, format, type, bufSize, data); } -void GL_APIENTRY glResumeTransformFeedback(void) +void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params) { - EVENT("(void)"); + return gl::GetnUniformfvEXT(program, location, bufSize, params); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params) +{ + return gl::GetnUniformivEXT(program, location, bufSize, params); +} - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); +void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint *ids) +{ + return gl::GenQueriesEXT(n, ids); +} - // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) - if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids) +{ + return gl::DeleteQueriesEXT(n, ids); +} - transformFeedback->resume(); - } +GLboolean GL_APIENTRY glIsQueryEXT(GLuint id) +{ + return gl::IsQueryEXT(id); } -void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id) { - EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", - program, bufSize, length, binaryFormat, binary); + return gl::BeginQueryEXT(target, id); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glEndQueryEXT(GLenum target) +{ + return gl::EndQueryEXT(target); +} - // glGetProgramBinary - UNIMPLEMENTED(); - } +void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) +{ + return gl::GetQueryivEXT(target, pname, params); } -void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) +void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) { - EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", - program, binaryFormat, binary, length); + return gl::GetQueryObjectuivEXT(id, pname, params); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +{ + return gl::DrawBuffersEXT(n, bufs); +} - // glProgramBinary - UNIMPLEMENTED(); - } +void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + return gl::DrawArraysInstancedANGLE(mode, first, count, primcount); } -void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) +void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) { - EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", - program, pname, value); + return gl::DrawElementsInstancedANGLE(mode, count, type, indices, primcount); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + return gl::VertexAttribDivisorANGLE(index, divisor); +} - // glProgramParameteri - UNIMPLEMENTED(); - } +void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary) +{ + return gl::GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary); } -void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length) { - EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", - target, numAttachments, attachments); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE) - { - gl::Error error = framebuffer->invalidate(context->getCaps(), numAttachments, attachments); - if (error.isError()) - { - context->recordError(error); - return; - } - } - } + return gl::ProgramBinaryOES(program, binaryFormat, binary, length); } -void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +void* GL_APIENTRY glMapBufferOES(GLenum target, GLenum access) { - EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " - "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, numAttachments, attachments, x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE) - { - gl::Error error = framebuffer->invalidateSub(numAttachments, attachments, x, y, width, height); - if (error.isError()) - { - context->recordError(error); - return; - } - } - } + return gl::MapBufferOES(target, access); } -void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, levels, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - gl::Error error = texture2d->storage(levels, internalformat, width, height); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - gl::Error error = textureCube->storage(levels, internalformat, width); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::UnmapBufferOES(target); } -void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " - "GLsizei height = %d, GLsizei depth = %d)", - target, levels, internalformat, width, height, depth); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture3d = context->getTexture3D(); - gl::Error error = texture3d->storage(levels, internalformat, width, height, depth); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture2darray = context->getTexture2DArray(); - gl::Error error = texture2darray->storage(levels, internalformat, width, height, depth); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - UNREACHABLE(); - } - } + return gl::GetBufferPointervOES(target, pname, params); } -void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +void* GL_APIENTRY glMapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { - EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " - "GLint* params = 0x%0.8p)", - target, internalformat, pname, bufSize, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (!formatCaps.renderable) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (target != GL_RENDERBUFFER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_NUM_SAMPLE_COUNTS: - if (bufSize != 0) - { - *params = formatCaps.sampleCounts.size(); - } - break; - - case GL_SAMPLES: - std::copy_n(formatCaps.sampleCounts.rbegin(), std::min<size_t>(bufSize, formatCaps.sampleCounts.size()), params); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -// Extension functions - -void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " - "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " - "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", - srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - true)) - { - return; - } - - gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " - "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " - "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, format, type, pixels); - - UNIMPLEMENTED(); // FIXME -} - -void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, - GLenum *binaryFormat, void *binary) -{ - EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", - program, bufSize, length, binaryFormat, binary); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, - const void *binary, GLint length) -{ - EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", - program, binaryFormat, binary, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats; - if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end()) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Program *programObject = context->getProgram(program); - if (!programObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::MapBufferRangeEXT(target, offset, length, access); } -void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +void GL_APIENTRY glFlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) { - EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - ASSERT(context->getState().getDrawFramebuffer()); - - if (context->getState().getDrawFramebuffer()->id() == 0) - { - if (n != 1) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - else - { - for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) - { - const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; - if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - } - - gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); - ASSERT(framebuffer); - - for (unsigned int colorAttachment = 0; colorAttachment < static_cast<unsigned int>(n); colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); - } - - for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, GL_NONE); - } - } -} - -void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void** params) -{ - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (pname != GL_BUFFER_MAP_POINTER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer || !buffer->isMapped()) - { - *params = NULL; - } - else - { - *params = buffer->getMapPointer(); - } - } -} - -void * GL_APIENTRY glMapBufferOES(GLenum target, GLenum access) -{ - EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - if (access != GL_WRITE_ONLY_OES) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - if (buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - gl::Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); - if (error.isError()) - { - context->recordError(error); - return NULL; - } - - return buffer->getMapPointer(); - } - - return NULL; + return gl::FlushMappedBufferRangeEXT(target, offset, length); } -GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target) +void GL_APIENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, + AddTraceEventFunc addTraceEvent) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return GL_FALSE; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL || !buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - // TODO: detect if we had corruption. if so, throw an error and return false. - - gl::Error error = buffer->unmap(); - if (error.isError()) - { - context->recordError(error); - return GL_FALSE; - } - - return GL_TRUE; - } - - return GL_FALSE; -} - -void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) -{ - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", - target, offset, length, access); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - if (offset < 0 || length < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - // Check for buffer overflow - size_t offsetSize = static_cast<size_t>(offset); - size_t lengthSize = static_cast<size_t>(length); - - if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || - offsetSize + lengthSize > static_cast<size_t>(buffer->getSize())) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - // Check for invalid bits in the mask - GLbitfield allAccessBits = GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT; - - if (access & ~(allAccessBits)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - if (length == 0 || buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - // Check for invalid bit combinations - if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_UNSYNCHRONIZED_BIT; - - if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - gl::Error error = buffer->mapRange(offset, length, access); - if (error.isError()) - { - context->recordError(error); - return NULL; - } - - return buffer->getMapPointer(); - } - - return NULL; -} - -void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length) -{ - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (offset < 0 || length < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Check for buffer overflow - size_t offsetSize = static_cast<size_t>(offset); - size_t lengthSize = static_cast<size_t>(length); - - if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || - offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength())) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // We do not currently support a non-trivial implementation of FlushMappedBufferRange - } -} - -__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname) -{ - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; - - static const Extension glExtensions[] = - { - {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES}, - {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE}, - {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE}, - {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV}, - {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV}, - {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV}, - {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV}, - {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV}, - {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV}, - {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV}, - {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE}, - {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT}, - {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT}, - {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT}, - {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT}, - {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT}, - {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT}, - {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT}, - {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT}, - {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT}, - {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT}, - {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT}, - {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT}, - {"glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)glDrawBuffersEXT}, - {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE}, - {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE}, - {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE}, - {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES}, - {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, - {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES}, - {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES}, - {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES}, - {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT}, - {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT}, }; - - for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++) - { - if (strcmp(procname, glExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address; - } - } - - return NULL; -} - -// Non-public functions used by EGL - -bool EGLAPIENTRY glBindTexImage(egl::Surface *surface) -{ - EVENT("(egl::Surface* surface = 0x%0.8p)", - surface); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture2D *textureObject = context->getTexture2D(); - ASSERT(textureObject != NULL); - - if (textureObject->isImmutable()) - { - return false; - } - - textureObject->bindTexImage(surface); - } - - return true; + gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; + gl::g_addTraceEvent = addTraceEvent; } } diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index 33557eb1c9..9c6dc497d0 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def @@ -144,7 +144,6 @@ EXPORTS glViewport @142 ; Extensions - glTexImage3DOES @143 glBlitFramebufferANGLE @149 glRenderbufferStorageMultisampleANGLE @150 glDeleteFencesNV @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D @282 glGetInternalformativ @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress @148 NONAME - glBindTexImage @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc deleted file mode 100644 index 76cd05566e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc +++ /dev/null @@ -1,103 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include <windows.h> -#include "../common/version.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "#include ""../common/version.h""\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "FileVersion", ANGLE_VERSION_STRING - VALUE "InternalName", "libGLESv2" - VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." - VALUE "OriginalFilename", "libGLESv2.dll" - VALUE "PrivateBuild", ANGLE_VERSION_STRING - VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "ProductVersion", ANGLE_VERSION_STRING - VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def index 18ffcf6a0d..e02b85bcf2 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def @@ -144,7 +144,6 @@ EXPORTS glViewport@16 @142 ; Extensions - glTexImage3DOES@40 @143 glBlitFramebufferANGLE@40 @149 glRenderbufferStorageMultisampleANGLE@20 @150 glDeleteFencesNV@8 @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D@24 @282 glGetInternalformativ@20 @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress@4 @148 NONAME - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def index 120371e013..d35309c6ce 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def @@ -144,7 +144,6 @@ EXPORTS glViewport @142 ; Extensions - glTexImage3DOES @143 glBlitFramebufferANGLE @149 glRenderbufferStorageMultisampleANGLE @150 glDeleteFencesNV @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D @282 glGetInternalformativ @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress @148 NONAME - glBindTexImage @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def index 8c1306a703..e2b2c333a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def @@ -144,7 +144,6 @@ EXPORTS glViewport@16 @142 ; Extensions - glTexImage3DOES@40 @143 glBlitFramebufferANGLE@40 @149 glRenderbufferStorageMultisampleANGLE@20 @150 glDeleteFencesNV@8 @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D@24 @282 glGetInternalformativ@20 @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress@4 @148 NONAME - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @284 diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp deleted file mode 100644 index 00f63ae079..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// Copyright (c) 2002-2012 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. -// - -// main.cpp: DLL entry point and management of thread-local data. - -#include "libGLESv2/main.h" -#include "libGLESv2/Context.h" - -#include "common/tls.h" - -static TLSIndex currentTLS = TLS_INVALID_INDEX; - -namespace gl -{ - -// TODO(kbr): figure out how these are going to be managed on -// non-Windows platforms. These routines would need to be exported -// from ANGLE and called cooperatively when users create and destroy -// threads -- or the initialization of the TLS index, and allocation -// of thread-local data, will have to be done lazily. Will have to use -// destructor function with pthread_create_key on POSIX platforms to -// clean up thread-local data. - -// Call this exactly once at process startup. -bool CreateThreadLocalIndex() -{ - currentTLS = CreateTLSIndex(); - if (currentTLS == TLS_INVALID_INDEX) - { - return false; - } - return true; -} - -// Call this exactly once at process shutdown. -void DestroyThreadLocalIndex() -{ - DestroyTLSIndex(currentTLS); - currentTLS = TLS_INVALID_INDEX; -} - -// Call this upon thread startup. -Current *AllocateCurrent() -{ - ASSERT(currentTLS != TLS_INVALID_INDEX); - if (currentTLS == TLS_INVALID_INDEX) - { - return NULL; - } - - Current *current = new Current(); - current->context = NULL; - current->display = NULL; - - if (!SetTLSValue(currentTLS, current)) - { - ERR("Could not set thread local storage."); - return NULL; - } - - return current; -} - -// Call this upon thread shutdown. -void DeallocateCurrent() -{ - Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); - SafeDelete(current); - SetTLSValue(currentTLS, NULL); -} - -} - -#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) -extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - { - if (!gl::CreateThreadLocalIndex()) - { - return FALSE; - } - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::InitializeDebugAnnotations(); -#endif - } - // Fall through to initialize index - case DLL_THREAD_ATTACH: - { - gl::AllocateCurrent(); - } - break; - case DLL_THREAD_DETACH: - { - gl::DeallocateCurrent(); - } - break; - case DLL_PROCESS_DETACH: - { - gl::DeallocateCurrent(); - gl::DestroyThreadLocalIndex(); - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::UninitializeDebugAnnotations(); -#endif - } - break; - default: - break; - } - - return TRUE; -} -#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC - -namespace gl -{ - -Current *GetCurrentData() -{ -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS)); - - // ANGLE issue 488: when the dll is loaded after thread initialization, - // thread local storage (current) might not exist yet. - return (current ? current : AllocateCurrent()); -#else - // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current current = { 0, 0 }; - return ¤t; -#endif -} - -void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) -{ - Current *current = GetCurrentData(); - - current->context = context; - current->display = display; - - if (context && display && surface) - { - context->makeCurrent(surface); - } -} - -Context *getContext() -{ - Current *current = GetCurrentData(); - - return current->context; -} - -Context *getNonLostContext() -{ - Context *context = getContext(); - - if (context) - { - if (context->isContextLost()) - { - context->recordError(Error(GL_OUT_OF_MEMORY, "Context has been lost.")); - return NULL; - } - else - { - return context; - } - } - return NULL; -} - -egl::Display *getDisplay() -{ - Current *current = GetCurrentData(); - - return current->display; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h deleted file mode 100644 index dff02787f5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2002-2013 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. -// - -// main.h: Management of thread-local data. - -#ifndef LIBGLESV2_MAIN_H_ -#define LIBGLESV2_MAIN_H_ - -#include "common/debug.h" - -#include <GLES2/gl2.h> -#include <EGL/egl.h> - -namespace egl -{ -class Display; -class Surface; -class AttributeMap; -} - -namespace gl -{ -class Context; - -struct Current -{ - Context *context; - egl::Display *display; -}; - -void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface); - -Context *getContext(); -Context *getNonLostContext(); -egl::Display *getDisplay(); - -} - -namespace rx -{ -class Renderer; -} - -extern "C" -{ -// Exported functions for use by EGL -gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); -void glDestroyContext(gl::Context *context); -void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); -gl::Context *glGetCurrentContext(); -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap); -void glDestroyRenderer(rx::Renderer *renderer); - -__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname); -bool EGLAPIENTRY glBindTexImage(egl::Surface *surface); -} - -#endif // LIBGLESV2_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h deleted file mode 100644 index 1dd46785d9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) 2013 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. -// - -// FenceImpl.h: Defines the rx::FenceNVImpl and rx::FenceSyncImpl classes. - -#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_ -#define LIBGLESV2_RENDERER_FENCEIMPL_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -#include "angle_gl.h" - -namespace rx -{ - -class FenceNVImpl -{ - public: - FenceNVImpl() { }; - virtual ~FenceNVImpl() { }; - - virtual gl::Error set() = 0; - virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0; - virtual gl::Error finishFence(GLboolean *outFinished) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FenceNVImpl); -}; - -class FenceSyncImpl -{ - public: - FenceSyncImpl() { }; - virtual ~FenceSyncImpl() { }; - - virtual gl::Error set() = 0; - virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0; - virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0; - virtual gl::Error getStatus(GLint *outResult) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FenceSyncImpl); -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCEIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp deleted file mode 100644 index 5b9b75f562..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) 2002-2012 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. -// - -// Image.h: Implements the rx::Image class, an abstract base class for the -// renderer-specific classes which will define the interface to the underlying -// surfaces or resources. - -#include "libGLESv2/renderer/Image.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -Image::Image() -{ - mWidth = 0; - mHeight = 0; - mDepth = 0; - mInternalFormat = GL_NONE; - mActualFormat = GL_NONE; - mTarget = GL_NONE; - mRenderable = false; - mDirty = false; -} - -gl::Error Image::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, gl::Framebuffer *source) -{ - gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTarget *renderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - - ASSERT(renderTarget); - return copy(xoffset, yoffset, zoffset, area, renderTarget); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp deleted file mode 100644 index 857fdc9dae..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2012 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. -// - -// RenderTarget.cpp: Implements serial handling for rx::RenderTarget - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -unsigned int RenderTarget::mCurrentSerial = 1; - -RenderTarget::RenderTarget() - : mSerial(issueSerials(1)) -{ -} - -RenderTarget::~RenderTarget() -{ -} - -unsigned int RenderTarget::getSerial() const -{ - return mSerial; -} - -unsigned int RenderTarget::issueSerials(unsigned int count) -{ - unsigned int firstSerial = mCurrentSerial; - mCurrentSerial += count; - return firstSerial; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h deleted file mode 100644 index 3bdfb0cc98..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2012 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. -// - -// RenderTarget.h: Defines an abstract wrapper class to manage IDirect3DSurface9 -// and ID3D11View objects belonging to renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET_H_ - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" - -namespace rx -{ -class RenderTarget -{ - public: - RenderTarget(); - virtual ~RenderTarget(); - - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLsizei getDepth() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; - virtual GLsizei getSamples() const = 0; - gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } - - virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0; - - virtual unsigned int getSerial() const; - static unsigned int issueSerials(unsigned int count); - - struct Desc { - GLsizei width; - GLsizei height; - GLsizei depth; - GLenum format; - }; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget); - - const unsigned int mSerial; - static unsigned int mCurrentSerial; -}; - -} - -#endif // LIBGLESV2_RENDERTARGET_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h deleted file mode 100644 index 52e070f1d3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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. -// - -// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl - -#ifndef LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ -#define LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ - -#include "angle_gl.h" - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -namespace rx -{ - -class RenderbufferImpl -{ - public: - RenderbufferImpl(); - virtual ~RenderbufferImpl() = 0; - - virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0; - - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; - virtual GLsizei getSamples() const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferImpl); -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp deleted file mode 100644 index df3dae1e38..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// Copyright (c) 2012-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. -// - -// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. - -#include "common/utilities.h" -#include "libEGL/AttributeMap.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer.h" - -#include <EGL/eglext.h> - -#if defined (ANGLE_ENABLE_D3D9) -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#endif // ANGLE_ENABLE_D3D9 - -#if defined (ANGLE_ENABLE_D3D11) -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#endif // ANGLE_ENABLE_D3D11 - -#if defined (ANGLE_TEST_CONFIG) -#define ANGLE_DEFAULT_D3D11 1 -#endif - -#if !defined(ANGLE_DEFAULT_D3D11) -// Enables use of the Direct3D 11 API for a default display, when available -#define ANGLE_DEFAULT_D3D11 0 -#endif - -namespace rx -{ - -Renderer::Renderer() - : mCapsInitialized(false), - mWorkaroundsInitialized(false) -{ -} - -Renderer::~Renderer() -{ -} - -const gl::Caps &Renderer::getRendererCaps() const -{ - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } - - return mCaps; -} - -const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const -{ - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } - - return mTextureCaps; -} - -const gl::Extensions &Renderer::getRendererExtensions() const -{ - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } - - return mExtensions; -} - -const Workarounds &Renderer::getWorkarounds() const -{ - if (!mWorkaroundsInitialized) - { - mWorkarounds = generateWorkarounds(); - mWorkaroundsInitialized = true; - } - - return mWorkarounds; -} - -typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, const egl::AttributeMap &); - -template <typename RendererType> -Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attributes) -{ - return new RendererType(display, nativeDisplay, attributes); -} - -} - -extern "C" -{ - -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap) -{ - std::vector<rx::CreateRendererFunction> rendererCreationFunctions; - - EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); - -# if defined(ANGLE_ENABLE_D3D11) - if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) - { - rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>); - } -# endif - -# if defined(ANGLE_ENABLE_D3D9) - if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) - { - rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>); - } -# endif - - if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && - nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) - { - // The default display is requested, try the D3D9 and D3D11 renderers, order them using - // the definition of ANGLE_DEFAULT_D3D11 -# if ANGLE_DEFAULT_D3D11 -# if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>); -# endif -# if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>); -# endif -# else -# if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>); -# endif -# if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>); -# endif -# endif - } - - for (size_t i = 0; i < rendererCreationFunctions.size(); i++) - { - rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, attribMap); - if (renderer->initialize() == EGL_SUCCESS) - { - return renderer; - } - else - { - // Failed to create the renderer, try the next - SafeDelete(renderer); - } - } - - return NULL; -} - -void glDestroyRenderer(rx::Renderer *renderer) -{ - ASSERT(renderer); - SafeDelete(renderer); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h deleted file mode 100644 index b85895a938..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ /dev/null @@ -1,193 +0,0 @@ -// -// Copyright (c) 2012-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. -// - -// Renderer.h: Defines a back-end specific class that hides the details of the -// implementation-specific renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER_H_ -#define LIBGLESV2_RENDERER_RENDERER_H_ - -#include "libGLESv2/Caps.h" -#include "libGLESv2/Error.h" -#include "libGLESv2/Uniform.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "common/NativeWindow.h" -#include "common/mathutil.h" - -#include <cstdint> - -#include <EGL/egl.h> - -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. -// It should only be used selectively to work around specific bugs. -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 -#endif - -namespace egl -{ -class Display; -} - -namespace gl -{ -class Buffer; -class Framebuffer; -struct Data; -} - -namespace rx -{ -class QueryImpl; -class FenceNVImpl; -class FenceSyncImpl; -class BufferImpl; -class VertexArrayImpl; -class ShaderImpl; -class ProgramImpl; -class TextureImpl; -class TransformFeedbackImpl; -class RenderbufferImpl; -struct TranslatedIndexData; -struct Workarounds; -class SwapChain; - -struct ConfigDesc -{ - GLenum renderTargetFormat; - GLenum depthStencilFormat; - GLint multiSample; - bool fastConfig; - bool es3Capable; -}; - -class Renderer -{ - public: - Renderer(); - virtual ~Renderer(); - - virtual EGLint initialize() = 0; - virtual bool resetDevice() = 0; - - virtual int generateConfigs(ConfigDesc **configDescList) = 0; - virtual void deleteConfigs(ConfigDesc *configDescList) = 0; - - virtual gl::Error sync(bool block) = 0; - - virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, - GLint first, GLsizei count, GLsizei instances) = 0; - virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) = 0; - - virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; - virtual gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; - virtual gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; - virtual gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; - virtual gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; - - virtual gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) = 0; - - virtual gl::Error blitFramebuffer(const gl::Data &data, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) = 0; - - // TODO(jmadill): caps? and virtual for egl::Display - virtual bool getShareHandleSupport() const = 0; - virtual bool getPostSubBufferSupport() const = 0; - - // Shader creation - virtual ShaderImpl *createShader(const gl::Data &data, GLenum type) = 0; - virtual ProgramImpl *createProgram() = 0; - - // Shader operations - virtual void releaseShaderCompiler() = 0; - - // Texture creation - virtual TextureImpl *createTexture(GLenum target) = 0; - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer() = 0; - virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth) = 0; - - // Buffer creation - virtual BufferImpl *createBuffer() = 0; - - // Vertex Array creation - virtual VertexArrayImpl *createVertexArray() = 0; - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type) = 0; - virtual FenceNVImpl *createFenceNV() = 0; - virtual FenceSyncImpl *createFenceSync() = 0; - - // Transform Feedback creation - virtual TransformFeedbackImpl *createTransformFeedback() = 0; - - // lost device - //TODO(jmadill): investigate if this stuff is necessary in GL - virtual void notifyDeviceLost() = 0; - virtual bool isDeviceLost() = 0; - virtual bool testDeviceLost(bool notify) = 0; - virtual bool testDeviceResettable() = 0; - - virtual DWORD getAdapterVendor() const = 0; - virtual std::string getRendererDescription() const = 0; - virtual GUID getAdapterIdentifier() const = 0; - - // Renderer capabilities (virtual because of egl::Display) - virtual const gl::Caps &getRendererCaps() const; - const gl::TextureCapsMap &getRendererTextureCaps() const; - virtual const gl::Extensions &getRendererExtensions() const; - const Workarounds &getWorkarounds() const; - - // TODO(jmadill): needed by egl::Display, probably should be removed - virtual int getMajorShaderModel() const = 0; - virtual int getMinSwapInterval() const = 0; - virtual int getMaxSwapInterval() const = 0; - virtual bool getLUID(LUID *adapterLuid) const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer); - - virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; - virtual Workarounds generateWorkarounds() const = 0; - - mutable bool mCapsInitialized; - mutable gl::Caps mCaps; - mutable gl::TextureCapsMap mTextureCaps; - mutable gl::Extensions mExtensions; - - mutable bool mWorkaroundsInitialized; - mutable Workarounds mWorkarounds; -}; - -struct dx_VertexConstants -{ - float depthRange[4]; - float viewAdjust[4]; -}; - -struct dx_PixelConstants -{ - float depthRange[4]; - float viewCoords[4]; - float depthFront[4]; -}; - -enum ShaderType -{ - SHADER_VERTEX, - SHADER_PIXEL, - SHADER_GEOMETRY -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h deleted file mode 100644 index f1a96d74fb..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2012 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. -// - -// ShaderExecutable.h: Defines a renderer-agnostic class to contain shader -// executable implementation details. - -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ - -#include "common/angleutils.h" -#include "common/debug.h" - -#include <vector> -#include <cstdint> - -namespace rx -{ - -class ShaderExecutable -{ - public: - ShaderExecutable(const void *function, size_t length) - : mFunctionBuffer(length) - { - memcpy(mFunctionBuffer.data(), function, length); - } - - virtual ~ShaderExecutable() {} - - const uint8_t *getFunction() const - { - return mFunctionBuffer.data(); - } - - size_t getLength() const - { - return mFunctionBuffer.size(); - } - - const std::string &getDebugInfo() const - { - return mDebugInfo; - } - - void appendDebugInfo(const std::string &info) - { - mDebugInfo += info; - } - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); - - std::vector<uint8_t> mFunctionBuffer; - std::string mDebugInfo; -}; - -class UniformStorage -{ - public: - UniformStorage(size_t initialSize) - : mSize(initialSize) - { - } - - virtual ~UniformStorage() {} - - size_t size() const { return mSize; } - - private: - size_t mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h deleted file mode 100644 index 3e662557e4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright 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. -// - -// TextureImpl.h: Defines the abstract rx::TextureImpl classes. - -#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_ -#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/Error.h" - -#include "angle_gl.h" - -#include "libGLESv2/ImageIndex.h" - -namespace egl -{ -class Surface; -} - -namespace gl -{ -class Framebuffer; -struct PixelUnpackState; -struct SamplerState; -} - -namespace rx -{ - -class Image; - -class TextureImpl -{ - public: - virtual ~TextureImpl() {}; - - // Deprecated in favour of the ImageIndex method - virtual Image *getImage(int level, int layer) const = 0; - virtual Image *getImage(const gl::ImageIndex &index) const = 0; - virtual GLsizei getLayerCount(int level) const = 0; - - virtual void setUsage(GLenum usage) = 0; - - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; - - virtual gl::Error generateMipmaps() = 0; - - virtual void bindTexImage(egl::Surface *surface) = 0; - virtual void releaseTexImage() = 0; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h deleted file mode 100644 index 20a166fb7a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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. -// - -// angletypes.h: Workarounds for driver bugs and other issues. - -#ifndef LIBGLESV2_RENDERER_WORKAROUNDS_H_ -#define LIBGLESV2_RENDERER_WORKAROUNDS_H_ - -// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate -// independent of ANGLE's renderer. Workarounds should also be accessible -// outside of the Renderer. - -namespace rx -{ - -enum D3DWorkaroundType -{ - ANGLE_D3D_WORKAROUND_NONE, - ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION, - ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION -}; - -struct Workarounds -{ - Workarounds() - : mrtPerfWorkaround(false), - setDataFasterThanImageUpload(false) - {} - - bool mrtPerfWorkaround; - bool setDataFasterThanImageUpload; -}; - -} - -#endif // LIBGLESV2_RENDERER_WORKAROUNDS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h deleted file mode 100644 index e0e8af166b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2013-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. -// - -// copyvertex.h: Defines vertex buffer copying and conversion functions - -#ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_ -#define LIBGLESV2_RENDERER_COPYVERTEX_H_ - -#include "common/mathutil.h" - -namespace rx -{ - -// 'widenDefaultValueBits' gives the default value for the alpha channel (4th component) -// the sentinel value 0 means we do not want to widen the input or add an alpha channel -template <typename T, size_t componentCount, uint32_t widenDefaultValueBits> -inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -template <size_t componentCount> -inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -template <typename T, size_t componentCount, bool normalized> -inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -template <bool isSigned, bool normalized, bool toFloat> -inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -} - -#include "copyvertex.inl" - -#endif // LIBGLESV2_RENDERER_COPYVERTEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp deleted file mode 100644 index 12b919ab5a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2012 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. -// - -// Image.h: Implements the rx::Image class, an abstract base class for the -// renderer-specific classes which will define the interface to the underlying -// surfaces or resources. - -#include "libGLESv2/renderer/d3d/ImageD3D.h" - -namespace rx -{ - -ImageD3D::ImageD3D() -{ -} - -ImageD3D *ImageD3D::makeImageD3D(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(ImageD3D*, img)); - return static_cast<ImageD3D*>(img); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h deleted file mode 100644 index 554ca0cee0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) 2002-2012 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. -// - -// Image.h: Defines the rx::Image class, an abstract base class for the -// renderer-specific classes which will define the interface to the underlying -// surfaces or resources. - -#ifndef LIBGLESV2_RENDERER_IMAGED3D_H_ -#define LIBGLESV2_RENDERER_IMAGED3D_H_ - -#include "common/debug.h" -#include "libGLESv2/renderer/Image.h" - -namespace gl -{ -class Framebuffer; -struct ImageIndex; -struct Box; -} - -namespace rx -{ -class TextureStorage; - -class ImageD3D : public Image -{ - public: - ImageD3D(); - virtual ~ImageD3D() {}; - - static ImageD3D *makeImageD3D(Image *img); - - virtual bool isDirty() const = 0; - - virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(ImageD3D); -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h deleted file mode 100644 index 9440a449f2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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. -// - -// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl. - -#ifndef LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ -#define LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ - -#include "angle_gl.h" - -#include "common/angleutils.h" -#include "libGLESv2/renderer/RenderbufferImpl.h" - -namespace rx -{ -class RendererD3D; -class RenderTarget; -class SwapChain; - -class RenderbufferD3D : public RenderbufferImpl -{ - public: - RenderbufferD3D(RendererD3D *renderer); - virtual ~RenderbufferD3D(); - - static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); - - virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override; - gl::Error setStorage(SwapChain *swapChain, bool depth); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - RenderTarget *getRenderTarget(); - unsigned int getRenderTargetSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferD3D); - - RendererD3D *mRenderer; - RenderTarget *mRenderTarget; -}; -} - -#endif // LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp deleted file mode 100644 index 5cddd8ab5e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp +++ /dev/null @@ -1,801 +0,0 @@ -// -// 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. -// - -// RendererD3D.cpp: Implementation of the base D3D Renderer. - -#include "libGLESv2/renderer/d3d/RendererD3D.h" - -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/ResourceManager.h" -#include "libGLESv2/State.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/formatutils.h" -#include "common/utilities.h" - -namespace rx -{ - -RendererD3D::RendererD3D(egl::Display *display) - : mDisplay(display) -{ -} - -RendererD3D::~RendererD3D() -{ - cleanup(); -} - -void RendererD3D::cleanup() -{ - for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i) - { - i->second.set(NULL); - } - mIncompleteTextures.clear(); -} - -// static -RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer)); - return static_cast<RendererD3D*>(renderer); -} - -gl::Error RendererD3D::drawElements(const gl::Data &data, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) -{ - ASSERT(data.state->getCurrentProgramId() != 0); - - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - gl::Error error = generateSwizzles(data); - if (error.isError()) - { - return error; - } - - if (!applyPrimitiveType(mode, count)) - { - return gl::Error(GL_NO_ERROR); - } - - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); - if (error.isError()) - { - return error; - } - - gl::VertexArray *vao = data.state->getVertexArray(); - TranslatedIndexData indexInfo; - indexInfo.indexRange = indexRange; - error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); - if (error.isError()) - { - return error; - } - - GLsizei vertexCount = indexInfo.indexRange.length() + 1; - error = applyVertexBuffer(*data.state, indexInfo.indexRange.start, vertexCount, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(data); - // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation - // layer. - ASSERT(!transformFeedbackActive); - - error = applyShaders(data, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(data); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(data); - if (error.isError()) - { - return error; - } - - if (!skipDraw(data, mode)) - { - error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::drawArrays(const gl::Data &data, - GLenum mode, GLint first, - GLsizei count, GLsizei instances) -{ - ASSERT(data.state->getCurrentProgramId() != 0); - - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - gl::Error error = generateSwizzles(data); - if (error.isError()) - { - return error; - } - - if (!applyPrimitiveType(mode, count)) - { - return gl::Error(GL_NO_ERROR); - } - - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); - if (error.isError()) - { - return error; - } - - error = applyVertexBuffer(*data.state, first, count, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(data); - - error = applyShaders(data, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(data); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(data); - if (error.isError()) - { - return error; - } - - if (!skipDraw(data, mode)) - { - error = drawArrays(mode, count, instances, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - if (transformFeedbackActive) - { - markTransformFeedbackUsage(data); - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) -{ - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - - 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, *data.caps); - if (textureUnit != -1) - { - gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - if (texture->getSamplerState().swizzleRequired()) - { - gl::Error error = generateSwizzle(texture); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::generateSwizzles(const gl::Data &data) -{ - gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX); - if (error.isError()) - { - return error; - } - - error = generateSwizzles(data, gl::SAMPLER_PIXEL); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) -{ - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->completeness(data) == GL_FRAMEBUFFER_COMPLETE); - - gl::Error error = applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } - - float nearZ, farZ; - data.state->getDepthRange(&nearZ, &farZ); - setViewport(data.state->getViewport(), nearZ, farZ, drawMode, - data.state->getRasterizerState().frontFace, ignoreViewport); - - setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - - return gl::Error(GL_NO_ERROR); -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device -gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) -{ - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - int samples = framebufferObject->getSamples(data); - - gl::RasterizerState rasterizer = data.state->getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - gl::Error error = setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - - unsigned int mask = 0; - if (data.state->isSampleCoverageEnabled()) - { - GLclampf coverageValue; - bool coverageInvert = false; - data.state->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 = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), - data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -bool RendererD3D::applyTransformFeedbackBuffers(const gl::Data &data) -{ - gl::TransformFeedback *curTransformFeedback = data.state->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - applyTransformFeedbackBuffers(*data.state); - return true; - } - else - { - return false; - } -} - -// Applies the shaders and shader constants to the Direct3D device -gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedbackActive) -{ - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; - gl::VertexFormat::GetInputLayout(inputLayout, programBinary, *data.state); - - const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); - - gl::Error error = applyShaders(programBinary, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - return programBinary->applyUniforms(); -} - -// 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). -gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) -{ - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - - 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, *data.caps); - if (textureUnit != -1) - { - gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - gl::SamplerState sampler = texture->getSamplerState(); - - gl::Sampler *samplerObject = data.state->getSampler(textureUnit); - if (samplerObject) - { - samplerObject->getState(&sampler); - } - - // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler, *data.textureCaps, *data.extensions, data.clientVersion) && - !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) - { - gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler); - if (error.isError()) - { - return error; - } - - error = 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. - gl::Texture *incompleteTexture = getIncompleteTexture(textureType); - gl::Error error = 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 - gl::Error error = setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - } - - // Set all the remaining textures to NULL - size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits - : data.caps->maxVertexTextureImageUnits; - for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) - { - gl::Error error = setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::applyTextures(const gl::Data &data) -{ - FramebufferTextureSerialArray framebufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials); - - gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::applyUniformBuffers(const gl::Data &data) -{ - gl::Program *programObject = data.resourceManager->getProgram(data.state->getCurrentProgramId()); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - std::vector<gl::Buffer*> boundBuffers; - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) - { - GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); - - if (data.state->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 - { - gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(blockBinding); - ASSERT(uniformBuffer); - boundBuffers.push_back(uniformBuffer); - } - } - - return programBinary->applyUniformBuffers(boundBuffers, *data.caps); -} - -bool RendererD3D::skipDraw(const gl::Data &data, 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 (!data.state->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 (gl::IsTriangleMode(drawMode)) - { - if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK) - { - return true; - } - } - - return false; -} - -void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) -{ - for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) - { - gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); - if (buffer) - { - buffer->markTransformFeedbackUsage(); - } - } -} - -size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data, - FramebufferTextureSerialArray *outSerialArray) -{ - size_t serialCount = 0; - - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) - { - gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); - if (attachment && attachment->isTexture()) - { - gl::Texture *texture = attachment->getTexture(); - (*outSerialArray)[serialCount++] = texture->getTextureSerial(); - } - } - - gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilAttachment && depthStencilAttachment->isTexture()) - { - gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture(); - (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); - } - - std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); - - return serialCount; -} - -gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) -{ - if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) - { - const GLubyte color[] = { 0, 0, 0, 255 }; - const gl::PixelUnpackState incompleteUnpackState(1); - - gl::Texture* t = NULL; - switch (type) - { - default: - UNREACHABLE(); - // default falls through to TEXTURE_2D - - case GL_TEXTURE_2D: - { - gl::Texture2D *incomplete2d = new gl::Texture2D(createTexture(GL_TEXTURE_2D), gl::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: - { - gl::TextureCubeMap *incompleteCube = new gl::TextureCubeMap(createTexture(GL_TEXTURE_CUBE_MAP), gl::Texture::INCOMPLETE_TEXTURE_ID); - - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incompleteCube; - } - break; - - case GL_TEXTURE_3D: - { - gl::Texture3D *incomplete3d = new gl::Texture3D(createTexture(GL_TEXTURE_3D), gl::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: - { - gl::Texture2DArray *incomplete2darray = new gl::Texture2DArray(createTexture(GL_TEXTURE_2D_ARRAY), gl::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(); -} - -gl::Error RendererD3D::clear(const gl::Data &data, GLbitfield mask) -{ - gl::ClearParameters clearParams = data.state->getClearParameters(mask); - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) -{ - // glClearBufferfv can be called to clear the color buffer or depth buffer - gl::ClearParameters clearParams = data.state->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 = gl::ColorF(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_FLOAT; - } - - if (buffer == GL_DEPTH) - { - clearParams.clearDepth = true; - clearParams.depthClearValue = values[0]; - } - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) -{ - // glClearBufferuiv can only be called to clear a color buffer - gl::ClearParameters clearParams = data.state->getClearParameters(0); - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); - } - clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_UNSIGNED_INT; - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) -{ - // glClearBufferiv can be called to clear the color buffer or stencil buffer - gl::ClearParameters clearParams = data.state->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 = gl::ColorI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_INT; - } - - if (buffer == GL_STENCIL) - { - clearParams.clearStencil = true; - clearParams.stencilClearValue = values[1]; - } - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, - GLfloat depth, GLint stencil) -{ - if (data.state->isRasterizerDiscardEnabled()) - { - return gl::Error(GL_NO_ERROR); - } - - // glClearBufferfi can only be called to clear a depth stencil buffer - gl::ClearParameters clearParams = data.state->getClearParameters(0); - clearParams.clearDepth = true; - clearParams.depthClearValue = depth; - clearParams.clearStencil = true; - clearParams.stencilClearValue = stencil; - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::blitFramebuffer(const gl::Data &data, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - const gl::Framebuffer *readFramebuffer = data.state->getReadFramebuffer(); - const gl::Framebuffer *drawFramebuffer = data.state->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; - } - - gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); - gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); - if (blitRenderTarget || blitDepth || blitStencil) - { - const gl::Rectangle *scissor = data.state->isScissorTestEnabled() ? &data.state->getScissor() : NULL; - gl::Error error = blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, - blitRenderTarget, blitDepth, blitStencil, filter); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) -{ - const gl::Framebuffer *framebuffer = data.state->getReadFramebuffer(); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); - const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, data.state->getPackAlignment()); - - return readPixels(framebuffer, x, y, width, height, format, type, outputPitch, data.state->getPackState(), - reinterpret_cast<uint8_t*>(pixels)); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp deleted file mode 100644 index ff90a6a69a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// -// Copyright (c) 2012 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. -// - -// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/ProgramD3D.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" - -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) -{ - for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; - - if (translatedAttributes[attributeIndex].active) - { - inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, - translatedAttribute.currentValueType); - } - } -} - -const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; - -InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) -{ - mCounter = 0; - mDevice = NULL; - mDeviceContext = NULL; - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -InputLayoutCache::~InputLayoutCache() -{ - clear(); -} - -void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) -{ - clear(); - mDevice = device; - mDeviceContext = context; -} - -void InputLayoutCache::clear() -{ - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - SafeRelease(i->second.inputLayout); - } - mInputLayoutMap.clear(); - markDirty(); -} - -void InputLayoutCache::markDirty() -{ - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary) -{ - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; - programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); - - if (!mDevice || !mDeviceContext) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized."); - } - - InputLayoutKey ilKey = { 0 }; - - static const char* semanticName = "TEXCOORD"; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; - - gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); - - // Record the type of the associated vertex shader vector in our key - // This will prevent mismatched vertex shaders from using the same input layout - GLint attributeSize; - programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); - - ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; - ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; - ilKey.elements[ilKey.elementCount].desc.InputSlot = i; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; - ilKey.elementCount++; - } - } - - ID3D11InputLayout *inputLayout = NULL; - - InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); - if (keyIter != mInputLayoutMap.end()) - { - inputLayout = keyIter->second.inputLayout; - keyIter->second.lastUsedTime = mCounter++; - } - else - { - gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; - GetInputLayout(attributes, shaderInputLayout); - ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); - - ShaderExecutable *shader = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader); - if (error.isError()) - { - return error; - } - - ShaderExecutable *shader11 = ShaderExecutable11::makeShaderExecutable11(shader); - - D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; - for (unsigned int j = 0; j < ilKey.elementCount; ++j) - { - descs[j] = ilKey.elements[j].desc; - } - - HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); - } - - if (mInputLayoutMap.size() >= kMaxInputLayouts) - { - TRACE("Overflowed the limit of %u input layouts, removing the least recently used " - "to make room.", kMaxInputLayouts); - - InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) - { - leastRecentlyUsed = i; - } - } - SafeRelease(leastRecentlyUsed->second.inputLayout); - mInputLayoutMap.erase(leastRecentlyUsed); - } - - InputLayoutCounterPair inputCounterPair; - inputCounterPair.inputLayout = inputLayout; - inputCounterPair.lastUsedTime = mCounter++; - - mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); - } - - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - - bool dirtyBuffers = false; - size_t minDiff = gl::MAX_VERTEX_ATTRIBS; - size_t maxDiff = 0; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - ID3D11Buffer *buffer = NULL; - - if (attributes[i].active) - { - VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; - - buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) - : vertexBuffer->getBuffer(); - } - - UINT vertexStride = attributes[i].stride; - UINT vertexOffset = attributes[i].offset; - - if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || - vertexOffset != mCurrentVertexOffsets[i]) - { - dirtyBuffers = true; - minDiff = std::min(minDiff, static_cast<size_t>(i)); - maxDiff = std::max(maxDiff, static_cast<size_t>(i)); - - mCurrentBuffers[i] = buffer; - mCurrentVertexStrides[i] = vertexStride; - mCurrentVertexOffsets[i] = vertexOffset; - } - } - - if (dirtyBuffers) - { - ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); - mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, - mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); - } - - return gl::Error(GL_NO_ERROR); -} - -std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) -{ - static const unsigned int seed = 0xDEADBEEF; - - std::size_t hash = 0; - MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); - return hash; -} - -bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) -{ - if (a.elementCount != b.elementCount) - { - return false; - } - - return std::equal(a.begin(), a.end(), b.begin()); -} - -} diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h index 30bb7e3b94..27917e6eec 100644 --- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ -#define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ +#ifndef THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_ +#define THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" @@ -57,4 +57,4 @@ private: bool mArrayBoundsClampDefinitionNeeded; }; -#endif // THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ +#endif // THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_ diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp index dd86292649..a599c26502 100644 --- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp @@ -29,6 +29,8 @@ #else // defined(_MSC_VER) +// Ignore GCC force inline warnings +#pragma GCC diagnostic ignored "-Wattributes" #define FORCE_INLINE __attribute__((always_inline)) inline uint32_t rotl32 ( uint32_t x, int8_t r ) diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h index adb52004e2..bb02cd508f 100644 --- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h @@ -20,4 +20,4 @@ void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out //----------------------------------------------------------------------------- -#endif // _MURMURHASH3_H_
\ No newline at end of file +#endif // _MURMURHASH3_H_ diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h index 65005ee9c6..226085fbd3 100644 --- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h +++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SystemInfo_h -#define SystemInfo_h +#ifndef THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_ +#define THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_ namespace rx { @@ -32,4 +32,4 @@ bool isWindowsVistaOrGreater(); } // namespace rx -#endif // SystemInfo_h +#endif // THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_ diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h new file mode 100644 index 0000000000..af59dcfcc3 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h @@ -0,0 +1,795 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Trace events are for tracking application performance and resource usage. +// Macros are provided to track: +// Begin and end of function calls +// Counters +// +// Events are issued against categories. Whereas LOG's +// categories are statically defined, TRACE categories are created +// implicitly with a string. For example: +// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") +// +// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: +// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") +// doSomethingCostly() +// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") +// Note: our tools can't always determine the correct BEGIN/END pairs unless +// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them +// to be in separate scopes. +// +// A common use case is to trace entire function scopes. This +// issues a trace BEGIN and END automatically: +// void doSomethingCostly() { +// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); +// ... +// } +// +// Additional parameters can be associated with an event: +// void doSomethingCostly2(int howMuch) { +// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", +// "howMuch", howMuch); +// ... +// } +// +// The trace system will automatically add to this information the +// current process id, thread id, and a timestamp in microseconds. +// +// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and +// ASYNC_END: +// [single threaded sender code] +// static int send_count = 0; +// ++send_count; +// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); +// Send(new MyMessage(send_count)); +// [receive code] +// void OnMyMessage(send_count) { +// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); +// } +// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. +// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can +// be used for the ID parameter, and they will be mangled internally so that +// the same pointer on two different processes will not match. For example: +// class MyTracedClass { +// public: +// MyTracedClass() { +// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); +// } +// ~MyTracedClass() { +// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); +// } +// } +// +// Trace event also supports counters, which is a way to track a quantity +// as it varies over time. Counters are created with the following macro: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); +// +// Counters are process-specific. The macro itself can be issued from any +// thread, however. +// +// Sometimes, you want to track two counters at once. You can do this with two +// counter macros: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); +// Or you can do it with a combined macro: +// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", +// "bytesPinned", g_myCounterValue[0], +// "bytesAllocated", g_myCounterValue[1]); +// This indicates to the tracing UI that these counters should be displayed +// in a single graph, as a summed area chart. +// +// Since counters are in a global namespace, you may want to disembiguate with a +// unique ID, by using the TRACE_COUNTER_ID* variations. +// +// By default, trace collection is compiled in, but turned off at runtime. +// Collecting trace data is the responsibility of the embedding +// application. In Chrome's case, navigating to about:tracing will turn on +// tracing and display data collected across all active processes. +// +// +// Memory scoping note: +// Tracing copies the pointers, not the string content, of the strings passed +// in for category, name, and arg_names. Thus, the following code will +// cause problems: +// char* str = strdup("impprtantName"); +// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! +// free(str); // Trace system now has dangling pointer +// +// To avoid this issue with the |name| and |arg_name| parameters, use the +// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. +// Notes: The category must always be in a long-lived char* (i.e. static const). +// The |arg_values|, when used, are always deep copied with the _COPY +// macros. +// +// When are string argument values copied: +// const char* arg_values are only referenced by default: +// TRACE_EVENT1("category", "name", +// "arg1", "literal string is only referenced"); +// Use TRACE_STR_COPY to force copying of a const char*: +// TRACE_EVENT1("category", "name", +// "arg1", TRACE_STR_COPY("string will be copied")); +// std::string arg_values are always copied: +// TRACE_EVENT1("category", "name", +// "arg1", std::string("string will be copied")); +// +// +// Thread Safety: +// A thread safe singleton and mutex are used for thread safety. Category +// enabled flags are used to limit the performance impact when the system +// is not enabled. +// +// TRACE_EVENT macros first cache a pointer to a category. The categories are +// statically allocated and safe at all times, even after exit. Fetching a +// category is protected by the TraceLog::lock_. Multiple threads initializing +// the static variable is safe, as they will be serialized by the lock and +// multiple calls will return the same pointer to the category. +// +// Then the category_enabled flag is checked. This is a unsigned char, and +// not intended to be multithread safe. It optimizes access to addTraceEvent +// which is threadsafe internally via TraceLog::lock_. The enabled flag may +// cause some threads to incorrectly call or skip calling addTraceEvent near +// the time of the system being enabled or disabled. This is acceptable as +// we tolerate some data loss while the system is being enabled/disabled and +// because addTraceEvent is threadsafe internally and checks the enabled state +// again under lock. +// +// Without the use of these static category pointers and enabled flags all +// trace points would carry a significant performance cost of aquiring a lock +// and resolving the category. + +#ifndef COMMON_TRACE_EVENT_H_ +#define COMMON_TRACE_EVENT_H_ + +#include <string> + +#include "common/event_tracer.h" + +// By default, const char* argument values are assumed to have long-lived scope +// and will not be copied. Use this macro to force a const char* to be copied. +#define TRACE_STR_COPY(str) \ + WebCore::TraceEvent::TraceStringWithCopy(str) + +// Records a pair of begin and end events called "name" for the current +// scope, with 0, 1 or 2 associated arguments. If the category is not +// enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name) +#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val) +#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_INSTANT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_INSTANT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_BEGIN0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_BEGIN0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single END event for "name" immediately. If the category +// is not enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_END0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_END0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER1(category, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast<int>(value)) +#define TRACE_COPY_COUNTER1(category, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast<int>(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) +#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID1(category, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast<int>(value)) +#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast<int>(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) +#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast<int>(value1_val), \ + value2_name, static_cast<int>(value2_val)) + +// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC +// events are considered to match if their category, name and id values all +// match. |id| must either be a pointer or an integer value up to 64 bits. If +// it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +// An asynchronous operation can consist of multiple phases. The first phase is +// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the +// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. +// An async operation can span threads and processes, but all events in that +// operation must use the same |name| and |id|. Each event can have its own +// args. +#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Records a single ASYNC_STEP event for |step| immediately. If the category +// is not enabled, then this does nothing. The |name| and |id| must match the +// ASYNC_BEGIN event above. The |step| param identifies this step within the +// async event. This should be called at the beginning of the next phase of an +// asynchronous operation. +#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_NONE, "step", step) +#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step) +#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \ + arg1_name, arg1_val) + +// Records a single ASYNC_END event for "name" immediately. If the category +// is not enabled, then this does nothing. +#define TRACE_EVENT_ASYNC_END0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Creates a scope of a sampling state with the given category and name (both must +// be constant strings). These states are intended for a sampling profiler. +// Implementation note: we store category and name together because we don't +// want the inconsistency/expense of storing two pointers. +// |thread_bucket| is [0..2] and is used to statically isolate samples in one +// thread from others. +// +// { // The sampling state is set within this scope. +// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); +// ...; +// } +#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ + TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name); + +// Returns a current sampling state of the given bucket. +// The format of the returned string is "category\0name". +#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ + TraceEvent::SamplingStateScope<bucket_number>::current() + +// Sets a current sampling state of the given bucket. +// |category| and |name| have to be constant strings. +#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ + TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name) + +// Sets a current sampling state of the given bucket. +// |categoryAndName| doesn't need to be a constant string. +// The format of the string is "category\0name". +#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \ + TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName) + +// Syntactic sugars for the sampling tracing in the main thread. +#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_GET_SAMPLING_STATE() \ + TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) +#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \ + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName) + +//////////////////////////////////////////////////////////////////////////////// +// Implementation specific tracing API definitions. + +// Get a pointer to the enabled state of the given trace category. Only +// long-lived literal strings should be given as the category name. The returned +// pointer can be held permanently in a local static for example. If the +// unsigned char is non-zero, tracing is enabled. If tracing is enabled, +// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled +// between the load of the tracing state and the call to +// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out +// for best performance when tracing is disabled. +// const unsigned char* +// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name) +#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \ + gl::TraceGetTraceCategoryEnabledFlag + +// Add a trace event to the platform tracing system. +// void TRACE_EVENT_API_ADD_TRACE_EVENT( +// char phase, +// const unsigned char* category_enabled, +// const char* name, +// unsigned long long id, +// int num_args, +// const char** arg_names, +// const unsigned char* arg_types, +// const unsigned long long* arg_values, +// unsigned char flags) +#define TRACE_EVENT_API_ADD_TRACE_EVENT \ + gl::TraceAddTraceEvent + +//////////////////////////////////////////////////////////////////////////////// + +// Implementation detail: trace event macros create temporary variables +// to keep instrumentation overhead low. These macros give each temporary +// variable a unique name based on the line number to prevent name collissions. +#define INTERNAL_TRACE_EVENT_UID3(a, b) \ + trace_event_unique_##a##b +#define INTERNAL_TRACE_EVENT_UID2(a, b) \ + INTERNAL_TRACE_EVENT_UID3(a, b) +#define INTERNALTRACEEVENTUID(name_prefix) \ + INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) + +// Implementation detail: internal macro to create static category. +#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \ + static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \ + if (!INTERNALTRACEEVENTUID(catstatic)) \ + INTERNALTRACEEVENTUID(catstatic) = \ + TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + gl::TraceEvent::addTraceEvent( \ + phase, INTERNALTRACEEVENTUID(catstatic), name, \ + gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \ + } \ + } while (0) + +// Implementation detail: internal macro to create static category and add begin +// event if the category is enabled. Also adds the end event when the scope +// ends. +#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + gl::TraceEvent::TraceEndOnScopeClose \ + INTERNALTRACEEVENTUID(profileScope); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + gl::TraceEvent::addTraceEvent( \ + TRACE_EVENT_PHASE_BEGIN, \ + INTERNALTRACEEVENTUID(catstatic), \ + name, gl::TraceEvent::noEventId, \ + TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ + INTERNALTRACEEVENTUID(profileScope).initialize( \ + INTERNALTRACEEVENTUID(catstatic), name); \ + } + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \ + ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + gl::TraceEvent::TraceID traceEventTraceID( \ + id, &traceEventFlags); \ + gl::TraceEvent::addTraceEvent( \ + phase, INTERNALTRACEEVENTUID(catstatic), \ + name, traceEventTraceID.data(), traceEventFlags, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +// Notes regarding the following definitions: +// New values can be added and propagated to third party libraries, but existing +// definitions must never be changed, because third party libraries may use old +// definitions. + +// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. +#define TRACE_EVENT_PHASE_BEGIN ('B') +#define TRACE_EVENT_PHASE_END ('E') +#define TRACE_EVENT_PHASE_INSTANT ('I') +#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') +#define TRACE_EVENT_PHASE_ASYNC_STEP ('T') +#define TRACE_EVENT_PHASE_ASYNC_END ('F') +#define TRACE_EVENT_PHASE_METADATA ('M') +#define TRACE_EVENT_PHASE_COUNTER ('C') +#define TRACE_EVENT_PHASE_SAMPLE ('P') + +// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. +#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0)) +#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0)) +#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1)) +#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2)) + +// Type values for identifying types in the TraceValue union. +#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) +#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) +#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) +#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) +#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) +#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) +#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7)) + + +namespace gl { + +namespace TraceEvent { + +// Specify these values when the corresponding argument of addTraceEvent is not +// used. +const int zeroNumArgs = 0; +const unsigned long long noEventId = 0; + +// TraceID encapsulates an ID that can either be an integer or pointer. Pointers +// are mangled with the Process ID so that they are unlikely to collide when the +// same pointer is used on different processes. +class TraceID { +public: + explicit TraceID(const void* id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id))) + { + *flags |= TRACE_EVENT_FLAG_MANGLE_ID; + } + explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(long long id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(long id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(int id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(short id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + explicit TraceID(signed char id, unsigned char* flags) : + m_data(static_cast<unsigned long long>(id)) { (void)flags; } + + unsigned long long data() const { return m_data; } + +private: + unsigned long long m_data; +}; + +// Simple union to store various types as unsigned long long. +union TraceValueUnion { + bool m_bool; + unsigned long long m_uint; + long long m_int; + double m_double; + const void* m_pointer; + const char* m_string; +}; + +// Simple container for const char* that should be copied instead of retained. +class TraceStringWithCopy { +public: + explicit TraceStringWithCopy(const char* str) : m_str(str) { } + operator const char* () const { return m_str; } +private: + const char* m_str; +}; + +// Define setTraceValue for each allowed type. It stores the type and +// value in the return arguments. This allows this API to avoid declaring any +// structures so that it is portable to third_party libraries. +#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ + union_member, \ + value_type_id) \ + static inline void setTraceValue(actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + TraceValueUnion typeValue; \ + typeValue.union_member = arg; \ + *type = value_type_id; \ + *value = typeValue.m_uint; \ + } +// Simpler form for int types that can be safely casted. +#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ + value_type_id) \ + static inline void setTraceValue(actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + *type = value_type_id; \ + *value = static_cast<unsigned long long>(arg); \ + } + +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL) +INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE) +INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer, + TRACE_VALUE_TYPE_POINTER) +INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string, + TRACE_VALUE_TYPE_STRING) +INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string, + TRACE_VALUE_TYPE_COPY_STRING) + +#undef INTERNAL_DECLARE_SET_TRACE_VALUE +#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT + +static inline void setTraceValue(const std::string& arg, + unsigned char* type, + unsigned long long* value) { + TraceValueUnion typeValue; + typeValue.m_string = arg.data(); + *type = TRACE_VALUE_TYPE_COPY_STRING; + *value = typeValue.m_uint; +} + +// These addTraceEvent template functions are defined here instead of in the +// macro, because the arg values could be temporary string objects. In order to +// store pointers to the internal c_str and pass through to the tracing API, the +// arg values must live throughout these procedures. + +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags) { + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + zeroNumArgs, 0, 0, 0, + flags); +} + +template<class ARG1_TYPE> +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1Name, + const ARG1_TYPE& arg1Val) { + const int numArgs = 1; + unsigned char argTypes[1]; + unsigned long long argValues[1]; + setTraceValue(arg1Val, &argTypes[0], &argValues[0]); + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + numArgs, &arg1Name, argTypes, argValues, + flags); +} + +template<class ARG1_TYPE, class ARG2_TYPE> +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1Name, + const ARG1_TYPE& arg1Val, + const char* arg2Name, + const ARG2_TYPE& arg2Val) { + const int numArgs = 2; + const char* argNames[2] = { arg1Name, arg2Name }; + unsigned char argTypes[2]; + unsigned long long argValues[2]; + setTraceValue(arg1Val, &argTypes[0], &argValues[0]); + setTraceValue(arg2Val, &argTypes[1], &argValues[1]); + return TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + numArgs, argNames, argTypes, argValues, + flags); +} + +// Used by TRACE_EVENTx macro. Do not use directly. +class TraceEndOnScopeClose { +public: + // Note: members of m_data intentionally left uninitialized. See initialize. + TraceEndOnScopeClose() : m_pdata(0) { } + ~TraceEndOnScopeClose() + { + if (m_pdata) + addEventIfEnabled(); + } + + void initialize(const unsigned char* categoryEnabled, + const char* name) + { + m_data.categoryEnabled = categoryEnabled; + m_data.name = name; + m_pdata = &m_data; + } + +private: + // Add the end event if the category is still enabled. + void addEventIfEnabled() + { + // Only called when m_pdata is non-null. + if (*m_pdata->categoryEnabled) { + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_END, + m_pdata->categoryEnabled, + m_pdata->name, noEventId, + zeroNumArgs, 0, 0, 0, + TRACE_EVENT_FLAG_NONE); + } + } + + // This Data struct workaround is to avoid initializing all the members + // in Data during construction of this object, since this object is always + // constructed, even when tracing is disabled. If the members of Data were + // members of this class instead, compiler warnings occur about potential + // uninitialized accesses. + struct Data { + const unsigned char* categoryEnabled; + const char* name; + }; + Data* m_pdata; + Data m_data; +}; + +} // namespace TraceEvent + +} // namespace gl + +#endif |