ANGLE: Upgrade to version 1.2.30d6c255d238

The following patches have been changed:

0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch
  Removed because it is no longer possible to build ANGLE with MSVC2008

0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch
  Removed because the minimum version of MinGW moved to 4.8.2

0005-Fix-build-when-SSE2-is-not-available.patch
  Removed because it was fixed upstream

0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch
  Removed because older versions of MinGW are not supported

0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
  Removed because it was fixed upstream

Task-number: QTBUG-41903
Change-Id: I976d30802f7f6fee725cf9a9f1325d5e82609835
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
This commit is contained in:
Andrew Knight 2014-11-14 10:52:01 +02:00 committed by Jani Heikkinen
parent 32db2f425a
commit c6df5fe3ed
231 changed files with 16959 additions and 13672 deletions

View File

@ -21,10 +21,12 @@ Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
Microsoft Open Technologies, Inc.
NVIDIA Corporation
Jacek Caban
Mark Callow
Ginn Chen
Tibor den Ouden
James Hauxwell
Sam Hocevar
Pierre Leveille

View File

@ -78,7 +78,12 @@ Turbulenz
Ulrik Persson (ddefrostt)
Mark Banner (standard8mbp)
David Kilzer
Jacek Caban
Tibor den Ouden
Microsoft Open Technologies, Inc.
Cooper Partin
Austin Kinross
NVIDIA Corporation
Olli Etuaho

View File

@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
#ifndef EGL_VERSION_1_5
#define EGL_VERSION_1_5 1
typedef void *EGLSync;
typedef khronos_intptr_t EGLAttrib;
typedef intptr_t EGLAttrib;
typedef khronos_utime_nanoseconds_t EGLTime;
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB

View File

@ -59,7 +59,7 @@ extern "C" {
#ifndef EGL_KHR_cl_event2
#define EGL_KHR_cl_event2 1
typedef void *EGLSyncKHR;
typedef khronos_intptr_t EGLAttribKHR;
typedef intptr_t EGLAttribKHR;
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
@ -442,20 +442,22 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205
#endif /* EGL_ANGLE_platform_angle */
#ifndef EGL_ANGLE_platform_angle_d3d
#define EGL_ANGLE_platform_angle_d3d 1
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
#endif /* EGL_ANGLE_platform_angle_d3d */
#ifndef EGL_ANGLE_platform_angle_opengl
#define EGL_ANGLE_platform_angle_opengl 1
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ARM_pixmap_multisample_discard

View File

@ -67,23 +67,22 @@
* implementations.
*/
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */
struct IUnknown;
typedef IUnknown *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef IUnknown *EGLNativeWindowType;
#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeDisplayType;
typedef IInspectable* EGLNativeWindowType;
#else
typedef HDC EGLNativeDisplayType;
typedef HWND EGLNativeWindowType;
#endif
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */

View File

@ -27,6 +27,10 @@
#include "KHR/khrplatform.h"
#include <map>
#include <string>
#include <vector>
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
@ -42,18 +46,17 @@ typedef unsigned int GLenum;
// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
#include "ShaderVars.h"
#ifdef __cplusplus
extern "C" {
#endif
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 130
#define ANGLE_SH_VERSION 132
typedef enum {
SH_GLES2_SPEC = 0x8B40,
SH_WEBGL_SPEC = 0x8B41,
SH_GLES3_SPEC = 0x8B86,
SH_WEBGL2_SPEC = 0x8B87,
// The CSS Shaders spec is a subset of the WebGL spec.
//
// In both CSS vertex and fragment shaders, ANGLE:
@ -85,31 +88,6 @@ typedef enum {
SH_HLSL11_OUTPUT = 0x8B48
} ShShaderOutput;
typedef enum {
SH_PRECISION_HIGHP = 0x5001,
SH_PRECISION_MEDIUMP = 0x5002,
SH_PRECISION_LOWP = 0x5003,
SH_PRECISION_UNDEFINED = 0
} ShPrecisionType;
typedef enum {
SH_INFO_LOG_LENGTH = 0x8B84,
SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH
SH_ACTIVE_UNIFORMS = 0x8B86,
SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
SH_ACTIVE_ATTRIBUTES = 0x8B89,
SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
SH_VARYINGS = 0x8BBB,
SH_VARYING_MAX_LENGTH = 0x8BBC,
SH_MAPPED_NAME_MAX_LENGTH = 0x6000,
SH_NAME_MAX_LENGTH = 0x6001,
SH_HASHED_NAME_MAX_LENGTH = 0x6002,
SH_HASHED_NAMES_COUNT = 0x6003,
SH_SHADER_VERSION = 0x6004,
SH_RESOURCES_STRING_LENGTH = 0x6005,
SH_OUTPUT_TYPE = 0x6006
} ShShaderInfo;
// Compile options.
typedef enum {
SH_VALIDATE = 0,
@ -208,14 +186,14 @@ typedef enum {
//
// Driver must call this first, once, before doing any other
// compiler operations.
// If the function succeeds, the return value is nonzero, else zero.
// If the function succeeds, the return value is true, else false.
//
COMPILER_EXPORT int ShInitialize();
COMPILER_EXPORT bool ShInitialize();
//
// Driver should call this at shutdown.
// If the function succeeds, the return value is nonzero, else zero.
// If the function succeeds, the return value is true, else false.
//
COMPILER_EXPORT int ShFinalize();
COMPILER_EXPORT bool ShFinalize();
// The 64 bits hash function. The first parameter is the input string; the
// second parameter is the string length.
@ -246,6 +224,12 @@ typedef struct
int EXT_frag_depth;
int EXT_shader_texture_lod;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
// EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
// function. This applies to Tegra K1 devices.
int NV_draw_buffers;
// Set to 1 if highp precision is supported in the fragment language.
// Default is 0.
int FragmentPrecisionHigh;
@ -274,8 +258,10 @@ typedef struct
//
// Initialize built-in resources with minimum expected values.
// Parameters:
// resources: The object to initialize. Will be comparable with memcmp.
//
COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
//
// ShHandle held by but opaque to the driver. It is allocated,
@ -284,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
//
// If handle creation fails, 0 will be returned.
//
typedef void* ShHandle;
typedef void *ShHandle;
//
// Returns the a concatenated list of the items in ShBuiltInResources as a string.
// Returns the a concatenated list of the items in ShBuiltInResources as a
// null-terminated string.
// This function must be updated whenever ShBuiltInResources is changed.
// Parameters:
// handle: Specifies the handle of the compiler to be used.
// outStringLen: Specifies the size of the buffer, in number of characters. The size
// of the buffer required to store the resources string can be obtained
// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH.
// outStr: Returns a null-terminated string representing all the built-in resources.
COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr);
COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
//
// Driver calls these to create and destroy compiler objects.
@ -313,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources* resources);
const ShBuiltInResources *resources);
COMPILER_EXPORT void ShDestruct(ShHandle handle);
//
// Compiles the given shader source.
// If the function succeeds, the return value is nonzero, else zero.
// If the function succeeds, the return value is true, else false.
// Parameters:
// handle: Specifies the handle of compiler to be used.
// shaderStrings: Specifies an array of pointers to null-terminated strings
@ -340,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle);
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
COMPILER_EXPORT int ShCompile(
COMPILER_EXPORT bool ShCompile(
const ShHandle handle,
const char* const shaderStrings[],
const char * const shaderStrings[],
size_t numStrings,
int compileOptions
);
int compileOptions);
// Returns a parameter from a compiled shader.
// Return the version of the shader language.
COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
// Return the currently set language output type.
COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType(
const ShHandle handle);
// Returns null-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
// pname: Specifies the parameter to query.
// The following parameters are defined:
// SH_INFO_LOG_LENGTH: the number of characters in the information log
// including the null termination character.
// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
// including the null termination character.
// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
// variable name including the null
// termination character.
// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
// variable name including the null
// termination character.
// SH_VARYINGS: the number of varying variables.
// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
// including the null termination character.
// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
// the null termination character.
// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
// null termination character.
// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the
// null termination character.
// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile.
// SH_SHADER_VERSION: the version of the shader language
// SH_OUTPUT_TYPE: the currently set language output type
//
// params: Requested parameter
COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
ShShaderInfo pname,
size_t* params);
// Returns nul-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
// infoLog: Specifies an array of characters that is used to return
// the information log. It is assumed that infoLog has enough memory
// to accomodate the information log. The size of the buffer required
// to store the returned information log can be obtained by calling
// ShGetInfo with SH_INFO_LOG_LENGTH.
COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle);
// Returns null-terminated object code for a compiled shader.
// Parameters:
// handle: Specifies the compiler
// infoLog: Specifies an array of characters that is used to return
// the object code. It is assumed that infoLog has enough memory to
// accomodate the object code. The size of the buffer required to
// store the returned object code can be obtained by calling
// ShGetInfo with SH_OBJECT_CODE_LENGTH.
COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle);
// Returns information about a shader variable.
// Returns a (original_name, hash) map containing all the user defined
// names in the shader, including variable names, function names, struct
// names, and struct field names.
// Parameters:
// handle: Specifies the compiler
// variableType: Specifies the variable type; options include
// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
// index: Specifies the index of the variable to be queried.
// length: Returns the number of characters actually written in the string
// indicated by name (excluding the null terminator) if a value other
// than NULL is passed.
// size: Returns the size of the variable.
// type: Returns the data type of the variable.
// precision: Returns the precision of the variable.
// staticUse: Returns 1 if the variable is accessed in a statement after
// pre-processing, whether or not run-time flow of control will
// cause that statement to be executed.
// Returns 0 otherwise.
// name: Returns a null terminated string containing the name of the
// variable. It is assumed that name has enough memory to accormodate
// the variable name. The size of the buffer required to store the
// variable name can be obtained by calling ShGetInfo with
// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
// SH_VARYING_MAX_LENGTH.
// mappedName: Returns a null terminated string containing the mapped name of
// the variable, It is assumed that mappedName has enough memory
// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
// mapped name. If the name is not mapped, then name and mappedName
// are the same.
COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
ShShaderInfo variableType,
int index,
size_t* length,
int* size,
sh::GLenum* type,
ShPrecisionType* precision,
int* staticUse,
char* name,
char* mappedName);
// Returns information about a name hashing entry from the latest compile.
// Parameters:
// handle: Specifies the compiler
// index: Specifies the index of the name hashing entry to be queried.
// name: Returns a null terminated string containing the user defined name.
// It is assumed that name has enough memory to accomodate the name.
// The size of the buffer required to store the user defined name can
// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH.
// hashedName: Returns a null terminated string containing the hashed name of
// the uniform variable, It is assumed that hashedName has enough
// memory to accomodate the name. The size of the buffer required
// to store the name can be obtained by calling ShGetInfo with
// SH_HASHED_NAME_MAX_LENGTH.
COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle,
int index,
char* name,
char* hashedName);
COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
const ShHandle handle);
// Shader variable inspection.
// Returns a pointer to a list of variables of the designated type.
@ -476,17 +372,17 @@ typedef struct
int size;
} ShVariableInfo;
// Returns 1 if the passed in variables pack in maxVectors following
// Returns true if the passed in variables pack in maxVectors following
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// flag above.
// Parameters:
// maxVectors: the available rows of registers.
// varInfoArray: an array of variable info (types and sizes).
// varInfoArraySize: the size of the variable array.
COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits(
int maxVectors,
ShVariableInfo* varInfoArray,
ShVariableInfo *varInfoArray,
size_t varInfoArraySize);
// Gives the compiler-assigned register for an interface block.
@ -497,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
// interfaceBlockName: Specifies the interface block
// indexOut: output variable that stores the assigned register
COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
const char *interfaceBlockName,
const std::string &interfaceBlockName,
unsigned int *indexOut);
// Gives the compiler-assigned register for uniforms in the default
@ -509,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
// interfaceBlockName: Specifies the uniform
// indexOut: output variable that stores the assigned register
COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
const char *uniformName,
const std::string &uniformName,
unsigned int *indexOut);
#ifdef __cplusplus
}
#endif
#endif // _COMPILER_INTERFACE_INCLUDED_

View File

@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable
unsigned int elementCount() const { return std::max(1u, arraySize); }
bool isStruct() const { return !fields.empty(); }
// All of the shader's variables are described using nested data
// structures. This is needed in order to disambiguate similar looking
// types, such as two structs containing the same fields, but in
// different orders. "findInfoByMappedName" provides an easy query for
// users to dive into the data structure and fetch the unique variable
// instance corresponding to a dereferencing chain of the top-level
// variable.
// Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
// that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
// in |originalName|, based on the assumption that |this| defines 'a'.
// If no match is found, return false.
bool findInfoByMappedName(const std::string &mappedFullName,
const ShaderVariable **leafVar,
std::string* originalFullName) const;
GLenum type;
GLenum precision;
std::string name;
@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable
bool staticUse;
std::vector<ShaderVariable> fields;
std::string structName;
protected:
bool isSameVariableAtLinkTime(const ShaderVariable &other,
bool matchPrecision) const;
bool operator==(const ShaderVariable &other) const;
bool operator!=(const ShaderVariable &other) const
{
return !operator==(other);
}
};
struct COMPILER_EXPORT Uniform : public ShaderVariable
@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
~Uniform();
Uniform(const Uniform &other);
Uniform &operator=(const Uniform &other);
bool operator==(const Uniform &other) const;
bool operator!=(const Uniform &other) const
{
return !operator==(other);
}
// Decide whether two uniforms are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.5.
bool isSameUniformAtLinkTime(const Uniform &other) const;
};
struct COMPILER_EXPORT Attribute : public ShaderVariable
@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable
~Attribute();
Attribute(const Attribute &other);
Attribute &operator=(const Attribute &other);
bool operator==(const Attribute &other) const;
bool operator!=(const Attribute &other) const
{
return !operator==(other);
}
int location;
};
@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
~InterfaceBlockField();
InterfaceBlockField(const InterfaceBlockField &other);
InterfaceBlockField &operator=(const InterfaceBlockField &other);
bool operator==(const InterfaceBlockField &other) const;
bool operator!=(const InterfaceBlockField &other) const
{
return !operator==(other);
}
// Decide whether two InterfaceBlock fields are the same at shader
// link time, assuming one from vertex shader and the other from
// fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.7.
bool isSameInterfaceBlockFieldAtLinkTime(
const InterfaceBlockField &other) const;
bool isRowMajorLayout;
};
@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
{
Varying();
~Varying();
Varying(const Varying &other);
Varying(const Varying &otherg);
Varying &operator=(const Varying &other);
bool operator==(const Varying &other) const;
bool operator!=(const Varying &other) const
{
return !operator==(other);
}
// Decide whether two varyings are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.9.
bool isSameVaryingAtLinkTime(const Varying &other) const;
InterpolationType interpolation;
bool isInvariant;

View File

@ -0,0 +1,37 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// angle_windowsstore.h:
#ifndef ANGLE_WINDOWSSTORE_H_
#define ANGLE_WINDOWSSTORE_H_
// The following properties can be set on the CoreApplication to support additional
// ANGLE configuration options.
//
// The Visual Studio sample templates provided with this version of ANGLE have examples
// of how to set these property values.
//
// Property: EGLNativeWindowTypeProperty
// Type: IInspectable
// Description: Set this property to specify the window type to use for creating a surface.
// If this property is missing, surface creation will fail.
//
const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
//
// Property: EGLRenderSurfaceSizeProperty
// Type: Size
// Description: Set this property to specify a preferred size in pixels of the render surface.
// The render surface size width and height must be greater than 0.
// If this property is set, then the render surface size is fixed.
// If this property is missing, a default behavior will be provided.
// The default behavior uses the window size if a CoreWindow is specified or
// the size of the SwapChainPanel control if one is specified.
//
const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
#endif // ANGLE_WINDOWSSTORE_H_

View File

@ -7,6 +7,6 @@
// This is a default commit hash header, when git is not available.
//
#define ANGLE_COMMIT_HASH "abce76206141"
#define ANGLE_COMMIT_HASH "30d6c255d238"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000"
#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"

View File

@ -0,0 +1,77 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// NativeWindow.h: Defines NativeWindow, a class for managing and
// performing operations on an EGLNativeWindowType.
// It is used for HWND (Desktop Windows) and IInspectable objects
//(Windows Store Applications).
#ifndef COMMON_NATIVEWINDOW_H_
#define COMMON_NATIVEWINDOW_H_
#include <EGL/eglplatform.h>
#include "common/debug.h"
#include "common/platform.h"
// DXGISwapChain and DXGIFactory are typedef'd to specific required
// types. The HWND NativeWindow implementation requires IDXGISwapChain
// and IDXGIFactory and the Windows Store NativeWindow
// implementation requires IDXGISwapChain1 and IDXGIFactory2.
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
typedef IDXGISwapChain1 DXGISwapChain;
typedef IDXGIFactory2 DXGIFactory;
#include <wrl.h>
#include <wrl/wrappers/corewrappers.h>
#include <windows.applicationmodel.core.h>
#include <memory>
namespace rx
{
class InspectableNativeWindow;
}
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
#else
typedef IDXGISwapChain DXGISwapChain;
typedef IDXGIFactory DXGIFactory;
#endif
namespace rx
{
class NativeWindow
{
public:
explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display);
bool initialize();
bool getClientRect(LPRECT rect);
bool isIconic();
HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
DXGI_FORMAT format, UINT width, UINT height,
DXGISwapChain** swapChain);
inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; }
private:
EGLNativeWindowType mWindow;
EGLNativeDisplayType mDisplay;
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
std::shared_ptr<InspectableNativeWindow> mImpl;
#endif
};
bool IsValidEGLNativeWindowType(EGLNativeWindowType window);
}
#endif // COMMON_NATIVEWINDOW_H_

View File

@ -5,26 +5,33 @@
//
#include "common/angleutils.h"
#include "debug.h"
#include <stdio.h>
#include <vector>
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
{
// Attempt to just print to the current buffer
int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
{
// Buffer was not large enough, calculate the required size and resize the buffer
len = vsnprintf(NULL, 0, fmt, vararg);
outBuffer.resize(len + 1);
// Print again
len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
}
ASSERT(len >= 0);
return static_cast<size_t>(len);
}
std::string FormatString(const char *fmt, va_list vararg)
{
static std::vector<char> buffer(512);
// Attempt to just print to the current buffer
int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
if (len < 0 || static_cast<size_t>(len) >= buffer.size())
{
// Buffer was not large enough, calculate the required size and resize the buffer
len = vsnprintf(NULL, 0, fmt, vararg);
buffer.resize(len + 1);
// Print again
vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
}
return std::string(buffer.data(), len);
size_t len = FormatStringIntoVector(fmt, vararg, buffer);
return std::string(&buffer[0], len);
}
std::string FormatString(const char *fmt, ...)

View File

@ -17,6 +17,7 @@
#include <set>
#include <sstream>
#include <cstdarg>
#include <vector>
// A macro to disallow the copy constructor and operator= functions
// This must be used in the private: declarations for a class
@ -95,6 +96,13 @@ inline void StructZero(T *obj)
memset(obj, 0, sizeof(T));
}
template <typename T>
inline bool IsMaskFlagSet(T mask, T flag)
{
// Handles multibit flags as well
return (mask & flag) == flag;
}
inline const char* MakeStaticString(const std::string &str)
{
static std::set<std::string> strings;
@ -132,9 +140,12 @@ inline std::string Str(int i)
return strstr.str();
}
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer);
std::string FormatString(const char *fmt, va_list vararg);
std::string FormatString(const char *fmt, ...);
// snprintf is not defined with MSVC prior to to msvc14
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif

View File

@ -17,41 +17,211 @@
namespace gl
{
#if defined(ANGLE_ENABLE_PERF)
typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR);
#else
typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*);
#endif
static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg)
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
// Wraps the D3D9/D3D11 debug annotation functions.
class DebugAnnotationWrapper
{
#if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE)
std::string formattedMessage = FormatString(format, vararg);
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
{
public:
void beginEvent(const std::wstring &eventName)
{
D3DPERF_BeginEvent(0, eventName.c_str());
}
void endEvent()
{
D3DPERF_EndEvent();
}
void setMarker(const std::wstring &markerName)
{
D3DPERF_SetMarker(0, markerName.c_str());
}
bool getStatus()
{
return !!D3DPERF_GetStatus();
}
};
#endif // ANGLE_ENABLE_D3D9
#if defined(ANGLE_ENABLE_D3D11)
class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
{
public:
D3D11DebugAnnotationWrapper()
: mInitialized(false),
mD3d11Module(NULL),
mUserDefinedAnnotation(NULL)
{
// D3D11 devices can't be created during DllMain.
// We defer device creation until the object is actually used.
}
~D3D11DebugAnnotationWrapper()
{
if (mInitialized)
{
SafeRelease(mUserDefinedAnnotation);
FreeLibrary(mD3d11Module);
}
}
virtual void beginEvent(const std::wstring &eventName)
{
initializeDevice();
mUserDefinedAnnotation->BeginEvent(eventName.c_str());
}
virtual void endEvent()
{
initializeDevice();
mUserDefinedAnnotation->EndEvent();
}
virtual void setMarker(const std::wstring &markerName)
{
initializeDevice();
mUserDefinedAnnotation->SetMarker(markerName.c_str());
}
virtual bool getStatus()
{
// ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
// In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
// This should only be called in DEBUG mode.
// If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
IDXGraphicsAnalysis* graphicsAnalysis;
DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
bool underCapture = (graphicsAnalysis != NULL);
SafeRelease(graphicsAnalysis);
return underCapture;
#endif
#if defined(ANGLE_ENABLE_PERF)
// 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,
DebugTraceOutputTypeSetMarker,
DebugTraceOutputTypeBeginEvent
};
static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static std::vector<char> buffer(512);
if (perfActive())
{
// The perf function only accepts wide strings, widen the ascii message
static std::wstring wideMessage;
if (wideMessage.capacity() < formattedMessage.length())
size_t len = FormatStringIntoVector(format, vararg, buffer);
std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
switch (outputType)
{
wideMessage.reserve(formattedMessage.size());
case DebugTraceOutputTypeNone:
break;
case DebugTraceOutputTypeBeginEvent:
g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
break;
case DebugTraceOutputTypeSetMarker:
g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
break;
}
wideMessage.assign(formattedMessage.begin(), formattedMessage.end());
perfFunc(0, wideMessage.c_str());
}
#endif // ANGLE_ENABLE_PERF
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
#if defined(ANGLE_ENABLE_TRACE)
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
#if defined(NDEBUG)
if (traceFileDebugOnly)
if (traceInDebugOnly)
{
return;
}
#endif // NDEBUG
std::string formattedMessage = FormatString(format, vararg);
static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
if (file)
@ -60,25 +230,29 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c
file.flush();
}
#endif // ANGLE_ENABLE_TRACE
#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
OutputDebugStringA(formattedMessage.c_str());
#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
#endif // ANGLE_ENABLE_DEBUG_TRACE
}
void trace(bool traceFileDebugOnly, const char *format, ...)
void trace(bool traceInDebugOnly, const char *format, ...)
{
va_list vararg;
va_start(vararg, format);
#if defined(ANGLE_ENABLE_PERF)
output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
#else
output(traceFileDebugOnly, NULL, format, vararg);
output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
#endif
va_end(vararg);
}
bool perfActive()
{
#if defined(ANGLE_ENABLE_PERF)
static bool active = D3DPERF_GetStatus() != 0;
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static bool active = g_DebugAnnotationWrapper->getStatus();
return active;
#else
return false;
@ -87,26 +261,28 @@ bool perfActive()
ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
{
#if defined(ANGLE_ENABLE_PERF)
#if !defined(ANGLE_ENABLE_TRACE)
#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
if (!perfActive())
{
return;
}
#endif // !ANGLE_ENABLE_TRACE
#endif // !ANGLE_ENABLE_DEBUG_TRACE
va_list vararg;
va_start(vararg, format);
output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
#else
output(true, DebugTraceOutputTypeNone, format, vararg);
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
va_end(vararg);
#endif // ANGLE_ENABLE_PERF
}
ScopedPerfEventHelper::~ScopedPerfEventHelper()
{
#if defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
if (perfActive())
{
D3DPERF_EndEvent();
g_DebugAnnotationWrapper->endEvent();
}
#endif
}

View File

@ -20,8 +20,8 @@
namespace gl
{
// Outputs text to the debugging log
void trace(bool traceFileDebugOnly, const char *format, ...);
// Outputs text to the debugging log, or the debugging window
void trace(bool traceInDebugOnly, const char *format, ...);
// Returns whether D3DPERF is active.
bool perfActive();
@ -36,31 +36,34 @@ namespace gl
private:
DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
};
void InitializeDebugAnnotations();
void UninitializeDebugAnnotations();
}
// A macro to output a trace of a function call and its arguments to the debugging log
#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define TRACE(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define FIXME(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, in case of error.
#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define ERR(message, ...) (void(0))
#endif
// A macro to log a performance event around a scope.
#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#if defined(_MSC_VER)
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
#else
@ -83,7 +86,7 @@ namespace gl
#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
#endif
#ifndef ANGLE_ENABLE_TRACE
#ifndef ANGLE_ENABLE_DEBUG_TRACE
#define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
#else
#define UNUSED_TRACE_VARIABLE(variable)
@ -128,7 +131,7 @@ namespace gl
#endif
// A macro functioning as a compile-time assert to validate constant conditions
#if defined(_MSC_VER) && _MSC_VER >= 1600
#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3))
#define META_ASSERT_MSG(condition, msg) static_assert(condition, msg)
#else
#define META_ASSERT_CONCAT(a, b) a ## b

View File

@ -0,0 +1,35 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#define ANGLE_DISABLED 0
#define ANGLE_ENABLED 1
// Feature defaults
// Direct3D9EX
// The "Debug This Pixel..." feature in PIX often fails when using the
// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
// machine, define "ANGLE_D3D9EX=0" in your project file.
#if !defined(ANGLE_D3D9EX)
#define ANGLE_D3D9EX ANGLE_ENABLED
#endif
// Vsync
// ENABLED allows Vsync to be configured at runtime
// DISABLED disallows Vsync
#if !defined(ANGLE_VSYNC)
#define ANGLE_VSYNC ANGLE_ENABLED
#endif
// Program binary loading
#if !defined(ANGLE_PROGRAM_BINARY_LOAD)
#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED
#endif
// Shader debug info
#if !defined(ANGLE_SHADER_DEBUG_INFO)
#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED
#endif

View File

@ -109,7 +109,7 @@ inline unsigned int unorm(float x)
inline bool supportsSSE2()
{
#ifdef ANGLE_PLATFORM_WINDOWS
#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
static bool checked = false;
static bool supports = false;
@ -118,7 +118,6 @@ inline bool supportsSSE2()
return supports;
}
#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
int info[4];
__cpuid(info, 0);
@ -128,7 +127,6 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
#endif
checked = true;

View File

@ -11,9 +11,6 @@
#if defined(_WIN32) || defined(_WIN64)
# define ANGLE_PLATFORM_WINDOWS 1
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
# define ANGLE_PLATFORM_WINRT 1
# endif
#elif defined(__APPLE__)
# define ANGLE_PLATFORM_APPLE 1
# define ANGLE_PLATFORM_POSIX 1
@ -37,6 +34,9 @@
#endif
#ifdef ANGLE_PLATFORM_WINDOWS
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
# define ANGLE_ENABLE_WINDOWS_STORE 1
# endif
# ifndef STRICT
# define STRICT 1
# endif
@ -50,7 +50,7 @@
# include <windows.h>
# include <intrin.h>
# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF)
# if defined(ANGLE_ENABLE_D3D9)
# include <d3d9.h>
# if !defined(COMPILER_IMPLEMENTATION)
# include <d3dcompiler.h>
@ -62,13 +62,26 @@
# include <d3d10.h>
# include <d3d11.h>
# include <dxgi.h>
# if _MSC_VER >= 1700
# if defined(_MSC_VER) && (_MSC_VER >= 1700)
# include <d3d11_1.h>
# include <dxgi1_2.h>
# endif
# if !defined(COMPILER_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# if defined(__MINGW32__)
# endif
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <dxgi1_3.h>
# if defined(_DEBUG)
# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
# include <DXProgrammableCapture.h>
# endif
# include <dxgidebug.h>
# endif
# endif
# if defined(__MINGW32__) // Missing defines on MinGW
typedef enum D3D11_MAP_FLAG
{
D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
@ -78,8 +91,68 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS
UINT64 NumPrimitivesWritten;
UINT64 PrimitivesStorageNeeded;
} D3D11_QUERY_DATA_SO_STATISTICS;
# endif
# endif
typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
#define D3D11_MESSAGE_CATEGORY UINT
#define D3D11_MESSAGE_SEVERITY UINT
#define D3D11_MESSAGE_ID UINT
struct D3D11_MESSAGE;
typedef struct D3D11_INFO_QUEUE_FILTER_DESC
{
UINT NumCategories;
D3D11_MESSAGE_CATEGORY *pCategoryList;
UINT NumSeverities;
D3D11_MESSAGE_SEVERITY *pSeverityList;
UINT NumIDs;
D3D11_MESSAGE_ID *pIDList;
} D3D11_INFO_QUEUE_FILTER_DESC;
typedef struct D3D11_INFO_QUEUE_FILTER
{
D3D11_INFO_QUEUE_FILTER_DESC AllowList;
D3D11_INFO_QUEUE_FILTER_DESC DenyList;
} D3D11_INFO_QUEUE_FILTER;
static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
{
public:
virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
virtual void __stdcall ClearStoredMessages() = 0;
virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
virtual UINT64 __stdcall GetNumStoredMessages() = 0;
virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
virtual UINT64 __stdcall GetMessageCountLimit() = 0;
virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
virtual void __stdcall ClearStorageFilter() = 0;
virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual void __stdcall PopStorageFilter() = 0;
virtual UINT __stdcall GetStorageFilterStackSize() = 0;
virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
virtual void __stdcall ClearRetrievalFilter() = 0;
virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual void __stdcall PopRetrievalFilter() = 0;
virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
virtual BOOL __stdcall GetMuteDebugOutput() = 0;
};
#endif // __MINGW32__
# undef near
# undef far

View File

@ -10,29 +10,50 @@
#include <assert.h>
#if defined(ANGLE_PLATFORM_WINRT)
#ifdef ANGLE_ENABLE_WINDOWS_STORE
#include <vector>
std::vector<void *> *tls = nullptr;
std::vector<TLSIndex> *freeIndices = nullptr;
#include <set>
#include <map>
#include <mutex>
#include <wrl/client.h>
#include <wrl/async.h>
#include <Windows.System.Threading.h>
using namespace std;
using namespace Windows::Foundation;
using namespace ABI::Windows::System::Threading;
// Thread local storage for Windows Store support
typedef vector<void*> ThreadLocalData;
static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
static set<ThreadLocalData*> allThreadData;
static DWORD nextTlsIndex = 0;
static vector<DWORD> freeTlsIndices;
#endif
TLSIndex CreateTLSIndex()
{
TLSIndex index;
#if defined(ANGLE_PLATFORM_WINRT)
if (!tls)
tls = new std::vector<void *>;
if (freeIndices && !freeIndices->empty()) {
index = freeIndices->back();
freeIndices->pop_back();
return index;
} else {
tls->push_back(nullptr);
return tls->size() - 1;
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
if (!freeTlsIndices.empty())
{
DWORD result = freeTlsIndices.back();
freeTlsIndices.pop_back();
index = result;
}
#elif defined(ANGLE_PLATFORM_WINDOWS)
else
{
index = nextTlsIndex++;
}
#else
index = TlsAlloc();
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
// Create global pool key
if ((pthread_key_create(&index, NULL)) != 0)
@ -53,13 +74,23 @@ bool DestroyTLSIndex(TLSIndex index)
return false;
}
#if defined(ANGLE_PLATFORM_WINRT)
if (!freeIndices)
freeIndices = new std::vector<TLSIndex>;
freeIndices->push_back(index);
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
assert(index < nextTlsIndex);
assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
freeTlsIndices.push_back(index);
for (auto threadData : allThreadData)
{
if (threadData->size() > index)
{
threadData->at(index) = nullptr;
}
}
return true;
#elif ANGLE_PLATFORM_WINDOWS
#else
return (TlsFree(index) == TRUE);
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
return (pthread_key_delete(index) == 0);
#endif
@ -73,11 +104,25 @@ bool SetTLSValue(TLSIndex index, void *value)
return false;
}
#if defined(ANGLE_PLATFORM_WINRT)
tls->at(index) = value;
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
ThreadLocalData* threadData = currentThreadData;
if (!threadData)
{
threadData = new ThreadLocalData(index + 1, nullptr);
allThreadData.insert(threadData);
currentThreadData = threadData;
}
else if (threadData->size() <= index)
{
threadData->resize(index + 1, nullptr);
}
threadData->at(index) = value;
return true;
#elif defined(ANGLE_PLATFORM_WINDOWS)
#else
return (TlsSetValue(index, value) == TRUE);
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
return (pthread_setspecific(index, value) == 0);
#endif
@ -85,18 +130,26 @@ bool SetTLSValue(TLSIndex index, void *value)
void *GetTLSValue(TLSIndex index)
{
#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation
assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
#endif
if (index == TLS_INVALID_INDEX)
{
return NULL;
}
#if defined(ANGLE_PLATFORM_WINRT)
return tls->at(index);
#elif defined(ANGLE_PLATFORM_WINDOWS)
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
ThreadLocalData* threadData = currentThreadData;
if (threadData && threadData->size() > index)
{
return threadData->at(index);
}
else
{
return nullptr;
}
#else
return TlsGetValue(index);
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
return pthread_getspecific(index);
#endif

View File

@ -11,11 +11,15 @@
#include "common/platform.h"
#if defined(ANGLE_PLATFORM_WINRT)
typedef size_t TLSIndex;
# define TLS_OUT_OF_INDEXES (static_cast<TLSIndex>(-1))
# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES
#elif defined(ANGLE_PLATFORM_WINDOWS)
#ifdef ANGLE_PLATFORM_WINDOWS
// TLS does not exist for Windows Store and needs to be emulated
# ifdef ANGLE_ENABLE_WINDOWS_STORE
# define TLS_OUT_OF_INDEXES -1
# ifndef CREATE_SUSPENDED
# define CREATE_SUSPENDED 0x00000004
# endif
# endif
typedef DWORD TLSIndex;
# define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES)
#elif defined(ANGLE_PLATFORM_POSIX)
@ -28,6 +32,9 @@
# error Unsupported platform.
#endif
// TODO(kbr): for POSIX platforms this will have to be changed to take
// in a destructor function pointer, to allow the thread-local storage
// to be properly deallocated upon thread exit.
TLSIndex CreateTLSIndex();
bool DestroyTLSIndex(TLSIndex index);

View File

@ -9,17 +9,16 @@
#include "common/utilities.h"
#include "common/mathutil.h"
#include "common/platform.h"
#if defined(ANGLE_PLATFORM_WINRT)
# include <locale>
# include <codecvt>
# include <wrl.h>
# include <windows.storage.h>
using namespace Microsoft::WRL;
using namespace ABI::Windows::Storage;
#endif
#include <set>
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <wrl.h>
# include <wrl/wrappers/corewrappers.h>
# include <windows.applicationmodel.core.h>
# include <windows.graphics.display.h>
#endif
namespace gl
{
@ -447,50 +446,10 @@ int VariableSortOrder(GLenum type)
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
std::string getTempPath()
{
#if defined(ANGLE_PLATFORM_WINRT)
static std::string path;
while (path.empty())
{
ComPtr<IApplicationDataStatics> factory;
Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData);
HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory));
if (FAILED(result))
break;
ComPtr<IApplicationData> applicationData;
result = factory->get_Current(&applicationData);
if (FAILED(result))
break;
ComPtr<IStorageFolder> storageFolder;
result = applicationData->get_LocalFolder(&storageFolder);
if (FAILED(result))
break;
ComPtr<IStorageItem> localFolder;
result = storageFolder.As(&localFolder);
if (FAILED(result))
break;
HSTRING localFolderPath;
result = localFolder->get_Path(&localFolderPath);
if (FAILED(result))
break;
std::wstring_convert< std::codecvt_utf8<wchar_t> > converter;
path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL));
if (path.empty())
{
UNREACHABLE();
break;
}
}
return path;
#elif defined(ANGLE_PLATFORM_WINDOWS)
#ifdef ANGLE_PLATFORM_WINDOWS
char path[MAX_PATH];
DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
if (pathLen == 0)
@ -525,3 +484,33 @@ void writeFile(const char* path, const void* content, size_t size)
fwrite(content, sizeof(char), size, file);
fclose(file);
}
#endif // !ANGLE_ENABLE_WINDOWS_STORE
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
void Sleep(unsigned long dwMilliseconds)
{
static HANDLE singletonEvent = nullptr;
HANDLE sleepEvent = singletonEvent;
if (!sleepEvent)
{
sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (!sleepEvent)
return;
HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr);
if (previousEvent)
{
// Back out if multiple threads try to demand create at the same time.
CloseHandle(sleepEvent);
sleepEvent = previousEvent;
}
}
// Emulate sleep by waiting with timeout on an event that is never signalled.
WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false);
}
#endif // ANGLE_ENABLE_WINDOWS_STORE

View File

@ -46,7 +46,13 @@ template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
std::string getTempPath();
void writeFile(const char* path, const void* data, size_t size);
#endif
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
void Sleep(_In_ unsigned long dwMilliseconds);
#endif
#endif // LIBGLESV2_UTILITIES_H

View File

@ -0,0 +1,66 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// NativeWindow.cpp: Handler for managing HWND native window types.
#include "common/NativeWindow.h"
#include "common/debug.h"
namespace rx
{
bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
{
return (IsWindow(window) == TRUE);
}
NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display)
{
}
bool NativeWindow::initialize()
{
return true;
}
bool NativeWindow::getClientRect(LPRECT rect)
{
return GetClientRect(mWindow, rect) == TRUE;
}
bool NativeWindow::isIconic()
{
return IsIconic(mWindow) == TRUE;
}
HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
DXGI_FORMAT format, unsigned int width, unsigned int height,
DXGISwapChain** swapChain)
{
if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Format = format;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.Flags = 0;
swapChainDesc.OutputWindow = mWindow;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
}
}

View File

@ -0,0 +1,200 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
#include <algorithm>
#include "common/winrt/CoreWindowNativeWindow.h"
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler;
CoreWindowNativeWindow::~CoreWindowNativeWindow()
{
unregisterForSizeChangeEvents();
}
bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
{
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
ComPtr<IInspectable> displayInformation = display;
SIZE swapChainSize = {};
bool swapChainSizeSpecified = false;
HRESULT result = S_OK;
// IPropertySet is an optional parameter and can be null.
// If one is specified, cache as an IMap and read the properties
// used for initial host initialization.
if (propertySet)
{
result = props.As(&mPropertyMap);
if (SUCCEEDED(result))
{
// The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
// was prevalidated to contain the EGLNativeWindowType before being passed to
// this host.
result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified);
}
}
if (SUCCEEDED(result))
{
result = win.As(&mCoreWindow);
}
if (SUCCEEDED(result))
{
result = displayInformation.As(&mDisplayInformation);
}
if (SUCCEEDED(result))
{
#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2;
result = mDisplayInformation.As(&displayInformation2);
ASSERT(SUCCEEDED(result));
result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
ASSERT(SUCCEEDED(result));
#else
ABI::Windows::Graphics::Display::ResolutionScale resolutionScale;
result = mDisplayInformation->get_ResolutionScale(&resolutionScale);
ASSERT(SUCCEEDED(result));
mScaleFactor = DOUBLE(resolutionScale) / 100.0;
#endif
}
if (SUCCEEDED(result))
{
// If a swapchain size is specfied, then the automatic resize
// behaviors implemented by the host should be disabled. The swapchain
// will be still be scaled when being rendered to fit the bounds
// of the host.
// Scaling of the swapchain output occurs automatically because if
// the scaling mode setting DXGI_SCALING_STRETCH on the swapchain.
if (swapChainSizeSpecified)
{
mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
mSupportsSwapChainResize = false;
}
else
{
ABI::Windows::Foundation::Rect rect;
HRESULT result = mCoreWindow->get_Bounds(&rect);
if (SUCCEEDED(result))
{
LONG width = std::floor(rect.Width * mScaleFactor + 0.5);
LONG height = std::floor(rect.Height * mScaleFactor + 0.5);
mClientRect = { 0, 0, width, height };
}
}
}
if (SUCCEEDED(result))
{
mNewClientRect = mClientRect;
mClientRectChanged = false;
return registerForSizeChangeEvents();
}
return false;
}
bool CoreWindowNativeWindow::registerForSizeChangeEvents()
{
HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(),
&mSizeChangedEventToken);
if (SUCCEEDED(result))
{
return true;
}
return false;
}
void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
{
if (mCoreWindow)
{
(void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
}
mSizeChangedEventToken.value = 0;
}
HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
swapChainDesc.Width = width;
swapChainDesc.Height = height;
swapChainDesc.Format = format;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 2;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
*swapChain = nullptr;
ComPtr<IDXGISwapChain1> newSwapChain;
HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
if (SUCCEEDED(result))
{
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected
// Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
// other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
// (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED)
{
mSupportsSwapChainResize = false;
}
#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
result = newSwapChain.CopyTo(swapChain);
}
if (SUCCEEDED(result))
{
// If automatic swapchain resize behaviors have been disabled, then
// unregister for the resize change events.
if (mSupportsSwapChainResize == false)
{
unregisterForSizeChangeEvents();
}
}
return result;
}
// Basically, this shouldn't be used on Phone
HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e)
{
ABI::Windows::Foundation::Size size;
if (SUCCEEDED(e->get_Size(&size)))
{
SIZE windowSizeInPixels = {
std::floor(size.Width * mScaleFactor + 0.5),
std::floor(size.Height * mScaleFactor + 0.5)
};
setNewClientSize(windowSizeInPixels);
}
return S_OK;
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
#include "common/winrt/InspectableNativeWindow.h"
#include <memory>
#include <windows.graphics.display.h>
namespace rx
{
class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
{
public:
~CoreWindowNativeWindow();
bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
private:
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
};
}
#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_

View File

@ -0,0 +1,274 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types.
#include "common/winrt/CoreWindowNativeWindow.h"
#include "common/winrt/SwapChainPanelNativeWindow.h"
namespace rx
{
NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display)
: mWindow(window), mDisplay(display)
{
}
bool NativeWindow::initialize()
{
// If the native window type is a IPropertySet, extract the
// EGLNativeWindowType (IInspectable) and initialize the
// proper host with this IPropertySet.
ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
ComPtr<IInspectable> eglNativeWindow;
if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow))
{
// A property set was found and the EGLNativeWindowType was
// retrieved. The mWindow member of the host to must be updated
// to use the EGLNativeWindowType specified in the property set.
// mWindow is treated as a raw pointer not an AddRef'd interface, so
// the old mWindow does not need a Release() before this assignment.
mWindow = eglNativeWindow.Get();
}
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
if (IsCoreWindow(mWindow, &coreWindow))
{
mImpl = std::make_shared<CoreWindowNativeWindow>();
if (mImpl)
{
return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
}
}
else if (IsSwapChainPanel(mWindow, &swapChainPanel))
{
mImpl = std::make_shared<SwapChainPanelNativeWindow>();
if (mImpl)
{
return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
}
}
else
{
ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet");
}
return false;
}
bool NativeWindow::getClientRect(RECT *rect)
{
if (mImpl)
{
return mImpl->getClientRect(rect);
}
return false;
}
bool NativeWindow::isIconic()
{
return false;
}
HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (mImpl)
{
return mImpl->createSwapChain(device, factory, format, width, height, swapChain);
}
return E_UNEXPECTED;
}
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> win = window;
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
if (SUCCEEDED(win.As(&coreWin)))
{
if (coreWindow != nullptr)
{
*coreWindow = coreWin.Detach();
}
return true;
}
return false;
}
bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> win = window;
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
if (SUCCEEDED(win.As(&panel)))
{
if (swapChainPanel != nullptr)
{
*swapChainPanel = panel.Detach();
}
return true;
}
return false;
}
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> props = window;
ComPtr<IPropertySet> propSet;
ComPtr<IInspectable> nativeWindow;
ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap;
boolean hasEglNativeWindowPropertyKey = false;
HRESULT result = props.As(&propSet);
if (SUCCEEDED(result))
{
result = propSet.As(&propMap);
}
// Look for the presence of the EGLNativeWindowType in the property set
if (SUCCEEDED(result))
{
result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey);
}
// If the IPropertySet does not contain the required EglNativeWindowType key, the property set is
// considered invalid.
if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
{
ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow");
return false;
}
// The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType
if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
{
result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
}
if (SUCCEEDED(result))
{
if (propertySet != nullptr)
{
result = propSet.CopyTo(propertySet);
}
}
if (SUCCEEDED(result))
{
if (eglNativeWindow != nullptr)
{
result = nativeWindow.CopyTo(eglNativeWindow);
}
}
if (SUCCEEDED(result))
{
return true;
}
return false;
}
// A Valid EGLNativeWindowType IInspectable can only be:
//
// ICoreWindow
// IPropertySet
//
// Anything else will be rejected as an invalid IInspectable.
bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
{
return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
}
// Attempts to read an optional SIZE property value that is assumed to be in the form of
// an ABI::Windows::Foundation::Size. This function validates the Size value before returning
// it to the caller.
//
// Possible return values are:
// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
// S_OK, valueExists == false - optional SIZE value was not found
// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
// * Incorrect property type ( must be PropertyType_Size)
// * Invalid property value (width/height must be > 0)
// Additional errors may be returned from IMap or IPropertyValue
//
HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists)
{
if (!propertyMap || !propertyName || !value || !valueExists)
{
return false;
}
// Assume that the value does not exist
*valueExists = false;
*value = { 0, 0 };
ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
Size sizeValue = { 0, 0 };
boolean hasKey = false;
HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey);
if (SUCCEEDED(result) && !hasKey)
{
// Value does not exist, so return S_OK and set the exists parameter to false to indicate
// that a the optional property does not exist.
*valueExists = false;
return S_OK;
}
if (SUCCEEDED(result))
{
result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
}
if (SUCCEEDED(result))
{
result = propertyValue->get_Type(&propertyType);
}
// Check if the expected Size property is of PropertyType_Size type.
if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
{
if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0))
{
// A valid property value exists
*value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) };
*valueExists = true;
result = S_OK;
}
else
{
// An invalid Size property was detected. Width/Height values must > 0
result = E_INVALIDARG;
}
}
else
{
// An invalid property type was detected. Size property must be of PropertyType_Size
result = E_INVALIDARG;
}
return result;
}
}

View File

@ -0,0 +1,91 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// InspectableNativeWindow.h: Host specific implementation interface for
// managing IInspectable native window types.
#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
#include "common/platform.h"
#include "common/NativeWindow.h"
#include "angle_windowsstore.h"
#include <windows.ui.xaml.h>
#include <windows.ui.xaml.media.dxinterop.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
class InspectableNativeWindow
{
public:
InspectableNativeWindow() :
mSupportsSwapChainResize(true),
mRequiresSwapChainScaling(false),
mClientRectChanged(false),
mClientRect({0,0,0,0}),
mNewClientRect({0,0,0,0}),
mScaleFactor(1.0)
{
mSizeChangedEventToken.value = 0;
}
virtual ~InspectableNativeWindow(){}
virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0;
virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
virtual bool registerForSizeChangeEvents() = 0;
virtual void unregisterForSizeChangeEvents() = 0;
virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; }
bool getClientRect(RECT *rect)
{
if (mClientRectChanged && mSupportsSwapChainResize)
{
mClientRect = mNewClientRect;
mClientRectChanged = false;
}
*rect = mClientRect;
return true;
}
void setNewClientSize(const SIZE &newSize)
{
if (mSupportsSwapChainResize && !mRequiresSwapChainScaling)
{
mNewClientRect = { 0, 0, newSize.cx, newSize.cy };
mClientRectChanged = true;
}
if (mRequiresSwapChainScaling)
{
scaleSwapChain(newSize);
}
}
protected:
bool mSupportsSwapChainResize;
bool mRequiresSwapChainScaling;
RECT mClientRect;
RECT mNewClientRect;
bool mClientRectChanged;
DOUBLE mScaleFactor;
EventRegistrationToken mSizeChangedEventToken;
};
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists);
}
#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_

View File

@ -0,0 +1,226 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types.
#include "common/winrt/SwapChainPanelNativeWindow.h"
#include <algorithm>
#include <math.h>
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
{
unregisterForSizeChangeEvents();
}
bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
{
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
SIZE swapChainSize = {};
bool swapChainSizeSpecified = false;
HRESULT result = S_OK;
// IPropertySet is an optional parameter and can be null.
// If one is specified, cache as an IMap and read the properties
// used for initial host initialization.
if (propertySet)
{
result = props.As(&mPropertyMap);
if (SUCCEEDED(result))
{
// The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
// was prevalidated to contain the EGLNativeWindowType before being passed to
// this host.
result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified);
}
}
if (SUCCEEDED(result))
{
result = win.As(&mSwapChainPanel);
}
if (SUCCEEDED(result))
{
// If a swapchain size is specfied, then the automatic resize
// behaviors implemented by the host should be disabled. The swapchain
// will be still be scaled when being rendered to fit the bounds
// of the host.
// Scaling of the swapchain output needs to be handled by the
// host for swapchain panels even though the scaling mode setting
// DXGI_SCALING_STRETCH is configured on the swapchain.
if (swapChainSizeSpecified)
{
mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
// Enable host swapchain scaling
mRequiresSwapChainScaling = true;
}
else
{
result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect);
}
}
if (SUCCEEDED(result))
{
mNewClientRect = mClientRect;
mClientRectChanged = false;
return registerForSizeChangeEvents();
}
return false;
}
bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
{
ComPtr<ABI::Windows::UI::Xaml::ISizeChangedEventHandler> sizeChangedHandler;
ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement;
HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
if (SUCCEEDED(result))
{
result = mSwapChainPanel.As(&frameworkElement);
}
if (SUCCEEDED(result))
{
result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
}
if (SUCCEEDED(result))
{
return true;
}
return false;
}
void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
{
ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement;
if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement)))
{
(void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken);
}
mSizeChangedEventToken.value = 0;
}
HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
swapChainDesc.Width = width;
swapChainDesc.Height = height;
swapChainDesc.Format = format;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 2;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
*swapChain = nullptr;
ComPtr<IDXGISwapChain1> newSwapChain;
ComPtr<ISwapChainPanelNative> swapChainPanelNative;
RECT currentPanelSize = {};
HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
if (SUCCEEDED(result))
{
result = mSwapChainPanel.As(&swapChainPanelNative);
}
if (SUCCEEDED(result))
{
result = swapChainPanelNative->SetSwapChain(newSwapChain.Get());
}
if (SUCCEEDED(result))
{
// The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel
// to perform the runtime-scale behavior. This swapchain is cached here because there are
// no methods for retreiving the currently configured on from ISwapChainPanelNative.
mSwapChain = newSwapChain;
result = newSwapChain.CopyTo(swapChain);
}
// If the host is responsible for scaling the output of the swapchain, then
// scale it now before returning an instance to the caller. This is done by
// first reading the current size of the swapchain panel, then scaling
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
result = GetSwapChainPanelSize(mSwapChainPanel, &currentPanelSize);
}
// Scale the swapchain to fit inside the contents of the panel.
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom };
result = scaleSwapChain(currentSize);
}
if (SUCCEEDED(result))
{
// If automatic swapchain resize behaviors have been disabled, then
// unregister for the resize change events.
if (mSupportsSwapChainResize == false)
{
unregisterForSizeChangeEvents();
}
}
return result;
}
HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
{
ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom };
// Setup a scale matrix for the swap chain
DXGI_MATRIX_3X2_F scaleMatrix = {};
scaleMatrix._11 = renderScale.Width;
scaleMatrix._22 = renderScale.Height;
ComPtr<IDXGISwapChain2> swapChain2;
HRESULT result = mSwapChain.As(&swapChain2);
if (SUCCEEDED(result))
{
result = swapChain2->SetMatrixTransform(&scaleMatrix);
}
return result;
}
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize)
{
ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
ABI::Windows::Foundation::Size renderSize = { 0, 0 };
HRESULT result = swapChainPanel.As(&uiElement);
if (SUCCEEDED(result))
{
result = uiElement->get_RenderSize(&renderSize);
}
if (SUCCEEDED(result))
{
*windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) };
}
return result;
}
}

View File

@ -0,0 +1,79 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types.
#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
#include "common/winrt/InspectableNativeWindow.h"
namespace rx
{
class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow>
{
public:
~SwapChainPanelNativeWindow();
bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
HRESULT scaleSwapChain(const SIZE &newSize);
private:
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
ComPtr<DXGISwapChain> mSwapChain;
};
[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)]
class SwapChainPanelSizeChangedHandler :
public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler>
{
public:
SwapChainPanelSizeChangedHandler() { }
HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
{
if (!host)
{
return E_INVALIDARG;
}
mHost = host;
return S_OK;
}
// ISizeChangedEventHandler
IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs)
{
std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
if (host)
{
// The size of the ISwapChainPanel control is returned in DIPs.
// We are keeping these in dips because the swapchain created for composition
// also uses dip units. This keeps dimensions, viewports, etc in the same unit.
// XAML Clients of the ISwapChainPanel are required to use dips to define their
// layout sizes as well.
ABI::Windows::Foundation::Size newSize;
HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
if (SUCCEEDED(result))
{
SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) };
host->setNewClientSize(windowSize);
}
}
return S_OK;
}
private:
std::weak_ptr<InspectableNativeWindow> mHost;
};
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize);
}
#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_

View File

@ -29,7 +29,8 @@ class DirectiveHandler
// Handle pragma of form: #pragma name[(value)]
virtual void handlePragma(const SourceLocation &loc,
const std::string &name,
const std::string &value) = 0;
const std::string &value,
bool stdgl) = 0;
virtual void handleExtension(const SourceLocation &loc,
const std::string &name,

View File

@ -38,19 +38,19 @@ enum DirectiveType
DirectiveType getDirective(const pp::Token *token)
{
static const std::string kDirectiveDefine("define");
static const std::string kDirectiveUndef("undef");
static const std::string kDirectiveIf("if");
static const std::string kDirectiveIfdef("ifdef");
static const std::string kDirectiveIfndef("ifndef");
static const std::string kDirectiveElse("else");
static const std::string kDirectiveElif("elif");
static const std::string kDirectiveEndif("endif");
static const std::string kDirectiveError("error");
static const std::string kDirectivePragma("pragma");
static const std::string kDirectiveExtension("extension");
static const std::string kDirectiveVersion("version");
static const std::string kDirectiveLine("line");
const char kDirectiveDefine[] = "define";
const char kDirectiveUndef[] = "undef";
const char kDirectiveIf[] = "if";
const char kDirectiveIfdef[] = "ifdef";
const char kDirectiveIfndef[] = "ifndef";
const char kDirectiveElse[] = "else";
const char kDirectiveElif[] = "elif";
const char kDirectiveEndif[] = "endif";
const char kDirectiveError[] = "error";
const char kDirectivePragma[] = "pragma";
const char kDirectiveExtension[] = "extension";
const char kDirectiveVersion[] = "version";
const char kDirectiveLine[] = "line";
if (token->type != pp::Token::IDENTIFIER)
return DIRECTIVE_NONE;
@ -155,7 +155,7 @@ class DefinedParser : public Lexer
protected:
virtual void lex(Token *token)
{
static const std::string kDefined("defined");
const char kDefined[] = "defined";
mLexer->lex(token);
if (token->type != Token::IDENTIFIER)
@ -592,6 +592,11 @@ void DirectiveParser::parsePragma(Token *token)
int state = PRAGMA_NAME;
mTokenizer->lex(token);
bool stdgl = token->text == "STDGL";
if (stdgl)
{
mTokenizer->lex(token);
}
while ((token->type != '\n') && (token->type != Token::LAST))
{
switch(state++)
@ -627,7 +632,7 @@ void DirectiveParser::parsePragma(Token *token)
}
else if (state > PRAGMA_NAME) // Do not notify for empty pragma.
{
mDirectiveHandler->handlePragma(token->location, name, value);
mDirectiveHandler->handlePragma(token->location, name, value, stdgl);
}
}

View File

@ -194,8 +194,8 @@ bool MacroExpander::expandMacro(const Macro &macro,
if (macro.predefined)
{
static const std::string kLine = "__LINE__";
static const std::string kFile = "__FILE__";
const char kLine[] = "__LINE__";
const char kFile[] = "__FILE__";
assert(replacements->size() == 1);
Token& repl = replacements->front();

View File

@ -29,24 +29,27 @@
bool IsWebGLBasedSpec(ShShaderSpec spec)
{
return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
return (spec == SH_WEBGL_SPEC ||
spec == SH_CSS_SHADERS_SPEC ||
spec == SH_WEBGL2_SPEC);
}
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
{
// WebGL defines a max token legnth of 256, while ES2 leaves max token
// size undefined. ES3 defines a max size of 1024 characters.
if (IsWebGLBasedSpec(spec))
switch (spec)
{
case SH_WEBGL_SPEC:
case SH_CSS_SHADERS_SPEC:
return 256;
}
else
{
default:
return 1024;
}
}
namespace {
class TScopedPoolAllocator
{
public:
@ -82,6 +85,24 @@ class TScopedSymbolTableLevel
private:
TSymbolTable* mTable;
};
int MapSpecToShaderVersion(ShShaderSpec spec)
{
switch (spec)
{
case SH_GLES2_SPEC:
case SH_WEBGL_SPEC:
case SH_CSS_SHADERS_SPEC:
return 100;
case SH_GLES3_SPEC:
case SH_WEBGL2_SPEC:
return 300;
default:
UNREACHABLE();
return 0;
}
}
} // namespace
TShHandleBase::TShHandleBase()
@ -178,9 +199,21 @@ bool TCompiler::compile(const char* const shaderStrings[],
(parseContext.treeRoot != NULL);
shaderVersion = parseContext.getShaderVersion();
if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
{
infoSink.info.prefix(EPrefixError);
infoSink.info << "unsupported shader version";
success = false;
}
if (success)
{
mPragma = parseContext.pragma();
if (mPragma.stdgl.invariantAll)
{
symbolTable.setGlobalInvariant();
}
TIntermNode* root = parseContext.treeRoot;
success = intermediate.postProcess(root);
@ -360,7 +393,8 @@ void TCompiler::setResourceString()
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset;
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
builtInResourcesString = strstream.str();
}
@ -377,7 +411,6 @@ void TCompiler::clearResults()
uniforms.clear();
expandedUniforms.clear();
varyings.clear();
expandedVaryings.clear();
interfaceBlocks.clear();
builtInFunctionEmulator.Cleanup();
@ -507,13 +540,12 @@ void TCompiler::collectVariables(TIntermNode* root)
&uniforms,
&varyings,
&interfaceBlocks,
hashFunction);
hashFunction,
symbolTable);
root->traverse(&collect);
// For backwards compatiblity with ShGetVariableInfo, expand struct
// uniforms and varyings into separate variables for each field.
sh::ExpandVariables(uniforms, &expandedUniforms);
sh::ExpandVariables(varyings, &expandedVaryings);
// This is for enforcePackingRestriction().
sh::ExpandUniforms(uniforms, &expandedUniforms);
}
bool TCompiler::enforcePackingRestrictions()
@ -581,3 +613,10 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
{
return builtInFunctionEmulator;
}
void TCompiler::writePragma()
{
TInfoSinkBase &sink = infoSink.obj;
if (mPragma.stdgl.invariantAll)
sink << "#pragma STDGL invariant(all)\n";
}

View File

@ -18,6 +18,7 @@
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/Pragma.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VariableInfo.h"
#include "third_party/compiler/ArrayBoundsClamper.h"
@ -71,9 +72,7 @@ class TCompiler : public TShHandleBase
const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; }
const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
const std::vector<sh::ShaderVariable> &getExpandedUniforms() const { return expandedUniforms; }
const std::vector<sh::Varying> &getVaryings() const { return varyings; }
const std::vector<sh::ShaderVariable> &getExpandedVaryings() const { return expandedVaryings; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
ShHashFunction64 getHashFunction() const { return hashFunction; }
@ -81,7 +80,7 @@ class TCompiler : public TShHandleBase
TSymbolTable& getSymbolTable() { return symbolTable; }
ShShaderSpec getShaderSpec() const { return shaderSpec; }
ShShaderOutput getOutputType() const { return outputType; }
std::string getBuiltInResourcesString() const { return builtInResourcesString; }
const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
// Get the resources set by InitBuiltInSymbolTable
const ShBuiltInResources& getResources() const;
@ -131,6 +130,8 @@ class TCompiler : public TShHandleBase
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
const TPragma& getPragma() const { return mPragma; }
void writePragma();
const ArrayBoundsClamper& getArrayBoundsClamper() const;
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
@ -141,7 +142,6 @@ class TCompiler : public TShHandleBase
std::vector<sh::Uniform> uniforms;
std::vector<sh::ShaderVariable> expandedUniforms;
std::vector<sh::Varying> varyings;
std::vector<sh::ShaderVariable> expandedVaryings;
std::vector<sh::InterfaceBlock> interfaceBlocks;
private:
@ -174,6 +174,8 @@ class TCompiler : public TShHandleBase
// name hashing.
ShHashFunction64 hashFunction;
NameMap nameMap;
TPragma mPragma;
};
//

View File

@ -14,6 +14,9 @@
namespace sh
{
// Detect Loop Discontinuity
bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
{
mLoopDepth = 0;
@ -74,6 +77,55 @@ bool containsLoopDiscontinuity(TIntermNode *node)
return detectLoopDiscontinuity.traverse(node);
}
// Detect Any Loop
bool DetectAnyLoop::traverse(TIntermNode *node)
{
mHasLoop = false;
node->traverse(this);
return mHasLoop;
}
bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop)
{
mHasLoop = true;
return false;
}
// The following definitions stop all traversal when we have found a loop
bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *)
{
return !mHasLoop;
}
bool containsAnyLoop(TIntermNode *node)
{
DetectAnyLoop detectAnyLoop;
return detectAnyLoop.traverse(node);
}
// Detect Gradient Operation
bool DetectGradientOperation::traverse(TIntermNode *node)
{
mGradientOperation = false;

View File

@ -32,6 +32,25 @@ class DetectLoopDiscontinuity : public TIntermTraverser
bool containsLoopDiscontinuity(TIntermNode *node);
// Checks for the existence of any loop
class DetectAnyLoop : public TIntermTraverser
{
public:
bool traverse(TIntermNode *node);
protected:
bool visitBinary(Visit, TIntermBinary *);
bool visitUnary(Visit, TIntermUnary *);
bool visitSelection(Visit, TIntermSelection *);
bool visitAggregate(Visit, TIntermAggregate *);
bool visitLoop(Visit, TIntermLoop *);
bool visitBranch(Visit, TIntermBranch *);
bool mHasLoop;
};
bool containsAnyLoop(TIntermNode *node);
// Checks for intrinsic functions which compute gradients
class DetectGradientOperation : public TIntermTraverser
{

View File

@ -13,10 +13,10 @@
static TBehavior getBehavior(const std::string& str)
{
static const std::string kRequire("require");
static const std::string kEnable("enable");
static const std::string kDisable("disable");
static const std::string kWarn("warn");
const char kRequire[] = "require";
const char kEnable[] = "enable";
const char kDisable[] = "disable";
const char kWarn[] = "warn";
if (str == kRequire) return EBhRequire;
else if (str == kEnable) return EBhEnable;
@ -46,50 +46,61 @@ void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
const std::string& name,
const std::string& value)
const std::string& value,
bool stdgl)
{
static const std::string kSTDGL("STDGL");
static const std::string kOptimize("optimize");
static const std::string kDebug("debug");
static const std::string kOn("on");
static const std::string kOff("off");
if (stdgl)
{
const char kInvariant[] = "invariant";
const char kAll[] = "all";
bool invalidValue = false;
if (name == kSTDGL)
{
if (name == kInvariant && value == kAll)
mPragma.stdgl.invariantAll = true;
// The STDGL pragma is used to reserve pragmas for use by future
// revisions of GLSL. Ignore it.
// revisions of GLSL. Do not generate an error on unexpected
// name and value.
return;
}
else if (name == kOptimize)
{
if (value == kOn) mPragma.optimize = true;
else if (value == kOff) mPragma.optimize = false;
else invalidValue = true;
}
else if (name == kDebug)
{
if (value == kOn) mPragma.debug = true;
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
return;
}
const char kOptimize[] = "optimize";
const char kDebug[] = "debug";
const char kOn[] = "on";
const char kOff[] = "off";
if (invalidValue)
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
"invalid pragma value", value,
"'on' or 'off' expected");
bool invalidValue = false;
if (name == kOptimize)
{
if (value == kOn) mPragma.optimize = true;
else if (value == kOff) mPragma.optimize = false;
else invalidValue = true;
}
else if (name == kDebug)
{
if (value == kOn) mPragma.debug = true;
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
return;
}
if (invalidValue)
{
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
"invalid pragma value", value,
"'on' or 'off' expected");
}
}
}
void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
const std::string& name,
const std::string& behavior)
{
static const std::string kExtAll("all");
const char kExtAll[] = "all";
TBehavior behaviorVal = getBehavior(behavior);
if (behaviorVal == EBhUndefined)

View File

@ -29,7 +29,8 @@ class TDirectiveHandler : public pp::DirectiveHandler
virtual void handlePragma(const pp::SourceLocation& loc,
const std::string& name,
const std::string& value);
const std::string& value,
bool stdgl);
virtual void handleExtension(const pp::SourceLocation& loc,
const std::string& name,

View File

@ -133,6 +133,14 @@ bool CompareStructure(const TType &leftNodeType,
//
////////////////////////////////////////////////////////////////
void TIntermTyped::setTypePreservePrecision(const TType &t)
{
TPrecision precision = getPrecision();
mType = t;
ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
mType.setPrecision(precision);
}
#define REPLACE_IF_IS(node, type, original, replacement) \
if (node == original) { \
node = static_cast<type *>(replacement); \
@ -237,6 +245,52 @@ void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) con
}
}
void TIntermAggregate::setPrecisionFromChildren()
{
if (getBasicType() == EbtBool)
{
mType.setPrecision(EbpUndefined);
return;
}
TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin();
while (childIter != mSequence.end())
{
TIntermTyped *typed = (*childIter)->getAsTyped();
if (typed)
precision = GetHigherPrecision(typed->getPrecision(), precision);
++childIter;
}
mType.setPrecision(precision);
}
void TIntermAggregate::setBuiltInFunctionPrecision()
{
// All built-ins returning bool should be handled as ops, not functions.
ASSERT(getBasicType() != EbtBool);
TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin();
while (childIter != mSequence.end())
{
TIntermTyped *typed = (*childIter)->getAsTyped();
// ESSL spec section 8: texture functions get their precision from the sampler.
if (typed && IsSampler(typed->getBasicType()))
{
precision = typed->getPrecision();
break;
}
++childIter;
}
// ESSL 3.0 spec section 8: textureSize always gets highp precision.
// All other functions that take a sampler are assumed to be texture functions.
if (mName.find("textureSize") == 0)
mType.setPrecision(EbpHigh);
else
mType.setPrecision(precision);
}
bool TIntermSelection::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@ -336,6 +390,7 @@ bool TIntermUnary::promote(TInfoSink &)
return false;
break;
case EOpNegative:
case EOpPositive:
case EOpPostIncrement:
case EOpPostDecrement:
case EOpPreIncrement:
@ -1068,6 +1123,27 @@ TIntermTyped *TIntermConstantUnion::fold(
}
break;
case EOpPositive:
switch (getType().getBasicType())
{
case EbtFloat:
tempConstArray[i].setFConst(unionArray[i].getFConst());
break;
case EbtInt:
tempConstArray[i].setIConst(unionArray[i].getIConst());
break;
case EbtUInt:
tempConstArray[i].setUConst(static_cast<unsigned int>(
static_cast<int>(unionArray[i].getUConst())));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return NULL;
}
break;
case EOpLogicalNot:
// this code is written for possible future use,
// will not get executed currently

View File

@ -45,6 +45,7 @@ enum TOperator
//
EOpNegative,
EOpPositive,
EOpLogicalNot,
EOpVectorLogicalNot,
@ -265,6 +266,7 @@ class TIntermTyped : public TIntermNode
virtual bool hasSideEffects() const = 0;
void setType(const TType &t) { mType = t; }
void setTypePreservePrecision(const TType &t);
const TType &getType() const { return mType; }
TType *getTypePointer() { return &mType; }
@ -613,6 +615,9 @@ class TIntermAggregate : public TIntermOperator
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
void setPrecisionFromChildren();
void setBuiltInFunctionPrecision();
protected:
TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator

View File

@ -198,6 +198,7 @@ TIntermTyped *TIntermediate::addUnaryMath(
case EOpPostDecrement:
case EOpPreDecrement:
case EOpNegative:
case EOpPositive:
if (child->getType().getBasicType() == EbtStruct ||
child->getType().isArray())
{

View File

@ -395,6 +395,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
case EOpNegative: preString = "(-"; break;
case EOpPositive: preString = "(+"; break;
case EOpVectorLogicalNot: preString = "not("; break;
case EOpLogicalNot: preString = "(!"; break;
@ -574,7 +575,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
// Function declaration.
ASSERT(visit == PreVisit);
writeVariableType(node->getType());
out << " " << hashName(node->getName());
out << " " << hashFunctionName(node->getName());
out << "(";
writeFunctionParameters(*(node->getSequence()));
@ -649,17 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
mDeclaringVariables = false;
}
break;
case EOpInvariantDeclaration: {
// Invariant declaration.
ASSERT(visit == PreVisit);
case EOpInvariantDeclaration:
// Invariant declaration.
ASSERT(visit == PreVisit);
{
const TIntermSequence *sequence = node->getSequence();
ASSERT(sequence && sequence->size() == 1);
const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
ASSERT(symbol);
out << "invariant " << symbol->getSymbol() << ";";
visitChildren = false;
break;
out << "invariant " << hashVariableName(symbol->getSymbol());
}
visitChildren = false;
break;
case EOpConstructFloat:
writeTriplet(visit, "float(", NULL, ")");
break;
@ -741,7 +743,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
break;
case EOpComma:
writeTriplet(visit, NULL, ", ", NULL);
writeTriplet(visit, "(", ", ", ")");
break;
case EOpMod:

View File

@ -135,6 +135,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
mUniqueIndex = 0;
mContainsLoopDiscontinuity = false;
mContainsAnyLoop = false;
mOutputLod0Function = false;
mInsideDiscontinuousLoop = false;
mNestedLoopDepth = 0;
@ -172,6 +173,7 @@ OutputHLSL::~OutputHLSL()
void OutputHLSL::output()
{
mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
mContainsAnyLoop = containsAnyLoop(mContext.treeRoot);
const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
makeFlaggedStructMaps(flaggedStructs);
@ -320,14 +322,22 @@ void OutputHLSL::header()
if (mUsesDiscardRewriting)
{
out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
out << "#define ANGLE_USES_DISCARD_REWRITING\n";
}
if (mUsesNestedBreak)
{
out << "#define ANGLE_USES_NESTED_BREAK" << "\n";
out << "#define ANGLE_USES_NESTED_BREAK\n";
}
out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n"
"#define LOOP [loop]\n"
"#define FLATTEN [flatten]\n"
"#else\n"
"#define LOOP\n"
"#define FLATTEN\n"
"#endif\n";
if (mContext.shaderType == GL_FRAGMENT_SHADER)
{
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
@ -1747,6 +1757,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
case EOpPositive: outputTriplet(visit, "(+", "", ")"); break;
case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
@ -1860,15 +1871,20 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
{
if (!mInsideFunction)
{
out << "static ";
}
out << TypeString(variable->getType()) + " ";
for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
{
if (isSingleStatement(*sit))
{
mUnfoldShortCircuit->traverse(*sit);
}
if (!mInsideFunction)
{
out << "static ";
}
out << TypeString(variable->getType()) + " ";
TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
if (symbol)
@ -1884,7 +1900,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (*sit != sequence->back())
{
out << ", ";
out << ";\n";
}
}
}
@ -1925,7 +1941,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpPrototype:
if (visit == PreVisit)
{
out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
out << TypeString(node->getType()) << " " << Decorate(TFunction::unmangleName(node->getName())) << (mOutputLod0Function ? "Lod0(" : "(");
TIntermSequence *arguments = node->getSequence();
@ -2287,6 +2303,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
{
mUnfoldShortCircuit->traverse(node->getCondition());
// D3D errors when there is a gradient operation in a loop in an unflattened if
// however flattening all the ifs in branch heavy shaders made D3D error too.
// As a temporary workaround we flatten the ifs only if there is at least a loop
// present somewhere in the shader.
if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
{
out << "FLATTEN ";
}
out << "if (";
node->getCondition()->traverse(this);
@ -2367,14 +2392,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
if (node->getType() == ELoopDoWhile)
{
out << "{do\n";
out << "{LOOP do\n";
outputLineDirective(node->getLine().first_line);
out << "{\n";
}
else
{
out << "{for(";
out << "{LOOP for(";
if (node->getInit())
{
@ -2503,6 +2528,12 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node)
{
return false;
}
else if (aggregate->getOp() == EOpDeclaration)
{
// Declaring multiple comma-separated variables must be considered multiple statements
// because each individual declaration has side effects which are visible in the next.
return false;
}
else
{
for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++)
@ -2675,7 +2706,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
// for(int index = initial; index < clampedLimit; index += increment)
out << "for(";
out << "LOOP for(";
index->traverse(this);
out << " = ";
out << initial;

View File

@ -144,6 +144,7 @@ class OutputHLSL : public TIntermTraverser
int mUniqueIndex; // For creating unique names
bool mContainsLoopDiscontinuity;
bool mContainsAnyLoop;
bool mOutputLod0Function;
bool mInsideDiscontinuousLoop;
int mNestedLoopDepth;

View File

@ -1004,12 +1004,12 @@ void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char*
directiveHandler.handleExtension(srcLoc, extName, behavior);
}
void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value)
void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl)
{
pp::SourceLocation srcLoc;
srcLoc.file = loc.first_file;
srcLoc.line = loc.first_line;
directiveHandler.handlePragma(srcLoc, name, value);
directiveHandler.handlePragma(srcLoc, name, value, stdgl);
}
/////////////////////////////////////////////////////////////////////////////////
@ -1364,11 +1364,18 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv
{
error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
recover();
return NULL;
}
else
{
const TString kGlFrontFacing("gl_FrontFacing");
if (*identifier == kGlFrontFacing)
{
error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
recover();
return NULL;
}
symbolTable.addInvariantVarying(*identifier);
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
ASSERT(variable);
const TType &type = variable->getType();

View File

@ -116,7 +116,7 @@ struct TParseContext {
bool supportsExtension(const char* extension);
bool isExtensionEnabled(const char* extension) const;
void handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior);
void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value);
void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl);
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);

View File

@ -7,13 +7,23 @@
#ifndef COMPILER_PRAGMA_H_
#define COMPILER_PRAGMA_H_
struct TPragma {
struct TPragma
{
struct STDGL
{
STDGL() : invariantAll(false) { }
bool invariantAll;
};
// By default optimization is turned on and debug is turned off.
TPragma() : optimize(true), debug(false) { }
TPragma(bool o, bool d) : optimize(o), debug(d) { }
bool optimize;
bool debug;
STDGL stdgl;
};
#endif // COMPILER_PRAGMA_H_

View File

@ -37,72 +37,6 @@ bool isInitialized = false;
// and the shading language compiler.
//
static bool CheckVariableMaxLengths(const ShHandle handle,
size_t expectedValue)
{
size_t activeUniformLimit = 0;
ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
size_t activeAttribLimit = 0;
ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
size_t varyingLimit = 0;
ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
return (expectedValue == activeUniformLimit &&
expectedValue == activeAttribLimit &&
expectedValue == varyingLimit);
}
bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
{
size_t mappedNameMaxLength = 0;
ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
return (expectedValue == mappedNameMaxLength);
}
template <typename VarT>
const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index)
{
if (index < 0 || static_cast<size_t>(index) >= infoList.size())
{
return NULL;
}
return &infoList[index];
}
const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index)
{
switch (varType)
{
case SH_ACTIVE_ATTRIBUTES:
return ReturnVariable(compiler->getAttributes(), index);
case SH_ACTIVE_UNIFORMS:
return ReturnVariable(compiler->getExpandedUniforms(), index);
case SH_VARYINGS:
return ReturnVariable(compiler->getExpandedVaryings(), index);
default:
UNREACHABLE();
return NULL;
}
}
ShPrecisionType ConvertPrecision(sh::GLenum precision)
{
switch (precision)
{
case GL_HIGH_FLOAT:
case GL_HIGH_INT:
return SH_PRECISION_HIGHP;
case GL_MEDIUM_FLOAT:
case GL_MEDIUM_INT:
return SH_PRECISION_MEDIUMP;
case GL_LOW_FLOAT:
case GL_LOW_INT:
return SH_PRECISION_LOWP;
default:
return SH_PRECISION_UNDEFINED;
}
}
template <typename VarT>
const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType);
@ -150,32 +84,48 @@ const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariabl
return GetVariableList<VarT>(compiler, variableType);
}
TCompiler *GetCompilerFromHandle(ShHandle handle)
{
if (!handle)
return NULL;
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
return base->getAsCompiler();
}
TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
{
if (!handle)
return NULL;
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
return base->getAsTranslatorHLSL();
}
} // namespace anonymous
//
// Driver must call this first, once, before doing any other compiler operations.
// Subsequent calls to this function are no-op.
//
int ShInitialize()
bool ShInitialize()
{
if (!isInitialized)
{
isInitialized = InitProcess();
}
return isInitialized ? 1 : 0;
return isInitialized;
}
//
// Cleanup symbol tables
//
int ShFinalize()
bool ShFinalize()
{
if (isInitialized)
{
DetachProcess();
isInitialized = false;
}
return 1;
return true;
}
//
@ -183,6 +133,9 @@ int ShFinalize()
//
void ShInitBuiltInResources(ShBuiltInResources* resources)
{
// Make comparable.
memset(resources, 0, sizeof(*resources));
// Constants.
resources->MaxVertexAttribs = 8;
resources->MaxVertexUniformVectors = 128;
@ -201,6 +154,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->EXT_frag_depth = 0;
resources->EXT_shader_texture_lod = 0;
resources->NV_draw_buffers = 0;
// Disable highp precision in fragment shader by default.
resources->FragmentPrecisionHigh = 0;
@ -251,23 +206,13 @@ void ShDestruct(ShHandle handle)
DeleteCompiler(base->getAsCompiler());
}
void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString)
const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
{
if (!handle || !outString)
{
return;
}
TShHandleBase *base = static_cast<TShHandleBase*>(handle);
TCompiler *compiler = base->getAsCompiler();
if (!compiler)
{
return;
}
strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen);
outString[outStringLen - 1] = '\0';
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getBuiltInResourcesString();
}
//
// Do an actual compile on the given strings. The result is left
// in the given compile object.
@ -275,219 +220,62 @@ void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, cha
// Return: The return value of ShCompile is really boolean, indicating
// success or failure.
//
int ShCompile(
bool ShCompile(
const ShHandle handle,
const char* const shaderStrings[],
const char *const shaderStrings[],
size_t numStrings,
int compileOptions)
{
if (handle == 0)
return 0;
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return 0;
bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
return success ? 1 : 0;
return compiler->compile(shaderStrings, numStrings, compileOptions);
}
void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
int ShGetShaderVersion(const ShHandle handle)
{
if (!handle || !params)
return;
TCompiler* compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getShaderVersion();
}
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
switch(pname)
{
case SH_INFO_LOG_LENGTH:
*params = compiler->getInfoSink().info.size() + 1;
break;
case SH_OBJECT_CODE_LENGTH:
*params = compiler->getInfoSink().obj.size() + 1;
break;
case SH_ACTIVE_UNIFORMS:
*params = compiler->getExpandedUniforms().size();
break;
case SH_ACTIVE_UNIFORM_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_ACTIVE_ATTRIBUTES:
*params = compiler->getAttributes().size();
break;
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_VARYINGS:
*params = compiler->getExpandedVaryings().size();
break;
case SH_VARYING_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_MAPPED_NAME_MAX_LENGTH:
// Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
// handle array and struct dereferences.
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_NAME_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_HASHED_NAME_MAX_LENGTH:
if (compiler->getHashFunction() == NULL) {
*params = 0;
} else {
// 64 bits hashing output requires 16 bytes for hex
// representation.
const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
(void)HashedNamePrefix;
*params = 16 + sizeof(HashedNamePrefix);
}
break;
case SH_HASHED_NAMES_COUNT:
*params = compiler->getNameMap().size();
break;
case SH_SHADER_VERSION:
*params = compiler->getShaderVersion();
break;
case SH_RESOURCES_STRING_LENGTH:
*params = compiler->getBuiltInResourcesString().length() + 1;
break;
case SH_OUTPUT_TYPE:
*params = compiler->getOutputType();
break;
default: UNREACHABLE();
}
ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
{
TCompiler* compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getOutputType();
}
//
// Return any compiler log of messages for the application.
//
void ShGetInfoLog(const ShHandle handle, char* infoLog)
const std::string &ShGetInfoLog(const ShHandle handle)
{
if (!handle || !infoLog)
return;
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
TInfoSink& infoSink = compiler->getInfoSink();
strcpy(infoLog, infoSink.info.c_str());
TInfoSink &infoSink = compiler->getInfoSink();
return infoSink.info.str();
}
//
// Return any object code.
//
void ShGetObjectCode(const ShHandle handle, char* objCode)
const std::string &ShGetObjectCode(const ShHandle handle)
{
if (!handle || !objCode)
return;
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
TInfoSink& infoSink = compiler->getInfoSink();
strcpy(objCode, infoSink.obj.c_str());
TInfoSink &infoSink = compiler->getInfoSink();
return infoSink.obj.str();
}
void ShGetVariableInfo(const ShHandle handle,
ShShaderInfo varType,
int index,
size_t* length,
int* size,
sh::GLenum* type,
ShPrecisionType* precision,
int* staticUse,
char* name,
char* mappedName)
const std::map<std::string, std::string> *ShGetNameHashingMap(
const ShHandle handle)
{
if (!handle || !size || !type || !precision || !staticUse || !name)
return;
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
(varType == SH_ACTIVE_UNIFORMS) ||
(varType == SH_VARYINGS));
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return;
const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index);
if (!varInfo)
{
return;
}
if (length) *length = varInfo->name.size();
*size = varInfo->elementCount();
*type = varInfo->type;
*precision = ConvertPrecision(varInfo->precision);
*staticUse = varInfo->staticUse ? 1 : 0;
// This size must match that queried by
// SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
// in ShGetInfo, below.
size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
ASSERT(CheckVariableMaxLengths(handle, variableLength));
strncpy(name, varInfo->name.c_str(), variableLength);
name[variableLength - 1] = 0;
if (mappedName)
{
// This size must match that queried by
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength));
strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength);
mappedName[maxMappedNameLength - 1] = 0;
}
}
void ShGetNameHashingEntry(const ShHandle handle,
int index,
char* name,
char* hashedName)
{
if (!handle || !name || !hashedName || index < 0)
return;
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
const NameMap& nameMap = compiler->getNameMap();
if (index >= static_cast<int>(nameMap.size()))
return;
NameMap::const_iterator it = nameMap.begin();
for (int i = 0; i < index; ++i)
++it;
size_t len = it->first.length() + 1;
size_t max_len = 0;
ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
if (len > max_len) {
ASSERT(false);
len = max_len;
}
strncpy(name, it->first.c_str(), len);
// To be on the safe side in case the source is longer than expected.
name[len - 1] = '\0';
len = it->second.length() + 1;
max_len = 0;
ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
if (len > max_len) {
ASSERT(false);
len = max_len;
}
strncpy(hashedName, it->second.c_str(), len);
// To be on the safe side in case the source is longer than expected.
hashedName[len - 1] = '\0';
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return &(compiler->getNameMap());
}
const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
@ -515,11 +303,11 @@ const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handl
return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK);
}
int ShCheckVariablesWithinPackingLimits(
int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
bool ShCheckVariablesWithinPackingLimits(
int maxVectors, ShVariableInfo *varInfoArray, size_t varInfoArraySize)
{
if (varInfoArraySize == 0)
return 1;
return true;
ASSERT(varInfoArray);
std::vector<sh::ShaderVariable> variables;
for (size_t ii = 0; ii < varInfoArraySize; ++ii)
@ -528,24 +316,17 @@ int ShCheckVariablesWithinPackingLimits(
variables.push_back(var);
}
VariablePacker packer;
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
}
bool ShGetInterfaceBlockRegister(const ShHandle handle,
const char *interfaceBlockName,
const std::string &interfaceBlockName,
unsigned int *indexOut)
{
if (!handle || !interfaceBlockName || !indexOut)
{
return false;
}
ASSERT(indexOut);
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TranslatorHLSL* translator = base->getAsTranslatorHLSL();
if (!translator)
{
return false;
}
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
if (!translator->hasInterfaceBlock(interfaceBlockName))
{
@ -557,20 +338,12 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
}
bool ShGetUniformRegister(const ShHandle handle,
const char *uniformName,
const std::string &uniformName,
unsigned int *indexOut)
{
if (!handle || !uniformName || !indexOut)
{
return false;
}
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TranslatorHLSL* translator = base->getAsTranslatorHLSL();
if (!translator)
{
return false;
}
ASSERT(indexOut);
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
if (!translator->hasUniform(uniformName))
{

View File

@ -9,6 +9,8 @@
#include <GLSLANG/ShaderLang.h>
#include "compiler/translator/compilerdebug.h"
namespace sh
{
@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
return *this;
}
bool ShaderVariable::operator==(const ShaderVariable &other) const
{
if (type != other.type ||
precision != other.precision ||
name != other.name ||
mappedName != other.mappedName ||
arraySize != other.arraySize ||
staticUse != other.staticUse ||
fields.size() != other.fields.size() ||
structName != other.structName)
{
return false;
}
for (size_t ii = 0; ii < fields.size(); ++ii)
{
if (fields[ii] != other.fields[ii])
return false;
}
return true;
}
bool ShaderVariable::findInfoByMappedName(
const std::string &mappedFullName,
const ShaderVariable **leafVar, std::string *originalFullName) const
{
ASSERT(leafVar && originalFullName);
// There are three cases:
// 1) the top variable is of struct type;
// 2) the top variable is an array;
// 3) otherwise.
size_t pos = mappedFullName.find_first_of(".[");
std::string topName;
if (pos == std::string::npos)
{
// Case 3.
if (mappedFullName != this->mappedName)
return false;
*originalFullName = this->name;
*leafVar = this;
return true;
}
else
{
std::string topName = mappedFullName.substr(0, pos);
if (topName != this->mappedName)
return false;
std::string originalName = this->name;
std::string remaining;
if (mappedFullName[pos] == '[')
{
// Case 2.
size_t closePos = mappedFullName.find_first_of(']');
if (closePos < pos || closePos == std::string::npos)
return false;
// Append '[index]'.
originalName += mappedFullName.substr(pos, closePos - pos + 1);
if (closePos + 1 == mappedFullName.size())
{
*originalFullName = originalName;
*leafVar = this;
return true;
}
else
{
// In the form of 'a[0].b', so after ']', '.' is expected.
if (mappedFullName[closePos + 1] != '.')
return false;
remaining = mappedFullName.substr(closePos + 2); // Skip "]."
}
}
else
{
// Case 1.
remaining = mappedFullName.substr(pos + 1); // Skip "."
}
for (size_t ii = 0; ii < this->fields.size(); ++ii)
{
const ShaderVariable *fieldVar = NULL;
std::string originalFieldName;
bool found = fields[ii].findInfoByMappedName(
remaining, &fieldVar, &originalFieldName);
if (found)
{
*originalFullName = originalName + "." + originalFieldName;
*leafVar = fieldVar;
return true;
}
}
return false;
}
}
bool ShaderVariable::isSameVariableAtLinkTime(
const ShaderVariable &other, bool matchPrecision) const
{
if (type != other.type)
return false;
if (matchPrecision && precision != other.precision)
return false;
if (name != other.name)
return false;
ASSERT(mappedName == other.mappedName);
if (arraySize != other.arraySize)
return false;
if (fields.size() != other.fields.size())
return false;
for (size_t ii = 0; ii < fields.size(); ++ii)
{
if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
matchPrecision))
{
return false;
}
}
if (structName != other.structName)
return false;
return true;
}
Uniform::Uniform()
{}
@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other)
return *this;
}
bool Uniform::operator==(const Uniform &other) const
{
return ShaderVariable::operator==(other);
}
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{
return ShaderVariable::isSameVariableAtLinkTime(other, true);
}
Attribute::Attribute()
: location(-1)
{}
@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other)
return *this;
}
bool Attribute::operator==(const Attribute &other) const
{
return (ShaderVariable::operator==(other) &&
location == other.location);
}
InterfaceBlockField::InterfaceBlockField()
: isRowMajorLayout(false)
{}
@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o
return *this;
}
bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
{
return (ShaderVariable::operator==(other) &&
isRowMajorLayout == other.isRowMajorLayout);
}
bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
const InterfaceBlockField &other) const
{
return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
isRowMajorLayout == other.isRowMajorLayout);
}
Varying::Varying()
: interpolation(INTERPOLATION_SMOOTH),
isInvariant(false)
@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other)
return *this;
}
bool Varying::operator==(const Varying &other) const
{
return (ShaderVariable::operator==(other) &&
interpolation == other.interpolation &&
isInvariant == other.isInvariant);
}
bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
{
return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
interpolation == other.interpolation &&
isInvariant == other.isInvariant);
}
InterfaceBlock::InterfaceBlock()
: arraySize(0),
layout(BLOCKLAYOUT_PACKED),

View File

@ -31,6 +31,7 @@
//
#include <assert.h>
#include <set>
#include "common/angleutils.h"
#include "compiler/translator/InfoSink.h"
@ -299,19 +300,21 @@ class TSymbolTableLevel
tLevel level;
};
enum ESymbolLevel
{
COMMON_BUILTINS = 0,
ESSL1_BUILTINS = 1,
ESSL3_BUILTINS = 2,
LAST_BUILTIN_LEVEL = ESSL3_BUILTINS,
GLOBAL_LEVEL = 3
};
// Define ESymbolLevel as int rather than an enum since level can go
// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
// compiler optimizes the >= of the last element to ==.
typedef int ESymbolLevel;
const int COMMON_BUILTINS = 0;
const int ESSL1_BUILTINS = 1;
const int ESSL3_BUILTINS = 2;
const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS;
const int GLOBAL_LEVEL = 3;
class TSymbolTable
{
public:
TSymbolTable()
: mGlobalInvariant(false)
{
// The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect
@ -408,6 +411,25 @@ class TSymbolTable
// for the specified TBasicType
TPrecision getDefaultPrecision(TBasicType type) const;
// This records invariant varyings declared through
// "invariant varying_name;".
void addInvariantVarying(const TString &originalName)
{
mInvariantVaryings.insert(originalName);
}
// If this returns false, the varying could still be invariant
// if it is set as invariant during the varying variable
// declaration - this piece of information is stored in the
// variable's type, not here.
bool isVaryingInvariant(const TString &originalName) const
{
return (mGlobalInvariant ||
mInvariantVaryings.count(originalName) > 0);
}
void setGlobalInvariant() { mGlobalInvariant = true; }
bool getGlobalInvariant() const { return mGlobalInvariant; }
static int nextUniqueId()
{
return ++uniqueIdCounter;
@ -423,6 +445,9 @@ class TSymbolTable
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector< PrecisionStackLevel *> precisionStack;
std::set<TString> mInvariantVaryings;
bool mGlobalInvariant;
static int uniqueIdCounter;
};

View File

@ -16,6 +16,8 @@ TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
void TranslatorESSL::translate(TIntermNode* root) {
TInfoSinkBase& sink = getInfoSink().obj;
writePragma();
// Write built-in extension behaviors.
writeExtensionBehavior();
@ -37,8 +39,13 @@ void TranslatorESSL::writeExtensionBehavior() {
for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
iter != extensionBehavior.end(); ++iter) {
if (iter->second != EBhUndefined) {
sink << "#extension " << iter->first << " : "
<< getBehaviorString(iter->second) << "\n";
if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
sink << "#extension GL_NV_draw_buffers : "
<< getBehaviorString(iter->second) << "\n";
} else {
sink << "#extension " << iter->first << " : "
<< getBehaviorString(iter->second) << "\n";
}
}
}
}

View File

@ -9,18 +9,6 @@
#include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/VersionGLSL.h"
static void writeVersion(sh::GLenum type, TIntermNode* root,
TInfoSinkBase& sink) {
TVersionGLSL versionGLSL(type);
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
// If there is no version directive in the shader, 110 is implied.
if (version > 110) {
sink << "#version " << version << "\n";
}
}
TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec)
: TCompiler(type, spec, SH_GLSL_OUTPUT) {
}
@ -29,7 +17,9 @@ void TranslatorGLSL::translate(TIntermNode* root) {
TInfoSinkBase& sink = getInfoSink().obj;
// Write GLSL version.
writeVersion(getShaderType(), root, sink);
writeVersion(root);
writePragma();
// Write extension behaviour as needed
writeExtensionBehavior();
@ -46,6 +36,20 @@ void TranslatorGLSL::translate(TIntermNode* root) {
root->traverse(&outputGLSL);
}
void TranslatorGLSL::writeVersion(TIntermNode *root)
{
TVersionGLSL versionGLSL(getShaderType(), getPragma());
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
// If there is no version directive in the shader, 110 is implied.
if (version > 110)
{
TInfoSinkBase& sink = getInfoSink().obj;
sink << "#version " << version << "\n";
}
}
void TranslatorGLSL::writeExtensionBehavior() {
TInfoSinkBase& sink = getInfoSink().obj;
const TExtensionBehavior& extensionBehavior = getExtensionBehavior();

View File

@ -9,14 +9,16 @@
#include "compiler/translator/Compiler.h"
class TranslatorGLSL : public TCompiler {
public:
class TranslatorGLSL : public TCompiler
{
public:
TranslatorGLSL(sh::GLenum type, ShShaderSpec spec);
protected:
virtual void translate(TIntermNode* root);
protected:
virtual void translate(TIntermNode *root);
private:
private:
void writeVersion(TIntermNode *root);
void writeExtensionBehavior();
};

View File

@ -94,6 +94,7 @@ const char *GetOperatorString(TOperator op)
case EOpLogicalXor: return "^^";
case EOpLogicalAnd: return "&&";
case EOpNegative: return "-";
case EOpPositive: return "+";
case EOpVectorLogicalNot: return "not";
case EOpLogicalNot: return "!";
case EOpPostIncrement: return "++";

View File

@ -5,6 +5,7 @@
//
#include "angle_gl.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VariableInfo.h"
#include "compiler/translator/util.h"
#include "common/utilities.h"
@ -131,7 +132,8 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
std::vector<sh::Uniform> *uniforms,
std::vector<sh::Varying> *varyings,
std::vector<sh::InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction)
ShHashFunction64 hashFunction,
const TSymbolTable &symbolTable)
: mAttribs(attribs),
mOutputVariables(outputVariables),
mUniforms(uniforms),
@ -140,7 +142,10 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
mHashFunction(hashFunction)
mPositionAdded(false),
mPointSizeAdded(false),
mHashFunction(hashFunction),
mSymbolTable(symbolTable)
{
}
@ -200,12 +205,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
if (!mFragCoordAdded)
{
Varying info;
info.name = "gl_FragCoord";
info.mappedName = "gl_FragCoord";
const char kName[] = "gl_FragCoord";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT_VEC4;
info.arraySize = 0;
info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mFragCoordAdded = true;
}
@ -214,12 +221,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
if (!mFrontFacingAdded)
{
Varying info;
info.name = "gl_FrontFacing";
info.mappedName = "gl_FrontFacing";
const char kName[] = "gl_FrontFacing";
info.name = kName;
info.mappedName = kName;
info.type = GL_BOOL;
info.arraySize = 0;
info.precision = GL_NONE;
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mFrontFacingAdded = true;
}
@ -228,16 +237,50 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
if (!mPointCoordAdded)
{
Varying info;
info.name = "gl_PointCoord";
info.mappedName = "gl_PointCoord";
const char kName[] = "gl_PointCoord";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT_VEC2;
info.arraySize = 0;
info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mPointCoordAdded = true;
}
return;
case EvqPosition:
if (!mPositionAdded)
{
Varying info;
const char kName[] = "gl_Position";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT_VEC4;
info.arraySize = 0;
info.precision = GL_HIGH_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mPositionAdded = true;
}
return;
case EvqPointSize:
if (!mPointSizeAdded)
{
Varying info;
const char kName[] = "gl_PointSize";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT;
info.arraySize = 0;
info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mPointSizeAdded = true;
}
return;
default:
break;
}
@ -251,8 +294,10 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
class NameHashingTraverser : public GetVariableTraverser
{
public:
NameHashingTraverser(ShHashFunction64 hashFunction)
: mHashFunction(hashFunction)
NameHashingTraverser(ShHashFunction64 hashFunction,
const TSymbolTable &symbolTable)
: GetVariableTraverser(symbolTable),
mHashFunction(hashFunction)
{}
private:
@ -312,7 +357,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
const TType &fieldType = *field.type();
GetVariableTraverser traverser;
GetVariableTraverser traverser(mSymbolTable);
traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
@ -325,7 +370,7 @@ template <typename VarT>
void CollectVariables::visitVariable(const TIntermSymbol *variable,
std::vector<VarT> *infoList) const
{
NameHashingTraverser traverser(mHashFunction);
NameHashingTraverser traverser(mHashFunction, mSymbolTable);
traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
}
@ -421,9 +466,8 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
return true;
}
template <typename VarT>
void ExpandVariables(const std::vector<VarT> &compact,
std::vector<ShaderVariable> *expanded)
void ExpandUniforms(const std::vector<Uniform> &compact,
std::vector<ShaderVariable> *expanded)
{
for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
{
@ -432,7 +476,4 @@ void ExpandVariables(const std::vector<VarT> &compact,
}
}
template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *);
template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *);
}

View File

@ -11,6 +11,8 @@
#include "compiler/translator/IntermNode.h"
class TSymbolTable;
namespace sh
{
@ -23,7 +25,8 @@ class CollectVariables : public TIntermTraverser
std::vector<Uniform> *uniforms,
std::vector<Varying> *varyings,
std::vector<InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction);
ShHashFunction64 hashFunction,
const TSymbolTable &symbolTable);
virtual void visitSymbol(TIntermSymbol *symbol);
virtual bool visitAggregate(Visit, TIntermAggregate *node);
@ -48,13 +51,17 @@ class CollectVariables : public TIntermTraverser
bool mFrontFacingAdded;
bool mFragCoordAdded;
bool mPositionAdded;
bool mPointSizeAdded;
ShHashFunction64 mHashFunction;
const TSymbolTable &mSymbolTable;
};
// Expand struct variables to flattened lists of split variables
template <typename VarT>
void ExpandVariables(const std::vector<VarT> &compact,
std::vector<ShaderVariable> *expanded);
// Expand struct uniforms to flattened lists of split variables
void ExpandUniforms(const std::vector<Uniform> &compact,
std::vector<ShaderVariable> *expanded);
}

View File

@ -26,18 +26,12 @@ static const int GLSL_VERSION_120 = 120;
// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
// are built-in types, entire structures or arrays... are all l-values."
//
// TODO(alokp): The following two cases of invariant decalaration get lost
// during parsing - they do not get carried over to the intermediate tree.
// Handle these cases:
// 1. When a pragma is used to force all output variables to be invariant:
// - #pragma STDGL invariant(all)
// 2. When a previously decalared or built-in variable is marked invariant:
// - invariant gl_Position;
// - varying vec3 color; invariant color;
//
TVersionGLSL::TVersionGLSL(sh::GLenum type)
: mVersion(GLSL_VERSION_110)
TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma)
{
if (pragma.stdgl.invariantAll)
mVersion = GLSL_VERSION_120;
else
mVersion = GLSL_VERSION_110;
}
void TVersionGLSL::visitSymbol(TIntermSymbol *node)

View File

@ -9,6 +9,8 @@
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Pragma.h"
// Traverses the intermediate tree to return the minimum GLSL version
// required to legally access all built-in features used in the shader.
// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
@ -27,7 +29,7 @@
class TVersionGLSL : public TIntermTraverser
{
public:
TVersionGLSL(sh::GLenum type);
TVersionGLSL(sh::GLenum type, const TPragma &pragma);
// Returns 120 if the following is used the shader:
// - "invariant",

View File

@ -354,6 +354,15 @@ function_call
// Treat it like a built-in unary operator.
//
$$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1);
const TType& returnType = fnCandidate->getReturnType();
if (returnType.getBasicType() == EbtBool) {
// Bool types should not have precision, so we'll override any precision
// that might have been set by addUnaryMath.
$$->setType(returnType);
} else {
// addUnaryMath has set the precision of the node based on the operand.
$$->setTypePreservePrecision(returnType);
}
if ($$ == 0) {
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
@ -362,20 +371,29 @@ function_call
YYERROR;
}
} else {
$$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
$$ = aggregate;
}
} else {
// This is a real function call
$$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
$$->setType(fnCandidate->getReturnType());
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
aggregate->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn)
$$->getAsAggregate()->setUserDefined();
$$->getAsAggregate()->setName(fnCandidate->getMangledName());
aggregate->setUserDefined();
aggregate->setName(fnCandidate->getMangledName());
// This needs to happen after the name is set
if (builtIn)
aggregate->setBuiltInFunctionPrecision();
$$ = aggregate;
TQualifier qual;
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
@ -388,7 +406,6 @@ function_call
}
}
}
$$->setType(fnCandidate->getReturnType());
} else {
// error message was put out by PaFindFunction()
// Put on a dummy node for error recovery
@ -500,6 +517,7 @@ unary_expression
const char* errorOp = "";
switch($1.op) {
case EOpNegative: errorOp = "-"; break;
case EOpPositive: errorOp = "+"; break;
case EOpLogicalNot: errorOp = "!"; break;
default: break;
}
@ -514,7 +532,7 @@ unary_expression
// Grammar Note: No traditional style type casts.
unary_operator
: PLUS { $$.op = EOpNull; }
: PLUS { $$.op = EOpPositive; }
| DASH { $$.op = EOpNegative; }
| BANG { $$.op = EOpLogicalNot; }
;
@ -762,7 +780,7 @@ declaration
TIntermAggregate *prototype = new TIntermAggregate;
prototype->setType(function.getReturnType());
prototype->setName(function.getName());
prototype->setName(function.getMangledName());
for (size_t i = 0; i < function.getParamCount(); i++)
{

View File

@ -62,7 +62,9 @@ TString TType::getCompleteString() const
TStringStream stream;
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
stream << getQualifierString() << " " << getPrecisionString() << " ";
stream << getQualifierString() << " ";
if (precision != EbpUndefined)
stream << getPrecisionString() << " ";
if (array)
stream << "array[" << getArraySize() << "] of ";
if (isMatrix())
@ -221,6 +223,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
case EOpNegative: out << "Negate value"; break;
case EOpPositive: out << "Positive sign"; break;
case EOpVectorLogicalNot:
case EOpLogicalNot: out << "Negate conditional"; break;
@ -292,6 +295,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpFunction: out << "Function Definition: " << node->getName(); break;
case EOpFunctionCall: out << "Function Call: " << node->getName(); break;
case EOpParameters: out << "Function Parameters: "; break;
case EOpPrototype: out << "Function Prototype: " << node->getName(); break;
case EOpConstructFloat: out << "Construct float"; break;
case EOpConstructVec2: out << "Construct vec2"; break;

View File

@ -9,6 +9,7 @@
#include <limits>
#include "compiler/preprocessor/numeric_lex.h"
#include "compiler/translator/SymbolTable.h"
#include "common/utilities.h"
bool atof_clamp(const char *str, float *value)
@ -281,8 +282,47 @@ InterpolationType GetInterpolationType(TQualifier qualifier)
}
}
GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable)
: mSymbolTable(symbolTable)
{
}
template void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, InterfaceBlockField *variable);
template void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, ShaderVariable *variable);
template void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, Uniform *variable);
template<>
void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, Varying *variable)
{
ASSERT(variable);
switch (type.getQualifier())
{
case EvqInvariantVaryingIn:
case EvqInvariantVaryingOut:
variable->isInvariant = true;
break;
case EvqVaryingIn:
case EvqVaryingOut:
if (mSymbolTable.isVaryingInvariant(name))
{
variable->isInvariant = true;
}
break;
default:
break;
}
variable->interpolation = GetInterpolationType(type.getQualifier());
}
template <typename VarT>
void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output)
void GetVariableTraverser::traverse(const TType &type,
const TString &name,
std::vector<VarT> *output)
{
const TStructure *structure = type.getStruct();
@ -309,15 +349,16 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name, std:
traverse(*field->type(), field->name(), &variable.fields);
}
}
setTypeSpecificInfo(type, name, &variable);
visitVariable(&variable);
ASSERT(output);
output->push_back(variable);
}
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
}

View File

@ -24,6 +24,8 @@ extern bool atof_clamp(const char *str, float *value);
// Return false if overflow happens.
extern bool atoi_clamp(const char *str, int *value);
class TSymbolTable;
namespace sh
{
@ -38,7 +40,7 @@ TString ArrayString(const TType &type);
class GetVariableTraverser
{
public:
GetVariableTraverser() {}
GetVariableTraverser(const TSymbolTable &symbolTable);
template <typename VarT>
void traverse(const TType &type, const TString &name, std::vector<VarT> *output);
@ -48,6 +50,14 @@ class GetVariableTraverser
virtual void visitVariable(ShaderVariable *newVar) {}
private:
// Helper function called by traverse() to fill specific fields
// for attributes/varyings/uniforms.
template <typename VarT>
void setTypeSpecificInfo(
const TType &type, const TString &name, VarT *variable) {}
const TSymbolTable &mSymbolTable;
DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser);
};

View File

@ -0,0 +1,40 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "libEGL/AttributeMap.h"
namespace egl
{
AttributeMap::AttributeMap()
{
}
AttributeMap::AttributeMap(const EGLint *attributes)
{
for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
{
insert(curAttrib[0], curAttrib[1]);
}
}
void AttributeMap::insert(EGLint key, EGLint value)
{
mAttributes[key] = value;
}
bool AttributeMap::contains(EGLint key) const
{
return (mAttributes.find(key) != mAttributes.end());
}
EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const
{
std::map<EGLint, EGLint>::const_iterator iter = mAttributes.find(key);
return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
}
}

View File

@ -0,0 +1,33 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef LIBEGL_ATTRIBUTEMAP_H_
#define LIBEGL_ATTRIBUTEMAP_H_
#include <EGL/egl.h>
#include <map>
namespace egl
{
class AttributeMap
{
public:
AttributeMap();
explicit AttributeMap(const EGLint *attributes);
virtual void insert(EGLint key, EGLint value);
virtual bool contains(EGLint key) const;
virtual EGLint get(EGLint key, EGLint defaultValue) const;
private:
std::map<EGLint, EGLint> mAttributes;
};
}
#endif // LIBEGL_ATTRIBUTEMAP_H_

View File

@ -35,32 +35,36 @@ static DisplayMap *GetDisplayMap()
return &displays;
}
egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType)
egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
{
Display *display = NULL;
DisplayMap *displays = GetDisplayMap();
DisplayMap::const_iterator iter = displays->find(displayId);
if (iter != displays->end())
{
return iter->second;
display = iter->second;
}
else
{
display = new egl::Display(displayId);
displays->insert(std::make_pair(displayId, display));
}
// FIXME: Check if displayId is a valid display device context
egl::Display *display = new egl::Display(displayId, displayType);
displays->insert(std::make_pair(displayId, display));
// Apply new attributes if the display is not initialized yet.
if (!display->isInitialized())
{
display->setAttributes(attribMap);
}
return display;
}
Display::Display(EGLNativeDisplayType displayId, EGLint displayType)
Display::Display(EGLNativeDisplayType displayId)
: mDisplayId(displayId),
mRequestedDisplayType(displayType),
mAttributeMap(),
mRenderer(NULL)
{
#if defined(ANGLE_PLATFORM_WINRT)
if (mDisplayId)
mDisplayId->AddRef();
#endif
}
Display::~Display()
@ -73,28 +77,29 @@ Display::~Display()
{
displays->erase(iter);
}
#if defined(ANGLE_PLATFORM_WINRT)
if (mDisplayId)
mDisplayId->Release();
#endif
}
bool Display::initialize()
void Display::setAttributes(const AttributeMap &attribMap)
{
mAttributeMap = attribMap;
}
Error Display::initialize()
{
if (isInitialized())
{
return true;
return Error(EGL_SUCCESS);
}
mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType);
mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap);
if (!mRenderer)
{
terminate();
return error(EGL_NOT_INITIALIZED, false);
return Error(EGL_NOT_INITIALIZED);
}
//TODO(jmadill): should be part of caps?
EGLint minSwapInterval = mRenderer->getMinSwapInterval();
EGLint maxSwapInterval = mRenderer->getMaxSwapInterval();
EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize;
@ -125,13 +130,13 @@ bool Display::initialize()
if (!isInitialized())
{
terminate();
return false;
return Error(EGL_NOT_INITIALIZED);
}
initDisplayExtensionString();
initVendorString();
return true;
return Error(EGL_SUCCESS);
}
void Display::terminate()
@ -148,6 +153,8 @@ void Display::terminate()
glDestroyRenderer(mRenderer);
mRenderer = NULL;
mConfigSet.mSet.clear();
}
bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
@ -202,7 +209,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)
Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface)
{
const Config *configuration = mConfigSet.get(config);
EGLint postSubBufferSupported = EGL_FALSE;
@ -223,9 +230,9 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
case EGL_BACK_BUFFER:
break;
case EGL_SINGLE_BUFFER:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
break;
case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
@ -241,11 +248,11 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
fixedSize = attribList[1];
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
attribList += 2;
@ -254,7 +261,7 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
if (width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
return Error(EGL_BAD_PARAMETER);
}
if (!fixedSize)
@ -265,29 +272,33 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
if (hasExistingWindowSurface(window))
{
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
return Error(EGL_BAD_ALLOC);
}
if (mRenderer->testDeviceLost(false))
{
if (!restoreLostDevice())
return EGL_NO_SURFACE;
Error error = restoreLostDevice();
if (error.isError())
{
return error;
}
}
Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported);
if (!surface->initialize())
Error error = surface->initialize();
if (error.isError())
{
delete surface;
return EGL_NO_SURFACE;
SafeDelete(surface);
return error;
}
mSurfaceSet.insert(surface);
return success(surface);
*outSurface = surface;
return Error(EGL_SUCCESS);
}
EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface)
{
EGLint width = 0, height = 0;
EGLenum textureFormat = EGL_NO_TEXTURE;
@ -319,7 +330,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
textureFormat = attribList[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
break;
case EGL_TEXTURE_TARGET:
@ -330,19 +341,19 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
textureTarget = attribList[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
break;
case EGL_MIPMAP_TEXTURE:
if (attribList[1] != EGL_FALSE)
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
attribList += 2;
@ -351,88 +362,100 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
if (width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
return Error(EGL_BAD_PARAMETER);
}
if (width == 0 || height == 0)
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
}
if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
(textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
}
if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
}
if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
(textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
if (mRenderer->testDeviceLost(false))
{
if (!restoreLostDevice())
return EGL_NO_SURFACE;
Error error = restoreLostDevice();
if (error.isError())
{
return error;
}
}
Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
if (!surface->initialize())
Error error = surface->initialize();
if (error.isError())
{
delete surface;
return EGL_NO_SURFACE;
SafeDelete(surface);
return error;
}
mSurfaceSet.insert(surface);
return success(surface);
*outSurface = surface;
return Error(EGL_SUCCESS);
}
EGLContext Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
bool robustAccess, EGLContext *outContext)
{
if (!mRenderer)
{
return EGL_NO_CONTEXT;
*outContext = EGL_NO_CONTEXT;
return Error(EGL_SUCCESS);
}
else if (mRenderer->testDeviceLost(false)) // Lost device
{
if (!restoreLostDevice())
Error error = restoreLostDevice();
if (error.isError())
{
return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
return error;
}
}
//TODO(jmadill): shader model is not cross-platform
if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4)
{
return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
return Error(EGL_BAD_CONFIG);
}
gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
mContextSet.insert(context);
return success(context);
*outContext = context;
return Error(EGL_SUCCESS);
}
bool Display::restoreLostDevice()
Error Display::restoreLostDevice()
{
for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
{
if ((*ctx)->isResetNotificationEnabled())
return false; // If reset notifications have been requested, application must delete all contexts first
{
// If reset notifications have been requested, application must delete all contexts first
return Error(EGL_CONTEXT_LOST);
}
}
// Release surface resources to make the Reset() succeed
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
@ -441,16 +464,20 @@ bool Display::restoreLostDevice()
if (!mRenderer->resetDevice())
{
return error(EGL_BAD_ALLOC, false);
return Error(EGL_BAD_ALLOC);
}
// Restore any surfaces that may have been lost
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
(*surface)->resetSwapChain();
Error error = (*surface)->resetSwapChain();
if (error.isError())
{
return error;
}
}
return true;
return Error(EGL_SUCCESS);
}
@ -472,7 +499,6 @@ void Display::notifyDeviceLost()
{
(*context)->markContextLost();
}
egl::error(EGL_CONTEXT_LOST);
}
void Display::recreateSwapChains()
@ -604,10 +630,11 @@ void Display::initVendorString()
LUID adapterLuid = {0};
//TODO(jmadill): LUID is not cross-platform
if (mRenderer && mRenderer->getLUID(&adapterLuid))
{
char adapterLuidString[64];
snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
mVendorString += adapterLuidString;
}

View File

@ -14,7 +14,9 @@
#include <set>
#include <vector>
#include "libEGL/Error.h"
#include "libEGL/Config.h"
#include "libEGL/AttributeMap.h"
namespace gl
{
@ -30,10 +32,10 @@ class Display
public:
~Display();
bool initialize();
Error initialize();
void terminate();
static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType);
static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
static const char *getExtensionString(egl::Display *display);
@ -43,9 +45,10 @@ class Display
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);
EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface);
Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface);
Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
bool robustAccess, EGLContext *outContext);
void destroySurface(egl::Surface *surface);
void destroyContext(gl::Context *context);
@ -64,18 +67,19 @@ class Display
const char *getExtensionString() const;
const char *getVendorString() const;
EGLNativeDisplayType getDisplayId() const { return mDisplayId; }
private:
DISALLOW_COPY_AND_ASSIGN(Display);
Display(EGLNativeDisplayType displayId, EGLint displayType);
Display(EGLNativeDisplayType displayId);
bool restoreLostDevice();
void setAttributes(const AttributeMap &attribMap);
Error restoreLostDevice();
EGLNativeDisplayType mDisplayId;
EGLint mRequestedDisplayType;
AttributeMap mAttributeMap;
typedef std::set<Surface*> SurfaceSet;
SurfaceSet mSurfaceSet;

48
src/3rdparty/angle/src/libEGL/Error.cpp vendored Normal file
View File

@ -0,0 +1,48 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Error.cpp: Implements the egl::Error class which encapsulates an EGL error
// and optional error message.
#include "libEGL/Error.h"
#include "common/angleutils.h"
#include <cstdarg>
namespace egl
{
Error::Error(EGLint errorCode)
: mCode(errorCode),
mMessage()
{
}
Error::Error(EGLint errorCode, const char *msg, ...)
: mCode(errorCode),
mMessage()
{
va_list vararg;
va_start(vararg, msg);
mMessage = FormatString(msg, vararg);
va_end(vararg);
}
Error::Error(const Error &other)
: mCode(other.mCode),
mMessage(other.mMessage)
{
}
Error &Error::operator=(const Error &other)
{
mCode = other.mCode;
mMessage = other.mMessage;
return *this;
}
}

39
src/3rdparty/angle/src/libEGL/Error.h vendored Normal file
View File

@ -0,0 +1,39 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Error.h: Defines the egl::Error class which encapsulates an EGL error
// and optional error message.
#ifndef LIBEGL_ERROR_H_
#define LIBEGL_ERROR_H_
#include <EGL/egl.h>
#include <string>
namespace egl
{
class Error
{
public:
explicit Error(EGLint errorCode);
Error(EGLint errorCode, const char *msg, ...);
Error(const Error &other);
Error &operator=(const Error &other);
EGLint getCode() const { return mCode; }
bool isError() const { return (mCode != EGL_SUCCESS); }
const std::string &getMessage() const { return mMessage; }
private:
EGLint mCode;
std::string mMessage;
};
}
#endif // LIBEGL_ERROR_H_

View File

@ -22,23 +22,19 @@
#include "libEGL/main.h"
#include "libEGL/Display.h"
#if defined(ANGLE_PLATFORM_WINRT)
# include "wrl.h"
# include "windows.graphics.display.h"
# include "windows.ui.core.h"
using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::Core;
using namespace Microsoft::WRL;
#endif
#include "common/NativeWindow.h"
//TODO(jmadill): phase this out
#include "libGLESv2/renderer/d3d/RendererD3D.h"
namespace egl
{
Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported)
{
mRenderer = mDisplay->getRenderer();
//TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
mSwapChain = NULL;
mShareHandle = NULL;
mTexture = NULL;
@ -51,27 +47,19 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
mSwapInterval = -1;
mWidth = width;
mHeight = height;
mFixedWidth = mWidth;
mFixedHeight = mHeight;
setSwapInterval(1);
mFixedSize = fixedSize;
mSwapFlags = rx::SWAP_NORMAL;
#if defined(ANGLE_PLATFORM_WINRT)
if (mWindow)
mWindow->AddRef();
mScaleFactor = 1.0;
mSizeToken.value = 0;
mDpiToken.value = 0;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
mOrientationToken.value = 0;
# endif
#endif
subclassWindow();
}
Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
: mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
: mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
mRenderer = mDisplay->getRenderer();
//TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
mSwapChain = NULL;
mWindowSubclassed = false;
mTexture = NULL;
@ -85,90 +73,33 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
setSwapInterval(1);
// This constructor is for offscreen surfaces, which are always fixed-size.
mFixedSize = EGL_TRUE;
mSwapFlags = rx::SWAP_NORMAL;
#if defined(ANGLE_PLATFORM_WINRT)
mScaleFactor = 1.0;
mSizeToken.value = 0;
mDpiToken.value = 0;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
mOrientationToken.value = 0;
# endif
#endif
mFixedWidth = mWidth;
mFixedHeight = mHeight;
}
Surface::~Surface()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (mSizeToken.value) {
ComPtr<ICoreWindow> coreWindow;
HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = coreWindow->remove_SizeChanged(mSizeToken);
ASSERT(SUCCEEDED(hr));
}
if (mDpiToken.value) {
ComPtr<IDisplayInformation> displayInformation;
HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = displayInformation->remove_DpiChanged(mDpiToken);
ASSERT(SUCCEEDED(hr));
}
# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
if (mOrientationToken.value) {
ComPtr<IDisplayInformation> displayInformation;
HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = displayInformation->remove_OrientationChanged(mOrientationToken);
ASSERT(SUCCEEDED(hr));
}
# endif
#endif
unsubclassWindow();
release();
}
bool Surface::initialize()
Error Surface::initialize()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (!mFixedSize) {
HRESULT hr;
ComPtr<IDisplayInformation> displayInformation;
hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
ASSERT(SUCCEEDED(hr));
onDpiChanged(displayInformation.Get(), 0);
hr = displayInformation->add_DpiChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onDpiChanged).Get(),
&mDpiToken);
ASSERT(SUCCEEDED(hr));
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
onOrientationChanged(displayInformation.Get(), 0);
hr = displayInformation->add_OrientationChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onOrientationChanged).Get(),
&mOrientationToken);
ASSERT(SUCCEEDED(hr));
# endif
ComPtr<ICoreWindow> coreWindow;
hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
ASSERT(SUCCEEDED(hr));
Rect rect;
hr = coreWindow->get_Bounds(&rect);
ASSERT(SUCCEEDED(hr));
mWidth = rect.Width * mScaleFactor;
mHeight = rect.Height * mScaleFactor;
hr = coreWindow->add_SizeChanged(Callback<ITypedEventHandler<CoreWindow *, WindowSizeChangedEventArgs *>>(this, &Surface::onSizeChanged).Get(),
&mSizeToken);
ASSERT(SUCCEEDED(hr));
if (mNativeWindow.getNativeWindow())
{
if (!mNativeWindow.initialize())
{
return Error(EGL_BAD_SURFACE);
}
}
#endif
if (!resetSwapChain())
return false;
Error error = resetSwapChain();
if (error.isError())
{
return error;
}
return true;
return Error(EGL_SUCCESS);
}
void Surface::release()
@ -181,85 +112,80 @@ void Surface::release()
mTexture->releaseTexImage();
mTexture = NULL;
}
#if defined(ANGLE_PLATFORM_WINRT)
if (mWindow)
mWindow->Release();
#endif
}
bool Surface::resetSwapChain()
Error Surface::resetSwapChain()
{
ASSERT(!mSwapChain);
int width;
int height;
#if !defined(ANGLE_PLATFORM_WINRT)
if (!mFixedSize)
{
RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect))
if (!mNativeWindow.getClientRect(&windowRect))
{
ASSERT(false);
ERR("Could not retrieve the window dimensions");
return error(EGL_BAD_SURFACE, false);
return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
}
width = windowRect.right - windowRect.left;
height = windowRect.bottom - windowRect.top;
}
else
#endif
{
// non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
}
mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle,
mConfig->mRenderTargetFormat,
mConfig->mDepthStencilFormat);
if (!mSwapChain)
{
return error(EGL_BAD_ALLOC, false);
return Error(EGL_BAD_ALLOC);
}
if (!resetSwapChain(width, height))
Error error = resetSwapChain(width, height);
if (error.isError())
{
delete mSwapChain;
mSwapChain = NULL;
return false;
SafeDelete(mSwapChain);
return error;
}
return true;
return Error(EGL_SUCCESS);
}
bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
backbufferWidth = std::max(1, backbufferWidth);
backbufferHeight = std::max(1, backbufferHeight);
#endif
EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
if (status == EGL_CONTEXT_LOST)
{
mDisplay->notifyDeviceLost();
return false;
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return error(status, false);
return Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
return true;
return Error(EGL_SUCCESS);
}
bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
@ -269,69 +195,71 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
if (status == EGL_CONTEXT_LOST)
{
mRenderer->notifyDeviceLost();
return false;
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return error(status, false);
return Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
mSwapIntervalDirty = false;
return true;
return Error(EGL_SUCCESS);
}
bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mSwapChain)
{
return true;
return Error(EGL_SUCCESS);
}
if (x + width > mWidth)
if (x + width > abs(mWidth))
{
width = mWidth - x;
width = abs(mWidth) - x;
}
if (y + height > mHeight)
if (y + height > abs(mHeight))
{
height = mHeight - y;
height = abs(mHeight) - y;
}
if (width == 0 || height == 0)
{
return true;
return Error(EGL_SUCCESS);
}
EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags);
ASSERT(width > 0);
ASSERT(height > 0);
EGLint status = mSwapChain->swapRect(x, y, width, height);
if (status == EGL_CONTEXT_LOST)
{
mRenderer->notifyDeviceLost();
return false;
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return error(status, false);
return Error(status);
}
checkForOutOfDateSwapChain();
return true;
return Error(EGL_SUCCESS);
}
EGLNativeWindowType Surface::getWindowHandle()
{
return mWindow;
return mNativeWindow.getNativeWindow();
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
#if !defined(ANGLE_PLATFORM_WINRT)
static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
if (message == WM_SIZE)
@ -349,45 +277,50 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam
void Surface::subclassWindow()
{
#if !defined(ANGLE_PLATFORM_WINRT)
if (!mWindow)
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
DWORD processId;
DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
DWORD threadId = GetWindowThreadProcessId(window, &processId);
if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
{
return;
}
SetLastError(0);
LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
{
mWindowSubclassed = false;
return;
}
SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
mWindowSubclassed = true;
#else
mWindowSubclassed = false;
#endif
}
void Surface::unsubclassWindow()
{
#if !defined(ANGLE_PLATFORM_WINRT)
if(!mWindowSubclassed)
{
return;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
// un-subclass
LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
// Check the windowproc is still SurfaceWindowProc.
// If this assert fails, then it is likely the application has subclassed the
@ -396,29 +329,28 @@ void Surface::unsubclassWindow()
// EGL context, or to unsubclass before destroying the EGL context.
if(parentWndFunc)
{
LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
UNUSED_ASSERTION_VARIABLE(prevWndFunc);
ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
}
RemoveProp(mWindow, kSurfaceProperty);
RemoveProp(mWindow, kParentWndProc);
mWindowSubclassed = false;
RemoveProp(window, kSurfaceProperty);
RemoveProp(window, kParentWndProc);
#endif
mWindowSubclassed = false;
}
bool Surface::checkForOutOfDateSwapChain()
{
RECT client;
int clientWidth = getWidth();
int clientHeight = getHeight();
bool sizeDirty = false;
#if !defined(ANGLE_PLATFORM_WINRT)
if (!mFixedSize && !IsIconic(getWindowHandle()))
if (!mFixedSize && !mNativeWindow.isIconic())
{
RECT client;
// The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
// because that's not a useful size to render to.
if (!GetClientRect(getWindowHandle(), &client))
if (!mNativeWindow.getClientRect(&client))
{
ASSERT(false);
return false;
@ -429,7 +361,13 @@ bool Surface::checkForOutOfDateSwapChain()
clientHeight = client.bottom - client.top;
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
}
#endif
if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight))
{
clientWidth = mFixedWidth;
clientHeight = mFixedHeight;
sizeDirty = true;
}
bool wasDirty = (mSwapIntervalDirty || sizeDirty);
@ -455,17 +393,17 @@ bool Surface::checkForOutOfDateSwapChain()
return false;
}
bool Surface::swap()
Error Surface::swap()
{
return swapRect(0, 0, mWidth, mHeight);
return swapRect(0, 0, abs(mWidth), abs(mHeight));
}
bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mPostSubBufferSupported)
{
// Spec is not clear about how this should be handled.
return true;
return Error(EGL_SUCCESS);
}
return swapRect(x, y, width, height);
@ -550,77 +488,18 @@ EGLint Surface::isFixedSize() const
return mFixedSize;
}
void Surface::setFixedWidth(EGLint width)
{
mFixedWidth = width;
}
void Surface::setFixedHeight(EGLint height)
{
mFixedHeight = height;
}
EGLenum Surface::getFormat() const
{
return mConfig->mRenderTargetFormat;
}
#if defined(ANGLE_PLATFORM_WINRT)
HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
{
HRESULT hr;
Size size;
hr = args->get_Size(&size);
ASSERT(SUCCEEDED(hr));
resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5),
std::floor(size.Height * mScaleFactor + 0.5));
if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
{
glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
}
return S_OK;
}
HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *)
{
HRESULT hr;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
ComPtr<IDisplayInformation2> displayInformation2;
hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
ASSERT(SUCCEEDED(hr));
# else
ResolutionScale resolutionScale;
hr = displayInformation->get_ResolutionScale(&resolutionScale);
ASSERT(SUCCEEDED(hr));
mScaleFactor = double(resolutionScale) / 100.0;
# endif
return S_OK;
}
# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *)
{
HRESULT hr;
DisplayOrientations orientation;
hr = displayInformation->get_CurrentOrientation(&orientation);
ASSERT(SUCCEEDED(hr));
switch (orientation) {
default:
case DisplayOrientations_Portrait:
mSwapFlags = rx::SWAP_NORMAL;
break;
case DisplayOrientations_Landscape:
mSwapFlags = rx::SWAP_ROTATE_90;
break;
case DisplayOrientations_LandscapeFlipped:
mSwapFlags = rx::SWAP_ROTATE_270;
break;
case DisplayOrientations_PortraitFlipped:
mSwapFlags = rx::SWAP_ROTATE_180;
break;
}
return S_OK;
}
# endif
#endif
}

View File

@ -11,23 +11,12 @@
#ifndef LIBEGL_SURFACE_H_
#define LIBEGL_SURFACE_H_
#include "libEGL/Error.h"
#include <EGL/egl.h>
#include "common/angleutils.h"
#if defined(ANGLE_PLATFORM_WINRT)
#include <EventToken.h>
namespace ABI { namespace Windows {
namespace UI { namespace Core {
struct ICoreWindow;
struct IWindowSizeChangedEventArgs;
} }
namespace Graphics { namespace Display {
struct IDisplayInformation;
} }
} }
struct IInspectable;
#endif
#include "common/NativeWindow.h"
namespace gl
{
@ -35,8 +24,8 @@ class Texture2D;
}
namespace rx
{
class Renderer;
class SwapChain;
class RendererD3D; //TODO(jmadill): remove this
}
namespace egl
@ -52,13 +41,13 @@ class Surface
virtual ~Surface();
bool initialize();
Error initialize();
void release();
bool resetSwapChain();
Error resetSwapChain();
EGLNativeWindowType getWindowHandle();
bool swap();
bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
Error swap();
Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
virtual EGLint isPostSubBufferSupported() const;
@ -81,35 +70,31 @@ class Surface
virtual gl::Texture2D *getBoundTexture() const;
EGLint isFixedSize() const;
void setFixedWidth(EGLint width);
void setFixedHeight(EGLint height);
private:
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
#if defined(ANGLE_PLATFORM_WINRT)
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
# endif
#endif
Display *const mDisplay;
rx::Renderer *mRenderer;
rx::RendererD3D *mRenderer;
HANDLE mShareHandle;
rx::SwapChain *mSwapChain;
void subclassWindow();
void unsubclassWindow();
bool resizeSwapChain(int backbufferWidth, int backbufferHeight);
bool resetSwapChain(int backbufferWidth, int backbufferHeight);
bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
Error resetSwapChain(int backbufferWidth, int backbufferHeight);
Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
const EGLNativeWindowType mWindow; // Window that the surface is created for.
rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
const egl::Config *mConfig; // EGL config surface was created with
EGLint mHeight; // Height of surface
EGLint mWidth; // Width of surface
EGLint mFixedHeight; // Pending height of the surface
EGLint mFixedWidth; // Pending width of the surface
// EGLint horizontalResolution; // Horizontal dot pitch
// EGLint verticalResolution; // Vertical dot pitch
// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
@ -126,18 +111,9 @@ private:
EGLint mSwapInterval;
EGLint mPostSubBufferSupported;
EGLint mFixedSize;
EGLint mSwapFlags;
bool mSwapIntervalDirty;
gl::Texture2D *mTexture;
#if defined(ANGLE_PLATFORM_WINRT)
double mScaleFactor;
EventRegistrationToken mSizeToken;
EventRegistrationToken mDpiToken;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
EventRegistrationToken mOrientationToken;
# endif
#endif
};
}

View File

@ -13,7 +13,6 @@
#include "common/debug.h"
#include "common/version.h"
#include "common/platform.h"
#include "libGLESv2/Context.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/main.h"
@ -26,16 +25,20 @@
#include "libEGL/Display.h"
#include "libEGL/Surface.h"
#include "common/NativeWindow.h"
bool validateDisplay(egl::Display *display)
{
if (display == EGL_NO_DISPLAY)
{
return egl::error(EGL_BAD_DISPLAY, false);
recordError(egl::Error(EGL_BAD_DISPLAY));
return false;
}
if (!display->isInitialized())
{
return egl::error(EGL_NOT_INITIALIZED, false);
recordError(egl::Error(EGL_NOT_INITIALIZED));
return false;
}
return true;
@ -50,7 +53,8 @@ bool validateConfig(egl::Display *display, EGLConfig config)
if (!display->isValidConfig(config))
{
return egl::error(EGL_BAD_CONFIG, false);
recordError(egl::Error(EGL_BAD_CONFIG));
return false;
}
return true;
@ -65,7 +69,8 @@ bool validateContext(egl::Display *display, gl::Context *context)
if (!display->isValidContext(context))
{
return egl::error(EGL_BAD_CONTEXT, false);
recordError(egl::Error(EGL_BAD_CONTEXT));
return false;
}
return true;
@ -80,7 +85,8 @@ bool validateSurface(egl::Display *display, egl::Surface *surface)
if (!display->isValidSurface(surface))
{
return egl::error(EGL_BAD_SURFACE, false);
recordError(egl::Error(EGL_BAD_SURFACE));
return false;
}
return true;
@ -93,12 +99,7 @@ EGLint __stdcall eglGetError(void)
EVENT("()");
EGLint error = egl::getCurrentError();
if (error != EGL_SUCCESS)
{
egl::setCurrentError(EGL_SUCCESS);
}
recordError(egl::Error(EGL_SUCCESS));
return error;
}
@ -106,7 +107,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
{
EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
return egl::Display::getDisplay(display_id, egl::AttributeMap());
}
EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
@ -120,19 +121,26 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
break;
default:
return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY);
recordError(egl::Error(EGL_BAD_CONFIG));
return EGL_NO_DISPLAY;
}
EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
#if !defined(ANGLE_PLATFORM_WINRT)
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
// Validate the display device context
if (WindowFromDC(displayId) == NULL)
{
return egl::success(EGL_NO_DISPLAY);
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
#endif
EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
bool majorVersionSpecified = false;
bool minorVersionSpecified = false;
bool requestedWARP = false;
if (attrib_list)
{
for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
@ -140,7 +148,69 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
switch (curAttrib[0])
{
case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
requestedDisplayType = curAttrib[1];
switch (curAttrib[1])
{
case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
break;
case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
if (!egl::Display::supportsPlatformD3D())
{
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
break;
case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
if (!egl::Display::supportsPlatformOpenGL())
{
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
break;
default:
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
platformType = curAttrib[1];
break;
case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
if (curAttrib[1] != EGL_DONT_CARE)
{
majorVersionSpecified = true;
}
break;
case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
if (curAttrib[1] != EGL_DONT_CARE)
{
minorVersionSpecified = true;
}
break;
case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE:
if (!egl::Display::supportsPlatformD3D())
{
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
switch (curAttrib[1])
{
case EGL_FALSE:
case EGL_TRUE:
break;
default:
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
requestedWARP = (curAttrib[1] == EGL_TRUE);
break;
default:
@ -149,33 +219,20 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
}
}
switch (requestedDisplayType)
if (!majorVersionSpecified && minorVersionSpecified)
{
case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
break;
case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE:
if (!egl::Display::supportsPlatformD3D())
{
return egl::success(EGL_NO_DISPLAY);
}
break;
case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
if (!egl::Display::supportsPlatformOpenGL())
{
return egl::success(EGL_NO_DISPLAY);
}
break;
default:
return egl::success(EGL_NO_DISPLAY);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_DISPLAY;
}
return egl::Display::getDisplay(displayId, requestedDisplayType);
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));
}
EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
@ -185,20 +242,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
if (dpy == EGL_NO_DISPLAY)
{
return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
recordError(egl::Error(EGL_BAD_DISPLAY));
return EGL_FALSE;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!display->initialize())
egl::Error error = display->initialize();
if (error.isError())
{
return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
recordError(error);
return EGL_FALSE;
}
if (major) *major = 1;
if (minor) *minor = 4;
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
@ -207,14 +268,16 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
if (dpy == EGL_NO_DISPLAY)
{
return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
recordError(egl::Error(EGL_BAD_DISPLAY));
return EGL_FALSE;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
display->terminate();
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
@ -227,19 +290,28 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
return NULL;
}
const char *result;
switch (name)
{
case EGL_CLIENT_APIS:
return egl::success("OpenGL_ES");
result = "OpenGL_ES";
break;
case EGL_EXTENSIONS:
return egl::success(egl::Display::getExtensionString(display));
result = egl::Display::getExtensionString(display);
break;
case EGL_VENDOR:
return egl::success(display->getVendorString());
result = display->getVendorString();
break;
case EGL_VERSION:
return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")");
result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
break;
default:
return egl::error(EGL_BAD_PARAMETER, (const char*)NULL);
recordError(egl::Error(EGL_BAD_PARAMETER));
return NULL;
}
recordError(egl::Error(EGL_SUCCESS));
return result;
}
EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
@ -257,17 +329,20 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co
if (!num_config)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
const EGLint attribList[] = {EGL_NONE};
if (!display->getConfigs(configs, attribList, config_size, num_config))
{
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
@ -285,7 +360,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
if (!num_config)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
const EGLint attribList[] = {EGL_NONE};
@ -297,7 +373,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
display->getConfigs(configs, attrib_list, config_size, num_config);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
@ -314,10 +391,12 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
if (!display->getConfigAttrib(config, attribute, value))
{
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
@ -332,16 +411,21 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
return EGL_NO_SURFACE;
}
#if !defined(ANGLE_PLATFORM_WINRT)
HWND window = (HWND)win;
if (!IsWindow(window))
if (!rx::IsValidEGLNativeWindowType(win))
{
return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
recordError(egl::Error(EGL_BAD_NATIVE_WINDOW));
return EGL_NO_SURFACE;
}
#endif
return display->createWindowSurface(win, config, attrib_list);
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;
}
EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
@ -356,7 +440,15 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
return EGL_NO_SURFACE;
}
return display->createOffscreenSurface(config, NULL, attrib_list);
EGLSurface surface = EGL_NO_SURFACE;
egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface);
if (error.isError())
{
recordError(error);
return EGL_NO_SURFACE;
}
return surface;
}
EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
@ -373,7 +465,8 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG
UNIMPLEMENTED(); // FIXME
return egl::success(EGL_NO_SURFACE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_SURFACE;
}
EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
@ -390,12 +483,14 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
display->destroySurface((egl::Surface*)surface);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
@ -413,7 +508,8 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
switch (attribute)
@ -473,10 +569,12 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
*value = eglSurface->isFixedSize();
break;
default:
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
@ -498,7 +596,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
rx::SwapChain *swapchain = eglSurface->getSwapChain();
@ -522,7 +621,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
if (renderer->getMajorShaderModel() < 4)
{
return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
recordError(egl::Error(EGL_BAD_CONTEXT));
return EGL_FALSE;
}
*value = static_cast<rx::Renderer11*>(renderer)->getDevice();
@ -530,10 +630,12 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
break;
#endif
default:
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglBindAPI(EGLenum api)
@ -544,16 +646,19 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api)
{
case EGL_OPENGL_API:
case EGL_OPENVG_API:
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE; // Not supported by this implementation
case EGL_OPENGL_ES_API:
break;
default:
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
egl::setCurrentAPI(api);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLenum __stdcall eglQueryAPI(void)
@ -562,7 +667,8 @@ EGLenum __stdcall eglQueryAPI(void)
EGLenum API = egl::getCurrentAPI();
return egl::success(API);
recordError(egl::Error(EGL_SUCCESS));
return API;
}
EGLBoolean __stdcall eglWaitClient(void)
@ -571,7 +677,8 @@ EGLBoolean __stdcall eglWaitClient(void)
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglReleaseThread(void)
@ -580,7 +687,8 @@ EGLBoolean __stdcall eglReleaseThread(void)
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
@ -598,10 +706,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu
if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
{
return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_NO_SURFACE;
}
return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
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;
}
EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
@ -617,9 +734,30 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint
return EGL_FALSE;
}
switch (attribute)
{
case EGL_WIDTH:
if (!eglSurface->isFixedSize() || !value) {
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
eglSurface->setFixedWidth(value);
return EGL_TRUE;
case EGL_HEIGHT:
if (!eglSurface->isFixedSize() || !value) {
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
eglSurface->setFixedHeight(value);
return EGL_TRUE;
default:
break;
}
UNIMPLEMENTED(); // FIXME
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@ -636,30 +774,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
if (buffer != EGL_BACK_BUFFER)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->getBoundTexture())
{
return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ACCESS));
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
if (!glBindTexImage(eglSurface))
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@ -676,17 +820,20 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
if (buffer != EGL_BACK_BUFFER)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
gl::Texture2D *texture = eglSurface->getBoundTexture();
@ -696,7 +843,8 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
texture->releaseTexImage();
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
@ -714,12 +862,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
if (draw_surface == NULL)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
draw_surface->setSwapInterval(interval);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
@ -744,27 +894,38 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
if (attribute[1] == EGL_TRUE)
{
return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented
recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented
return EGL_NO_CONTEXT;
// robust_access = true;
}
else if (attribute[1] != EGL_FALSE)
return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
{
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
break;
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
{
reset_notification = true;
}
else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
{
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
break;
default:
return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
}
}
if (client_version != 2 && client_version != 3)
{
return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_CONFIG));
return EGL_NO_CONTEXT;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
@ -775,18 +936,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
{
return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_NO_CONTEXT;
}
if (sharedGLContext->getClientVersion() != client_version)
{
return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_CONTEXT));
return EGL_NO_CONTEXT;
}
// Can not share contexts between displays
if (sharedGLContext->getRenderer() != display->getRenderer())
{
return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_NO_CONTEXT;
}
}
@ -795,7 +959,16 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
return EGL_NO_CONTEXT;
}
return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
EGLContext context = EGL_NO_CONTEXT;
egl::Error error = display->createContext(config, client_version, static_cast<gl::Context*>(share_context),
reset_notification, robust_access, &context);
if (error.isError())
{
recordError(error);
return EGL_NO_CONTEXT;
}
return context;
}
EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
@ -812,12 +985,14 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
if (ctx == EGL_NO_CONTEXT)
{
return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
recordError(egl::Error(EGL_BAD_CONTEXT));
return EGL_FALSE;
}
display->destroyContext(context);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
@ -832,7 +1007,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE);
if (noContext != noSurface)
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
@ -850,7 +1026,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
if (renderer->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
}
@ -871,7 +1048,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLContext __stdcall eglGetCurrentContext(void)
@ -880,7 +1058,8 @@ EGLContext __stdcall eglGetCurrentContext(void)
EGLContext context = glGetCurrentContext();
return egl::success(context);
recordError(egl::Error(EGL_SUCCESS));
return context;
}
EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
@ -889,17 +1068,18 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
if (readdraw == EGL_READ)
{
EGLSurface read = egl::getCurrentReadSurface();
return egl::success(read);
recordError(egl::Error(EGL_SUCCESS));
return egl::getCurrentReadSurface();
}
else if (readdraw == EGL_DRAW)
{
EGLSurface draw = egl::getCurrentDrawSurface();
return egl::success(draw);
recordError(egl::Error(EGL_SUCCESS));
return egl::getCurrentDrawSurface();
}
else
{
return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_NO_SURFACE;
}
}
@ -909,7 +1089,8 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void)
EGLDisplay dpy = egl::getCurrentDisplay();
return egl::success(dpy);
recordError(egl::Error(EGL_SUCCESS));
return dpy;
}
EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
@ -927,7 +1108,8 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglWaitGL(void)
@ -936,7 +1118,8 @@ EGLBoolean __stdcall eglWaitGL(void)
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglWaitNative(EGLint engine)
@ -945,7 +1128,8 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine)
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
@ -962,20 +1146,25 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
if (display->getRenderer()->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->swap())
egl::Error error = eglSurface->swap();
if (error.isError())
{
return egl::success(EGL_TRUE);
recordError(error);
return EGL_FALSE;
}
return EGL_FALSE;
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
@ -992,12 +1181,14 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ
if (display->getRenderer()->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
@ -1006,7 +1197,8 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
if (x < 0 || y < 0 || width < 0 || height < 0)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
@ -1019,20 +1211,25 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
if (display->getRenderer()->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->postSubBuffer(x, y, width, height))
egl::Error error = eglSurface->postSubBuffer(x, y, width, height);
if (error.isError())
{
return egl::success(EGL_TRUE);
recordError(error);
return EGL_FALSE;
}
return EGL_FALSE;
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)

View File

@ -11,9 +11,6 @@
#include "common/debug.h"
#include "common/tls.h"
#if defined(ANGLE_PLATFORM_WINRT)
__declspec(thread)
#endif
static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
namespace egl
@ -21,12 +18,6 @@ namespace egl
Current *AllocateCurrent()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (currentTLS == TLS_OUT_OF_INDEXES)
{
currentTLS = CreateTLSIndex();
}
#endif
ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
if (currentTLS == TLS_OUT_OF_INDEXES)
{
@ -51,12 +42,6 @@ Current *AllocateCurrent()
void DeallocateCurrent()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (currentTLS == TLS_OUT_OF_INDEXES)
{
return;
}
#endif
Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
SafeDelete(current);
SetTLSValue(currentTLS, NULL);
@ -72,7 +57,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
{
case DLL_PROCESS_ATTACH:
{
#if defined(ANGLE_ENABLE_TRACE)
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
if (debug)
@ -87,15 +72,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
}
#endif
#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
return DisableThreadLibraryCalls(instance);
#endif
currentTLS = CreateTLSIndex();
if (currentTLS == TLS_OUT_OF_INDEXES)
{
return FALSE;
}
#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
gl::InitializeDebugAnnotations();
#endif
}
// Fall through to initialize index
case DLL_THREAD_ATTACH:
@ -105,15 +90,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
break;
case DLL_THREAD_DETACH:
{
#if !defined(ANGLE_PLATFORM_WINRT)
egl::DeallocateCurrent();
#endif
}
break;
case DLL_PROCESS_DETACH:
{
egl::DeallocateCurrent();
DestroyTLSIndex(currentTLS);
#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
gl::UninitializeDebugAnnotations();
#endif
}
break;
default:
@ -143,11 +130,11 @@ Current *GetCurrentData()
#endif
}
void setCurrentError(EGLint error)
void recordError(const Error &error)
{
Current *current = GetCurrentData();
current->error = error;
current->error = error.getCode();
}
EGLint getCurrentError()
@ -213,9 +200,4 @@ EGLSurface getCurrentReadSurface()
return current->readSurface;
}
void error(EGLint errorCode)
{
egl::setCurrentError(errorCode);
}
}

View File

@ -9,6 +9,8 @@
#ifndef LIBEGL_MAIN_H_
#define LIBEGL_MAIN_H_
#include "libEGL/Error.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@ -23,7 +25,7 @@ struct Current
EGLSurface readSurface;
};
void setCurrentError(EGLint error);
void recordError(const Error &error);
EGLint getCurrentError();
void setCurrentAPI(EGLenum API);
@ -38,24 +40,6 @@ EGLSurface getCurrentDrawSurface();
void setCurrentReadSurface(EGLSurface surface);
EGLSurface getCurrentReadSurface();
void error(EGLint errorCode);
template<class T>
const T &error(EGLint errorCode, const T &returnValue)
{
error(errorCode);
return returnValue;
}
template<class T>
const T &success(const T &returnValue)
{
egl::setCurrentError(EGL_SUCCESS);
return returnValue;
}
}
#endif // LIBEGL_MAIN_H_

View File

@ -15,6 +15,7 @@
#include <cstddef>
#include <string>
#include <vector>
#include <stdint.h>
namespace gl
{
@ -26,7 +27,7 @@ class BinaryInputStream
{
mError = false;
mOffset = 0;
mData = static_cast<const char*>(data);
mData = static_cast<const uint8_t*>(data);
mLength = length;
}
@ -85,7 +86,7 @@ class BinaryInputStream
return;
}
v->assign(mData + mOffset, length);
v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
mOffset += length;
}
@ -115,11 +116,16 @@ class BinaryInputStream
return mOffset == mLength;
}
const uint8_t *data()
{
return mData;
}
private:
DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
bool mError;
size_t mOffset;
const char *mData;
const uint8_t *mData;
size_t mLength;
template <typename T>

View File

@ -19,7 +19,6 @@
namespace rx
{
class Renderer;
class BufferImpl;
};

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,12 @@
#include "common/angleutils.h"
#include "common/RefCountObject.h"
#include "libGLESv2/Caps.h"
#include "libGLESv2/Constants.h"
#include "libGLESv2/Data.h"
#include "libGLESv2/Error.h"
#include "libGLESv2/HandleAllocator.h"
#include "libGLESv2/angletypes.h"
#include "libGLESv2/Constants.h"
#include "libGLESv2/VertexAttribute.h"
#include "libGLESv2/State.h"
#include "libGLESv2/angletypes.h"
#include "angle_gl.h"
@ -50,11 +50,6 @@ class Texture3D;
class Texture2DArray;
class Framebuffer;
class Renderbuffer;
class RenderbufferStorage;
class Colorbuffer;
class Depthbuffer;
class Stencilbuffer;
class DepthStencilbuffer;
class FenceNV;
class FenceSync;
class Query;
@ -68,7 +63,7 @@ class TransformFeedback;
class Context
{
public:
Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
virtual ~Context();
@ -86,7 +81,7 @@ class Context
GLuint createRenderbuffer();
GLuint createSampler();
GLuint createTransformFeedback();
GLsync createFenceSync(GLenum condition);
GLsync createFenceSync();
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
@ -115,7 +110,7 @@ class Context
void bindArrayBuffer(GLuint buffer);
void bindElementArrayBuffer(GLuint buffer);
void bindTexture(GLenum target, GLuint texture);
void bindTexture(GLenum target, GLuint handle);
void bindReadFramebuffer(GLuint framebuffer);
void bindDrawFramebuffer(GLuint framebuffer);
void bindRenderbuffer(GLuint renderbuffer);
@ -130,8 +125,8 @@ class Context
void bindPixelPackBuffer(GLuint buffer);
void bindPixelUnpackBuffer(GLuint buffer);
void useProgram(GLuint program);
void linkProgram(GLuint program);
void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
Error linkProgram(GLuint program);
Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
void bindTransformFeedback(GLuint transformFeedback);
Error beginQuery(GLenum target, GLuint query);
@ -139,8 +134,6 @@ class Context
void setFramebufferZero(Framebuffer *framebuffer);
void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
void setVertexAttribDivisor(GLuint index, GLuint divisor);
void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
@ -183,17 +176,17 @@ class Context
bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
Error clear(GLbitfield mask);
Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values);
Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values);
Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values);
Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil);
Error clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
Error clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values);
Error clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
Error clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
Error drawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei instances,
const rx::RangeUI &indexRange);
void sync(bool block); // flush/finish
Error sync(bool block); // flush/finish
void recordError(const Error &error);
@ -215,32 +208,21 @@ class Context
void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type);
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
rx::Renderer *getRenderer() { return mRenderer; }
State &getState() { return mState; }
const State &getState() const { return mState; }
Data getData() const;
void releaseShaderCompiler();
private:
DISALLOW_COPY_AND_ASSIGN(Context);
// TODO: std::array may become unavailable using older versions of GCC
typedef std::array<unsigned int, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
Error applyRenderTarget(GLenum drawMode, bool ignoreViewport);
Error applyState(GLenum drawMode);
Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive);
Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials,
size_t framebufferSerialCount);
Error applyTextures(ProgramBinary *programBinary);
Error applyUniformBuffers();
bool applyTransformFeedbackBuffers();
void markTransformFeedbackUsage();
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer);
@ -249,18 +231,9 @@ class Context
void detachTransformFeedback(GLuint transformFeedback);
void detachSampler(GLuint sampler);
Error generateSwizzles(ProgramBinary *programBinary, SamplerType type);
Error generateSwizzles(ProgramBinary *programBinary);
Texture *getIncompleteTexture(GLenum type);
bool skipDraw(GLenum drawMode);
void initRendererString();
void initExtensionStrings();
size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray);
void initCaps(GLuint clientVersion);
// Caps to use for validation
@ -273,7 +246,6 @@ class Context
int mClientVersion;
typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
TextureMap mZeroTextures;
TextureMap mIncompleteTextures;

View File

@ -0,0 +1,51 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Data.cpp: Container class for all GL relevant state, caps and objects
#include "libGLESv2/Data.h"
#include "libGLESv2/ResourceManager.h"
namespace gl
{
Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn,
const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn,
const ResourceManager *resourceManagerIn)
: clientVersion(clientVersionIn),
state(&stateIn),
caps(&capsIn),
textureCaps(&textureCapsIn),
extensions(&extensionsIn),
resourceManager(resourceManagerIn)
{}
Data::~Data()
{
}
Data::Data(const Data &other)
: clientVersion(other.clientVersion),
state(other.state),
caps(other.caps),
textureCaps(other.textureCaps),
extensions(other.extensions),
resourceManager(other.resourceManager)
{
}
Data &Data::operator=(const Data &other)
{
clientVersion = other.clientVersion;
state = other.state;
caps = other.caps;
textureCaps = other.textureCaps;
extensions = other.extensions;
resourceManager = other.resourceManager;
return *this;
}
}

38
src/3rdparty/angle/src/libGLESv2/Data.h vendored Normal file
View File

@ -0,0 +1,38 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Data.h: Container class for all GL relevant state, caps and objects
#ifndef LIBGLESV2_DATA_H_
#define LIBGLESV2_DATA_H_
#include "libGLESv2/State.h"
namespace gl
{
struct Data
{
public:
Data(GLint clientVersion, const State &state, const Caps &caps,
const TextureCapsMap &textureCaps, const Extensions &extensions,
const ResourceManager *resourceManager);
~Data();
Data(const Data &other);
Data &operator=(const Data &other);
GLint clientVersion;
const State *state;
const Caps *caps;
const TextureCapsMap *textureCaps;
const Extensions *extensions;
const ResourceManager *resourceManager;
};
}
#endif // LIBGLESV2_DATA_H_

View File

@ -4,191 +4,113 @@
// found in the LICENSE file.
//
// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
// Important note on accurate timers in Windows:
//
// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
// as timeGetTime on laptops and "jumping" during certain hardware events.
//
// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
//
// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
// from buggy implementations.
// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
// extension and GLES3 sync objects.
#include "libGLESv2/Fence.h"
#include "libGLESv2/renderer/FenceImpl.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/main.h"
#include "common/utilities.h"
#include "angle_gl.h"
namespace gl
{
FenceNV::FenceNV(rx::Renderer *renderer)
FenceNV::FenceNV(rx::FenceNVImpl *impl)
: mFence(impl),
mIsSet(false),
mStatus(GL_FALSE),
mCondition(GL_NONE)
{
mFence = renderer->createFence();
}
FenceNV::~FenceNV()
{
delete mFence;
SafeDelete(mFence);
}
GLboolean FenceNV::isFence() const
{
// GL_NV_fence spec:
// A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
return (mFence->isSet() ? GL_TRUE : GL_FALSE);
return (mIsSet ? GL_TRUE : GL_FALSE);
}
void FenceNV::setFence(GLenum condition)
Error FenceNV::setFence(GLenum condition)
{
mFence->set();
Error error = mFence->set();
if (error.isError())
{
return error;
}
mCondition = condition;
mStatus = GL_FALSE;
mIsSet = true;
return Error(GL_NO_ERROR);
}
GLboolean FenceNV::testFence()
Error FenceNV::testFence(GLboolean *outResult)
{
// Flush the command buffer by default
bool result = mFence->test(true);
mStatus = (result ? GL_TRUE : GL_FALSE);
return mStatus;
}
void FenceNV::finishFence()
{
ASSERT(mFence->isSet());
while (!mFence->test(true))
Error error = mFence->test(true, &mStatus);
if (error.isError())
{
Sleep(0);
return error;
}
*outResult = mStatus;
return Error(GL_NO_ERROR);
}
GLint FenceNV::getFencei(GLenum pname)
Error FenceNV::finishFence()
{
ASSERT(mFence->isSet());
ASSERT(mIsSet);
switch (pname)
{
case GL_FENCE_STATUS_NV:
{
// GL_NV_fence spec:
// Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
// or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
if (mStatus == GL_TRUE)
{
return GL_TRUE;
}
mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE);
return mStatus;
}
case GL_FENCE_CONDITION_NV:
return mCondition;
default: UNREACHABLE(); return 0;
}
return mFence->finishFence(&mStatus);
}
FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
: RefCountObject(id)
FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id)
: RefCountObject(id),
mFence(impl),
mCondition(GL_NONE)
{
mFence = renderer->createFence();
LARGE_INTEGER counterFreqency = { 0 };
BOOL success = QueryPerformanceFrequency(&counterFreqency);
UNUSED_ASSERTION_VARIABLE(success);
ASSERT(success);
mCounterFrequency = counterFreqency.QuadPart;
}
FenceSync::~FenceSync()
{
delete mFence;
SafeDelete(mFence);
}
void FenceSync::set(GLenum condition)
Error FenceSync::set(GLenum condition)
{
Error error = mFence->set();
if (error.isError())
{
return error;
}
mCondition = condition;
mFence->set();
return Error(GL_NO_ERROR);
}
GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
{
ASSERT(mFence->isSet());
bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
if (mFence->test(flushCommandBuffer))
{
return GL_ALREADY_SIGNALED;
}
if (mFence->hasError())
{
return GL_WAIT_FAILED;
}
if (timeout == 0)
{
return GL_TIMEOUT_EXPIRED;
}
LARGE_INTEGER currentCounter = { 0 };
BOOL success = QueryPerformanceCounter(&currentCounter);
UNUSED_ASSERTION_VARIABLE(success);
ASSERT(success);
LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer))
{
Sleep(0);
BOOL success = QueryPerformanceCounter(&currentCounter);
UNUSED_ASSERTION_VARIABLE(success);
ASSERT(success);
}
if (mFence->hasError())
{
return GL_WAIT_FAILED;
}
if (currentCounter.QuadPart >= endCounter)
{
return GL_TIMEOUT_EXPIRED;
}
return GL_CONDITION_SATISFIED;
ASSERT(mCondition != GL_NONE);
return mFence->clientWait(flags, timeout, outResult);
}
void FenceSync::serverWait()
Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
{
// Because our API is currently designed to be called from a single thread, we don't need to do
// extra work for a server-side fence. GPU commands issued after the fence is created will always
// be processed after the fence is signaled.
return mFence->serverWait(flags, timeout);
}
GLenum FenceSync::getStatus() const
Error FenceSync::getStatus(GLint *outResult) const
{
if (mFence->test(false))
{
// The spec does not specify any way to report errors during the status test (e.g. device lost)
// so we report the fence is unblocked in case of error or signaled.
return GL_SIGNALED;
}
return GL_UNSIGNALED;
return mFence->getStatus(outResult);
}
}

View File

@ -4,18 +4,21 @@
// found in the LICENSE file.
//
// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension.
// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
// extension and GLES3 sync objects.
#ifndef LIBGLESV2_FENCE_H_
#define LIBGLESV2_FENCE_H_
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
namespace rx
{
class Renderer;
class FenceImpl;
class FenceNVImpl;
class FenceSyncImpl;
}
namespace gl
@ -24,14 +27,13 @@ namespace gl
class FenceNV
{
public:
explicit FenceNV(rx::Renderer *renderer);
explicit FenceNV(rx::FenceNVImpl *impl);
virtual ~FenceNV();
GLboolean isFence() const;
void setFence(GLenum condition);
GLboolean testFence();
void finishFence();
GLint getFencei(GLenum pname);
Error setFence(GLenum condition);
Error testFence(GLboolean *outResult);
Error finishFence();
GLboolean getStatus() const { return mStatus; }
GLuint getCondition() const { return mCondition; }
@ -39,7 +41,9 @@ class FenceNV
private:
DISALLOW_COPY_AND_ASSIGN(FenceNV);
rx::FenceImpl *mFence;
rx::FenceNVImpl *mFence;
bool mIsSet;
GLboolean mStatus;
GLenum mCondition;
@ -48,21 +52,20 @@ class FenceNV
class FenceSync : public RefCountObject
{
public:
explicit FenceSync(rx::Renderer *renderer, GLuint id);
explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id);
virtual ~FenceSync();
void set(GLenum condition);
GLenum clientWait(GLbitfield flags, GLuint64 timeout);
void serverWait();
GLenum getStatus() const;
Error set(GLenum condition);
Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult);
Error serverWait(GLbitfield flags, GLuint64 timeout);
Error getStatus(GLint *outResult) const;
GLuint getCondition() const { return mCondition; }
private:
DISALLOW_COPY_AND_ASSIGN(FenceSync);
rx::FenceImpl *mFence;
LONGLONG mCounterFrequency;
rx::FenceSyncImpl *mFence;
GLenum mCondition;
};

View File

@ -16,13 +16,18 @@
#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/RenderTarget.h"
#include "libGLESv2/renderer/RenderbufferImpl.h"
#include "libGLESv2/renderer/Workarounds.h"
#include "libGLESv2/renderer/d3d/TextureD3D.h"
#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
#include "common/utilities.h"
namespace rx
{
RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
// TODO: Move these functions, and the D3D-specific header inclusions above,
// to FramebufferD3D.
gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT)
{
if (attachment->isTexture())
{
@ -31,14 +36,16 @@ RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
const gl::ImageIndex *index = attachment->getTextureImageIndex();
ASSERT(index);
return textureD3D->getRenderTarget(*index);
return textureD3D->getRenderTarget(*index, outRT);
}
else
{
gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
ASSERT(renderbuffer);
RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
*outRT = renderbufferD3D->getRenderTarget();
return gl::Error(GL_NO_ERROR);
}
gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
ASSERT(renderbuffer);
// TODO: cast to RenderbufferD3D
return renderbuffer->getStorage()->getRenderTarget();
}
// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
@ -56,9 +63,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
ASSERT(renderbuffer);
// TODO: cast to RenderbufferD3D
return renderbuffer->getStorage()->getSerial();
RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
return renderbufferD3D->getRenderTargetSerial();
}
}
@ -66,9 +72,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
namespace gl
{
Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
: mRenderer(renderer),
mId(id),
Framebuffer::Framebuffer(GLuint id)
: mId(id),
mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
mDepthbuffer(NULL),
mStencilbuffer(NULL)
@ -91,124 +96,6 @@ Framebuffer::~Framebuffer()
SafeDelete(mStencilbuffer);
}
FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
{
if (handle == 0)
{
return NULL;
}
gl::Context *context = gl::getContext();
switch (type)
{
case GL_NONE:
return NULL;
case GL_RENDERBUFFER:
return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
case GL_TEXTURE_2D:
{
Texture *texture = context->getTexture(handle);
if (texture && texture->getTarget() == GL_TEXTURE_2D)
{
return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
}
else
{
return NULL;
}
}
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{
Texture *texture = context->getTexture(handle);
if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
{
return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
}
else
{
return NULL;
}
}
case GL_TEXTURE_3D:
{
Texture *texture = context->getTexture(handle);
if (texture && texture->getTarget() == GL_TEXTURE_3D)
{
return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
}
else
{
return NULL;
}
}
case GL_TEXTURE_2D_ARRAY:
{
Texture *texture = context->getTexture(handle);
if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
{
return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
}
else
{
return NULL;
}
}
default:
UNREACHABLE();
return NULL;
}
}
void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
{
ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
SafeDelete(mColorbuffers[colorAttachment]);
GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
}
void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
{
SafeDelete(mDepthbuffer);
mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
}
void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
{
SafeDelete(mStencilbuffer);
mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
}
void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
{
FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
SafeDelete(mDepthbuffer);
SafeDelete(mStencilbuffer);
// ensure this is a legitimate depth+stencil format
if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
{
mDepthbuffer = attachment;
// Make a new attachment object to ensure we do not double-delete
// See angle issue 686
mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
}
}
void Framebuffer::detachTexture(GLuint textureId)
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
@ -382,14 +269,13 @@ bool Framebuffer::usingExtendedDrawBuffers() const
return false;
}
GLenum Framebuffer::completeness() const
GLenum Framebuffer::completeness(const gl::Data &data) const
{
int width = 0;
int height = 0;
unsigned int colorbufferSize = 0;
int samples = -1;
bool missingAttachment = true;
GLuint clientVersion = mRenderer->getCurrentClientVersion();
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
@ -403,8 +289,7 @@ GLenum Framebuffer::completeness() const
}
GLenum internalformat = colorbuffer->getInternalFormat();
// TODO(geofflang): use context's texture caps
const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
if (colorbuffer->isTexture())
{
@ -443,7 +328,7 @@ GLenum Framebuffer::completeness() const
// in GLES 2.0, all color attachments attachments must have the same number of bitplanes
// in GLES 3.0, there is no such restriction
if (clientVersion < 3)
if (data.clientVersion < 3)
{
if (formatInfo.pixelBytes != colorbufferSize)
{
@ -483,14 +368,12 @@ GLenum Framebuffer::completeness() const
}
GLenum internalformat = mDepthbuffer->getInternalFormat();
// TODO(geofflang): use context's texture caps
const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
if (mDepthbuffer->isTexture())
{
// depth texture attachments require OES/ANGLE_depth_texture
// TODO(geofflang): use context's extensions
if (!mRenderer->getRendererExtensions().depthTextures)
if (!data.extensions->depthTextures)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
@ -538,15 +421,13 @@ GLenum Framebuffer::completeness() const
}
GLenum internalformat = mStencilbuffer->getInternalFormat();
// TODO(geofflang): use context's texture caps
const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
if (mStencilbuffer->isTexture())
{
// texture stencil attachments come along as part
// of OES_packed_depth_stencil + OES/ANGLE_depth_texture
// TODO(geofflang): use context's extensions
if (!mRenderer->getRendererExtensions().depthTextures)
if (!data.extensions->depthTextures)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
@ -602,42 +483,44 @@ GLenum Framebuffer::completeness() const
return GL_FRAMEBUFFER_COMPLETE;
}
void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
{
GLuint maxDimension = caps.maxRenderbufferSize;
invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension);
}
void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
GLint x, GLint y, GLsizei width, GLsizei height)
Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
{
ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
{
GLenum attachmentTarget = attachments[attachIndex];
gl::FramebufferAttachment *attachment =
(attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
getAttachment(attachmentTarget);
FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer()
: getAttachment(attachmentTarget);
if (attachment)
{
rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
if (renderTarget)
rx::RenderTarget *renderTarget = NULL;
Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
if (error.isError())
{
renderTarget->invalidate(x, y, width, height);
return error;
}
renderTarget->invalidate(x, y, width, height);
}
}
return Error(GL_NO_ERROR);
}
DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
: Framebuffer(renderer, 0)
DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil)
: Framebuffer(0)
{
Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0);
mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0);
// Make a new attachment objects to ensure we do not double-delete
// See angle issue 686
@ -648,9 +531,9 @@ DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colo
mReadBufferState = GL_BACK;
}
int Framebuffer::getSamples() const
int Framebuffer::getSamples(const gl::Data &data) const
{
if (completeness() == GL_FRAMEBUFFER_COMPLETE)
if (completeness(data) == GL_FRAMEBUFFER_COMPLETE)
{
// for a complete framebuffer, all attachments must have the same sample count
// in this case return the first nonzero sample size
@ -675,7 +558,7 @@ bool Framebuffer::hasValidDepthStencil() const
mDepthbuffer->id() == mStencilbuffer->id());
}
ColorbufferInfo Framebuffer::getColorbuffersForRender() const
ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const
{
ColorbufferInfo colorbuffersForRender;
@ -689,18 +572,78 @@ ColorbufferInfo Framebuffer::getColorbuffersForRender() const
ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
colorbuffersForRender.push_back(colorbuffer);
}
#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED)
else
else if (!workarounds.mrtPerfWorkaround)
{
colorbuffersForRender.push_back(NULL);
}
#endif
}
return colorbuffersForRender;
}
GLenum DefaultFramebuffer::completeness() const
void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex)
{
setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex));
}
void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer)
{
setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer));
}
void Framebuffer::setNULLAttachment(GLenum attachment)
{
setAttachment(attachment, NULL);
}
void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj)
{
if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS))
{
size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0;
SafeDelete(mColorbuffers[colorAttachment]);
mColorbuffers[colorAttachment] = attachmentObj;
}
else if (attachment == GL_DEPTH_ATTACHMENT)
{
SafeDelete(mDepthbuffer);
mDepthbuffer = attachmentObj;
}
else if (attachment == GL_STENCIL_ATTACHMENT)
{
SafeDelete(mStencilbuffer);
mStencilbuffer = attachmentObj;
}
else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
{
SafeDelete(mDepthbuffer);
SafeDelete(mStencilbuffer);
// ensure this is a legitimate depth+stencil format
if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0)
{
mDepthbuffer = attachmentObj;
// Make a new attachment object to ensure we do not double-delete
// See angle issue 686
if (attachmentObj->isTexture())
{
mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(),
*attachmentObj->getTextureImageIndex());
}
else
{
mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer());
}
}
}
else
{
UNREACHABLE();
}
}
GLenum DefaultFramebuffer::completeness(const gl::Data &) const
{
// The default framebuffer *must* always be complete, though it may not be
// subject to the same rules as application FBOs. ie, it could have 0x0 size.

View File

@ -10,41 +10,44 @@
#ifndef LIBGLESV2_FRAMEBUFFER_H_
#define LIBGLESV2_FRAMEBUFFER_H_
#include <vector>
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
#include "constants.h"
#include "Constants.h"
#include <vector>
namespace rx
{
class Renderer;
class RenderbufferImpl;
struct Workarounds;
}
namespace gl
{
class FramebufferAttachment;
class Colorbuffer;
class Depthbuffer;
class Stencilbuffer;
class DepthStencilbuffer;
class Texture;
class Renderbuffer;
struct ImageIndex;
struct Caps;
struct Extensions;
class TextureCapsMap;
struct Data;
typedef std::vector<FramebufferAttachment *> ColorbufferInfo;
class Framebuffer
{
public:
Framebuffer(rx::Renderer *renderer, GLuint id);
Framebuffer(GLuint id);
virtual ~Framebuffer();
GLuint id() const { return mId; }
void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer);
void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer);
void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer);
void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer);
void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex);
void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer);
void setNULLAttachment(GLenum attachment);
void detachTexture(GLuint texture);
void detachRenderbuffer(GLuint renderbuffer);
@ -66,24 +69,21 @@ class Framebuffer
bool isEnabledColorAttachment(unsigned int colorAttachment) const;
bool hasEnabledColorAttachment() const;
bool hasStencil() const;
int getSamples() const;
int getSamples(const gl::Data &data) const;
bool usingExtendedDrawBuffers() const;
virtual GLenum completeness() const;
virtual GLenum completeness(const gl::Data &data) const;
bool hasValidDepthStencil() const;
void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
GLint x, GLint y, GLsizei width, GLsizei height);
Error invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
Error invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
// Use this method to retrieve the color buffer map when doing rendering.
// It will apply a workaround for poor shader performance on some systems
// by compacting the list to skip NULL values.
ColorbufferInfo getColorbuffersForRender() const;
ColorbufferInfo getColorbuffersForRender(const rx::Workarounds &workarounds) const;
protected:
rx::Renderer *mRenderer;
GLuint mId;
FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
@ -96,15 +96,15 @@ class Framebuffer
private:
DISALLOW_COPY_AND_ASSIGN(Framebuffer);
FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const;
void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj);
};
class DefaultFramebuffer : public Framebuffer
{
public:
DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil);
virtual GLenum completeness() const;
GLenum completeness(const gl::Data &data) const override;
virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
private:
@ -118,7 +118,7 @@ namespace rx
class RenderTarget;
// TODO: place this in FramebufferD3D.h
RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment);
gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT);
unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment);
}

View File

@ -187,7 +187,7 @@ GLenum RenderbufferAttachment::getActualFormat() const
GLsizei RenderbufferAttachment::getSamples() const
{
return mRenderbuffer->getStorage()->getSamples();
return mRenderbuffer->getSamples();
}
GLuint RenderbufferAttachment::id() const

View File

@ -16,13 +16,6 @@
#include "angle_gl.h"
namespace rx
{
class Renderer;
class RenderTarget;
class TextureStorage;
}
namespace gl
{
class Renderbuffer;

View File

@ -48,10 +48,101 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
}
ImageIndex ImageIndex::MakeInvalid()
{
return ImageIndex(GL_NONE, -1, -1);
}
ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
: type(typeIn),
mipIndex(mipIndexIn),
layerIndex(layerIndexIn)
{}
ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(GL_TEXTURE_2D, rx::Range<GLint>(minMip, maxMip),
rx::Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL);
}
ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(0, 6), NULL);
}
ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
GLint minLayer, GLint maxLayer)
{
return ImageIndexIterator(GL_TEXTURE_3D, rx::Range<GLint>(minMip, maxMip), rx::Range<GLint>(minLayer, maxLayer), NULL);
}
ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
const GLsizei *layerCounts)
{
return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range<GLint>(minMip, maxMip),
rx::Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts);
}
ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange,
const rx::Range<GLint> &layerRange, const GLsizei *layerCounts)
: mType(type),
mMipRange(mipRange),
mLayerRange(layerRange),
mLayerCounts(layerCounts),
mCurrentMip(mipRange.start),
mCurrentLayer(layerRange.start)
{}
GLint ImageIndexIterator::maxLayer() const
{
return (mLayerCounts ? static_cast<GLint>(mLayerCounts[mCurrentMip]) : mLayerRange.end);
}
ImageIndex ImageIndexIterator::next()
{
ASSERT(hasNext());
ImageIndex value = current();
// Iterate layers in the inner loop for now. We can add switchable
// layer or mip iteration if we need it.
if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL)
{
if (mCurrentLayer < maxLayer()-1)
{
mCurrentLayer++;
}
else if (mCurrentMip < mMipRange.end-1)
{
mCurrentMip++;
mCurrentLayer = mLayerRange.start;
}
}
else if (mCurrentMip < mMipRange.end-1)
{
mCurrentMip++;
mCurrentLayer = mLayerRange.start;
}
return value;
}
ImageIndex ImageIndexIterator::current() const
{
ImageIndex value(mType, mCurrentMip, mCurrentLayer);
if (mType == GL_TEXTURE_CUBE_MAP)
{
value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer);
}
return value;
}
bool ImageIndexIterator::hasNext() const
{
return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
}
}

View File

@ -10,6 +10,7 @@
#define LIBGLESV2_IMAGE_INDEX_H_
#include "angle_gl.h"
#include "common/mathutil.h"
namespace gl
{
@ -20,6 +21,7 @@ struct ImageIndex
GLint mipIndex;
GLint layerIndex;
ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
ImageIndex(const ImageIndex &other);
ImageIndex &operator=(const ImageIndex &other);
@ -29,11 +31,36 @@ struct ImageIndex
static ImageIndex MakeCube(GLenum target, GLint mipIndex);
static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
static ImageIndex MakeInvalid();
static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
};
class ImageIndexIterator
{
public:
static ImageIndexIterator Make2D(GLint minMip, GLint maxMip);
static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip);
static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
ImageIndex next();
ImageIndex current() const;
bool hasNext() const;
private:
ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
ImageIndexIterator(GLenum type, const rx::Range<GLint> &mipRange,
const rx::Range<GLint> &layerRange, const GLsizei *layerCounts);
GLint maxLayer() const;
GLenum mType;
rx::Range<GLint> mMipRange;
rx::Range<GLint> mLayerRange;
const GLsizei *mLayerCounts;
GLint mCurrentMip;
GLint mCurrentLayer;
};
}

View File

@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name)
// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
// compiling them into binaries, determining the attribute mappings, and collecting
// a list of uniforms
bool Program::link(const Caps &caps)
Error Program::link(const Data &data)
{
unlink(false);
@ -252,10 +252,15 @@ bool Program::link(const Caps &caps)
resetUniformBlockBindings();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
if (result.error.isError())
{
return result.error;
}
return mLinked;
mLinked = result.linkSuccess;
return gl::Error(GL_NO_ERROR);
}
int AttributeBindings::getAttributeBinding(const std::string &name) const
@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const
return mProgramBinary.get();
}
bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
{
unlink(false);
mInfoLog.reset();
mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
if (!mLinked)
LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
if (result.error.isError())
{
mProgramBinary.set(NULL);
return result.error;
}
return mLinked;
mLinked = result.linkSuccess;
return Error(GL_NO_ERROR);
}
void Program::release()

View File

@ -29,6 +29,7 @@ class Renderer;
namespace gl
{
struct Caps;
struct Data;
class ResourceManager;
class Shader;
@ -77,9 +78,9 @@ class Program
void bindAttributeLocation(GLuint index, const char *name);
bool link(const Caps &caps);
Error link(const Data &data);
bool isLinked();
bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
ProgramBinary *getProgramBinary() const;
int getInfoLogLength() const;

File diff suppressed because it is too large Load Diff

View File

@ -24,11 +24,6 @@
#include <string>
#include <vector>
// TODO(jmadill): place this in workarounds library
#define ANGLE_WORKAROUND_ENABLED 1
#define ANGLE_WORKAROUND_DISABLED 2
#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED
namespace sh
{
class HLSLBlockEncoder;
@ -44,7 +39,6 @@ class HLSLBlockEncoder;
namespace rx
{
class ShaderExecutable;
class Renderer;
struct TranslatedAttribute;
class UniformStorage;
class ProgramImpl;
@ -58,6 +52,7 @@ class InfoLog;
class AttributeBindings;
class Buffer;
class Framebuffer;
struct Data;
// Struct used for correlating uniforms/elements of uniform arrays to handles
struct VariableLocation
@ -91,6 +86,14 @@ struct LinkedVarying
unsigned int semanticIndexCount;
};
struct LinkResult
{
bool linkSuccess;
Error error;
LinkResult(bool linkSuccess, const Error &error);
};
// This is the result of linking a program. It is the state that would be passed to ProgramBinary.
class ProgramBinary : public RefCountObject
{
@ -101,11 +104,6 @@ class ProgramBinary : public RefCountObject
rx::ProgramImpl *getImplementation() { return mProgram; }
const rx::ProgramImpl *getImplementation() const { return mProgram; }
rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo);
rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]);
rx::ShaderExecutable *getGeometryExecutable() const;
GLuint getAttributeLocation(const char *name);
int getSemanticIndex(int attributeIndex);
@ -113,8 +111,6 @@ class ProgramBinary : public RefCountObject
GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
GLint getUsedSamplerRange(SamplerType type);
bool usesPointSize() const;
bool usesPointSpriteEmulation() const;
bool usesGeometryShader() const;
GLint getUniformLocation(std::string name);
GLuint getUniformIndex(std::string name);
@ -145,18 +141,17 @@ class ProgramBinary : public RefCountObject
void getUniformiv(GLint location, GLint *params);
void getUniformuiv(GLint location, GLuint *params);
void dirtyAllUniforms();
Error applyUniforms();
Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
GLint getLength();
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
LinkResult link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings,
Shader *fragmentShader, Shader *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings,
GLenum transformFeedbackBufferMode);
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
GLint getActiveAttributeCount() const;
@ -188,30 +183,23 @@ class ProgramBinary : public RefCountObject
void updateSamplerMapping();
unsigned int getSerial() const;
int getShaderVersion() const;
void initAttributesByLayout();
void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
const std::vector<LinkedUniform*> &getUniforms() const { return mUniforms; }
static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
private:
DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
struct Sampler
{
Sampler();
bool active;
GLint logicalTextureUnit;
GLenum textureType;
};
void reset();
bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader);
bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock);
static bool linkValidateVariablesBase(InfoLog &infoLog,
const std::string &variableName,
@ -219,102 +207,21 @@ class ProgramBinary : public RefCountObject
const sh::ShaderVariable &fragmentVariable,
bool validatePrecision);
static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder);
bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps);
bool indexUniforms(InfoLog &infoLog, const Caps &caps);
static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
std::vector<Sampler> &outSamplers, GLuint *outUsedRange);
bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
const std::vector<std::string> &transformFeedbackVaryingNames,
GLenum transformFeedbackBufferMode,
std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
const Caps &caps) const;
template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields, const std::string &prefix, int blockIndex,
sh::BlockLayoutEncoder *encoder, std::vector<unsigned int> *blockUniformIndexes,
bool inRowMajorLayout);
bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
void defineOutputVariables(Shader *fragmentShader);
template <typename T>
void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType);
template <int cols, int rows>
void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType);
template <typename T>
void getUniformv(GLint location, T *params, GLenum uniformType);
class VertexExecutable
{
public:
VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
const GLenum signature[MAX_VERTEX_ATTRIBS],
rx::ShaderExecutable *shaderExecutable);
~VertexExecutable();
bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const;
const VertexFormat *inputs() const { return mInputs; }
const GLenum *signature() const { return mSignature; }
rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
private:
VertexFormat mInputs[MAX_VERTEX_ATTRIBS];
GLenum mSignature[MAX_VERTEX_ATTRIBS];
rx::ShaderExecutable *mShaderExecutable;
};
class PixelExecutable
{
public:
PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable);
~PixelExecutable();
bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
private:
std::vector<GLenum> mOutputSignature;
rx::ShaderExecutable *mShaderExecutable;
};
rx::ProgramImpl *mProgram;
std::vector<VertexExecutable *> mVertexExecutables;
std::vector<PixelExecutable *> mPixelExecutables;
rx::ShaderExecutable *mGeometryExecutable;
sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS];
int mSemanticIndex[MAX_VERTEX_ATTRIBS];
int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
GLenum mTransformFeedbackBufferMode;
std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
std::vector<Sampler> mSamplersPS;
std::vector<Sampler> mSamplersVS;
GLuint mUsedVertexSamplerRange;
GLuint mUsedPixelSamplerRange;
bool mUsesPointSize;
int mShaderVersion;
bool mDirtySamplerMapping;
std::vector<LinkedUniform*> mUniforms;
std::vector<UniformBlock*> mUniformBlocks;
std::vector<VariableLocation> mUniformIndex;
std::map<int, VariableLocation> mOutputVariables;
bool mValidated;

View File

@ -4,77 +4,86 @@
// found in the LICENSE file.
//
// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes
// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class,
// GL renderbuffer objects and related functionality.
// [OpenGL ES 2.0.24] section 4.4.3 page 108.
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/formatutils.h"
#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/d3d/RendererD3D.h"
#include "libGLESv2/renderer/RenderTarget.h"
#include "libGLESv2/renderer/RenderbufferImpl.h"
#include "common/utilities.h"
namespace gl
{
unsigned int RenderbufferStorage::mCurrentSerial = 1;
Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage)
Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id)
: RefCountObject(id),
mStorage(newStorage)
mRenderbuffer(impl)
{
ASSERT(mStorage);
ASSERT(mRenderbuffer);
mWidth = mRenderbuffer->getWidth();
mHeight = mRenderbuffer->getHeight();
mInternalFormat = mRenderbuffer->getInternalFormat();
mActualFormat = mRenderbuffer->getActualFormat();
mSamples = mRenderbuffer->getSamples();
}
Renderbuffer::~Renderbuffer()
{
SafeDelete(mStorage);
SafeDelete(mRenderbuffer);
}
void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
{
ASSERT(newStorage);
Error error = mRenderbuffer->setStorage(width, height, internalformat, samples);
if (error.isError())
{
return error;
}
SafeDelete(mStorage);
mStorage = newStorage;
mWidth = width;
mHeight = height;
mInternalFormat = internalformat;
mSamples = samples;
mActualFormat = mRenderbuffer->getActualFormat();
return Error(GL_NO_ERROR);
}
RenderbufferStorage *Renderbuffer::getStorage()
rx::RenderbufferImpl *Renderbuffer::getImplementation()
{
ASSERT(mStorage);
return mStorage;
ASSERT(mRenderbuffer);
return mRenderbuffer;
}
GLsizei Renderbuffer::getWidth() const
{
ASSERT(mStorage);
return mStorage->getWidth();
return mWidth;
}
GLsizei Renderbuffer::getHeight() const
{
ASSERT(mStorage);
return mStorage->getHeight();
return mHeight;
}
GLenum Renderbuffer::getInternalFormat() const
{
ASSERT(mStorage);
return mStorage->getInternalFormat();
return mInternalFormat;
}
GLenum Renderbuffer::getActualFormat() const
{
ASSERT(mStorage);
return mStorage->getActualFormat();
return mActualFormat;
}
GLsizei Renderbuffer::getSamples() const
{
ASSERT(mStorage);
return mStorage->getSamples();
return mSamples;
}
GLuint Renderbuffer::getRedSize() const
@ -107,176 +116,4 @@ GLuint Renderbuffer::getStencilSize() const
return GetInternalFormatInfo(getActualFormat()).stencilBits;
}
RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1))
{
mWidth = 0;
mHeight = 0;
mInternalFormat = GL_RGBA4;
mActualFormat = GL_RGBA8_OES;
mSamples = 0;
}
RenderbufferStorage::~RenderbufferStorage()
{
}
rx::RenderTarget *RenderbufferStorage::getRenderTarget()
{
return NULL;
}
GLsizei RenderbufferStorage::getWidth() const
{
return mWidth;
}
GLsizei RenderbufferStorage::getHeight() const
{
return mHeight;
}
GLenum RenderbufferStorage::getInternalFormat() const
{
return mInternalFormat;
}
GLenum RenderbufferStorage::getActualFormat() const
{
return mActualFormat;
}
GLsizei RenderbufferStorage::getSamples() const
{
return mSamples;
}
unsigned int RenderbufferStorage::getSerial() const
{
return mSerial;
}
unsigned int RenderbufferStorage::issueSerials(unsigned int count)
{
unsigned int firstSerial = mCurrentSerial;
mCurrentSerial += count;
return firstSerial;
}
bool RenderbufferStorage::isTexture() const
{
return false;
}
unsigned int RenderbufferStorage::getTextureSerial() const
{
return -1;
}
Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
{
mRenderTarget = renderer->createRenderTarget(swapChain, false);
if (mRenderTarget)
{
mWidth = mRenderTarget->getWidth();
mHeight = mRenderTarget->getHeight();
mInternalFormat = mRenderTarget->getInternalFormat();
mActualFormat = mRenderTarget->getActualFormat();
mSamples = mRenderTarget->getSamples();
}
}
Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
{
mRenderTarget = renderer->createRenderTarget(width, height, format, samples);
if (mRenderTarget)
{
mWidth = width;
mHeight = height;
mInternalFormat = format;
mActualFormat = mRenderTarget->getActualFormat();
mSamples = mRenderTarget->getSamples();
}
}
Colorbuffer::~Colorbuffer()
{
if (mRenderTarget)
{
delete mRenderTarget;
}
}
rx::RenderTarget *Colorbuffer::getRenderTarget()
{
return mRenderTarget;
}
DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain)
{
mDepthStencil = renderer->createRenderTarget(swapChain, true);
if (mDepthStencil)
{
mWidth = mDepthStencil->getWidth();
mHeight = mDepthStencil->getHeight();
mInternalFormat = mDepthStencil->getInternalFormat();
mSamples = mDepthStencil->getSamples();
mActualFormat = mDepthStencil->getActualFormat();
}
}
DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples)
{
mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples);
mWidth = mDepthStencil->getWidth();
mHeight = mDepthStencil->getHeight();
mInternalFormat = GL_DEPTH24_STENCIL8_OES;
mActualFormat = mDepthStencil->getActualFormat();
mSamples = mDepthStencil->getSamples();
}
DepthStencilbuffer::~DepthStencilbuffer()
{
if (mDepthStencil)
{
delete mDepthStencil;
}
}
rx::RenderTarget *DepthStencilbuffer::getRenderTarget()
{
return mDepthStencil;
}
Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
{
if (mDepthStencil)
{
mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
// glRenderbufferStorage
}
}
Depthbuffer::~Depthbuffer()
{
}
Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples)
{
if (mDepthStencil)
{
mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
// glRenderbufferStorage
}
}
Stencilbuffer::~Stencilbuffer()
{
}
}

View File

@ -4,30 +4,27 @@
// found in the LICENSE file.
//
// Renderbuffer.h: Defines the wrapper class gl::Renderbuffer, as well as the
// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer,
// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer
// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer.
// Implements GL renderbuffer objects and related functionality.
// [OpenGL ES 2.0.24] section 4.4.3 page 108.
#ifndef LIBGLESV2_RENDERBUFFER_H_
#define LIBGLESV2_RENDERBUFFER_H_
#include "angle_gl.h"
#include "libGLESv2/Error.h"
#include "common/angleutils.h"
#include "common/RefCountObject.h"
namespace rx
{
class Renderer;
class SwapChain;
class RenderTarget;
class TextureStorage;
class RenderbufferImpl;
}
namespace gl
{
class RenderbufferStorage;
class FramebufferAttachment;
// A GL renderbuffer object is usually used as a depth or stencil buffer attachment
@ -38,11 +35,12 @@ class FramebufferAttachment;
class Renderbuffer : public RefCountObject
{
public:
Renderbuffer(GLuint id, RenderbufferStorage *newStorage);
Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
virtual ~Renderbuffer();
void setStorage(RenderbufferStorage *newStorage);
RenderbufferStorage *getStorage();
Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
rx::RenderbufferImpl *getImplementation();
GLsizei getWidth() const;
GLsizei getHeight() const;
@ -57,102 +55,15 @@ class Renderbuffer : public RefCountObject
GLuint getStencilSize() const;
private:
RenderbufferStorage *mStorage;
};
DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage
// is called. The specific concrete type depends on whether the internal format is
// colour depth, stencil or packed depth/stencil.
class RenderbufferStorage
{
public:
RenderbufferStorage();
rx::RenderbufferImpl *mRenderbuffer;
virtual ~RenderbufferStorage() = 0;
virtual rx::RenderTarget *getRenderTarget();
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
virtual GLenum getActualFormat() const;
virtual GLsizei getSamples() const;
virtual unsigned int getSerial() const;
virtual bool isTexture() const;
virtual unsigned int getTextureSerial() const;
static unsigned int issueSerials(unsigned int count);
protected:
GLsizei mWidth;
GLsizei mHeight;
GLenum mInternalFormat;
GLenum mActualFormat;
GLsizei mSamples;
private:
DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
const unsigned int mSerial;
static unsigned int mCurrentSerial;
};
class Colorbuffer : public RenderbufferStorage
{
public:
Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain);
Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
virtual ~Colorbuffer();
virtual rx::RenderTarget *getRenderTarget();
private:
DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
rx::RenderTarget *mRenderTarget;
};
class DepthStencilbuffer : public RenderbufferStorage
{
public:
DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain);
DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
~DepthStencilbuffer();
virtual rx::RenderTarget *getRenderTarget();
protected:
rx::RenderTarget *mDepthStencil;
private:
DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
};
class Depthbuffer : public DepthStencilbuffer
{
public:
Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
virtual ~Depthbuffer();
private:
DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
};
class Stencilbuffer : public DepthStencilbuffer
{
public:
Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples);
virtual ~Stencilbuffer();
private:
DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
};
}

View File

@ -21,9 +21,9 @@
namespace gl
{
ResourceManager::ResourceManager(rx::Renderer *renderer)
: mRenderer(renderer),
mRefCount(1)
{
mRefCount = 1;
mRenderer = renderer;
}
ResourceManager::~ResourceManager()
@ -88,13 +88,13 @@ GLuint ResourceManager::createBuffer()
}
// Returns an unused shader/program name
GLuint ResourceManager::createShader(GLenum type)
GLuint ResourceManager::createShader(const gl::Data &data, GLenum type)
{
GLuint handle = mProgramShaderHandleAllocator.allocate();
if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER)
{
mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle);
mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle);
}
else UNREACHABLE();
@ -146,7 +146,7 @@ GLuint ResourceManager::createFenceSync()
{
GLuint handle = mFenceSyncHandleAllocator.allocate();
FenceSync *fenceSync = new FenceSync(mRenderer, handle);
FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle);
fenceSync->addRef();
mFenceSyncMap[handle] = fenceSync;
@ -295,9 +295,9 @@ Texture *ResourceManager::getTexture(unsigned int handle)
}
}
Program *ResourceManager::getProgram(unsigned int handle)
Program *ResourceManager::getProgram(unsigned int handle) const
{
ProgramMap::iterator program = mProgramMap.find(handle);
ProgramMap::const_iterator program = mProgramMap.find(handle);
if (program == mProgramMap.end())
{
@ -403,7 +403,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
{
if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
{
Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer);
mRenderbufferMap[renderbuffer] = renderbufferObject;
renderbufferObject->addRef();
}

View File

@ -32,6 +32,7 @@ class Texture;
class Renderbuffer;
class Sampler;
class FenceSync;
struct Data;
class ResourceManager
{
@ -43,7 +44,7 @@ class ResourceManager
void release();
GLuint createBuffer();
GLuint createShader(GLenum type);
GLuint createShader(const gl::Data &data, GLenum type);
GLuint createProgram();
GLuint createTexture();
GLuint createRenderbuffer();
@ -60,7 +61,7 @@ class ResourceManager
Buffer *getBuffer(GLuint handle);
Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle);
Program *getProgram(GLuint handle) const;
Texture *getTexture(GLuint handle);
Renderbuffer *getRenderbuffer(GLuint handle);
Sampler *getSampler(GLuint handle);
@ -78,8 +79,8 @@ class ResourceManager
private:
DISALLOW_COPY_AND_ASSIGN(ResourceManager);
std::size_t mRefCount;
rx::Renderer *mRenderer;
std::size_t mRefCount;
typedef std::unordered_map<GLuint, Buffer*> BufferMap;
BufferMap mBufferMap;

View File

@ -118,9 +118,15 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer);
}
void Shader::compile()
void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
{
mCompiled = mShader->compile(mSource);
std::string debugInfo(mShader->getDebugInfo());
getSourceImpl(debugInfo, bufSize, length, buffer);
}
void Shader::compile(const gl::Data &data)
{
mCompiled = mShader->compile(data, mSource);
}
void Shader::addRef()

View File

@ -31,6 +31,7 @@ class ShaderImpl;
namespace gl
{
class ResourceManager;
struct Data;
struct PackedVarying : public sh::Varying
{
@ -73,8 +74,9 @@ class Shader
void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
int getTranslatedSourceLength() const;
void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;
void compile();
void compile(const gl::Data &data);
bool isCompiled() const { return mCompiled; }
void addRef();

View File

@ -10,18 +10,20 @@
#include "libGLESv2/Context.h"
#include "libGLESv2/Caps.h"
#include "libGLESv2/VertexArray.h"
#include "libGLESv2/Query.h"
#include "libGLESv2/Framebuffer.h"
#include "libGLESv2/FramebufferAttachment.h"
#include "libGLESv2/renderer/RenderTarget.h"
#include "libGLESv2/Query.h"
#include "libGLESv2/VertexArray.h"
#include "libGLESv2/formatutils.h"
#include "libGLESv2/renderer/RenderTarget.h"
namespace gl
{
State::State()
{
mMaxDrawBuffers = 0;
mMaxCombinedTextureImageUnits = 0;
}
State::~State()
@ -31,7 +33,8 @@ State::~State()
void State::initialize(const Caps& caps, GLuint clientVersion)
{
mContext = NULL;
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@ -111,11 +114,15 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
mActiveSampler = 0;
const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex)
{
mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
}
mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes);
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
if (clientVersion >= 3)
@ -153,12 +160,6 @@ void State::reset()
mSamplers[samplerIdx].set(NULL);
}
const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f };
for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++)
{
mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues);
}
mArrayBuffer.set(NULL);
mRenderbuffer.set(NULL);
@ -170,15 +171,15 @@ void State::reset()
}
mGenericUniformBuffer.set(NULL);
for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++)
mGenericTransformFeedbackBuffer.set(NULL);
for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
{
mUniformBuffers[i].set(NULL);
bufItr->set(NULL);
}
mGenericTransformFeedbackBuffer.set(NULL);
for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr)
{
mTransformFeedbackBuffers[i].set(NULL);
bufItr->set(NULL);
}
mCopyReadBuffer.set(NULL);
@ -485,7 +486,7 @@ void State::setSampleCoverageParams(GLclampf value, bool invert)
mSampleCoverageInvert = invert;
}
void State::getSampleCoverageParams(GLclampf *value, bool *invert)
void State::getSampleCoverageParams(GLclampf *value, bool *invert) const
{
ASSERT(value != NULL && invert != NULL);
@ -612,14 +613,7 @@ void State::setSamplerTexture(GLenum type, Texture *texture)
Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
{
const BindingPointer<Texture>& binding = mSamplerTextures.at(type)[sampler];
if (binding.id() == 0) // Special case: 0 refers to default textures held by Context
{
return NULL;
}
return binding.get();
return mSamplerTextures.at(type)[sampler].get();
}
GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
@ -627,7 +621,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
return mSamplerTextures.at(type)[sampler].id();
}
void State::detachTexture(GLuint texture)
void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
{
// Textures have a detach method on State rather than a simple
// removeBinding, because the zero/null texture objects are managed
@ -640,13 +634,15 @@ void State::detachTexture(GLuint texture)
for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
{
GLenum textureType = bindingVec->first;
TextureBindingVector &textureVector = bindingVec->second;
for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
{
BindingPointer<Texture> &binding = textureVector[textureIdx];
if (binding.id() == texture)
{
binding.set(NULL);
// Zero textures are the "default" textures instead of NULL
binding.set(zeroTextures.at(textureType).get());
}
}
}
@ -667,6 +663,19 @@ void State::detachTexture(GLuint texture)
}
}
void State::initializeZeroTextures(const TextureMap &zeroTextures)
{
for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++)
{
TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first];
for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
{
samplerTextureArray[textureUnit].set(i->second.get());
}
}
}
void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
{
mSamplers[textureUnit].set(sampler);
@ -947,14 +956,14 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt
GLuint State::getIndexedUniformBufferId(GLuint index) const
{
ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
return mUniformBuffers[index].id();
}
Buffer *State::getIndexedUniformBuffer(GLuint index) const
{
ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
return mUniformBuffers[index].get();
}
@ -971,25 +980,30 @@ void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffe
GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const
{
ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
return mTransformFeedbackBuffers[index].id();
}
Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const
{
ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
return mTransformFeedbackBuffers[index].get();
}
GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const
{
ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
ASSERT(static_cast<size_t>(index) < mTransformFeedbackBuffers.size());
return mTransformFeedbackBuffers[index].getOffset();
}
size_t State::getTransformFeedbackBufferIndexRange() const
{
return mTransformFeedbackBuffers.size();
}
void State::setCopyReadBufferBinding(Buffer *buffer)
{
mCopyReadBuffer.set(buffer);
@ -1033,19 +1047,19 @@ void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
void State::setVertexAttribf(GLuint index, const GLfloat values[4])
{
ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setFloatValues(values);
}
void State::setVertexAttribu(GLuint index, const GLuint values[4])
{
ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
}
void State::setVertexAttribi(GLuint index, const GLint values[4])
{
ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setIntValues(values);
}
@ -1062,15 +1076,10 @@ const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
{
ASSERT(attribNum < MAX_VERTEX_ATTRIBS);
ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
return mVertexAttribCurrentValues[attribNum];
}
const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const
{
return mVertexAttribCurrentValues;
}
const void *State::getVertexAttribPointer(unsigned int attribNum) const
{
return getVertexArray()->getVertexAttribute(attribNum).pointer;
@ -1180,12 +1189,12 @@ void State::getFloatv(GLenum pname, GLfloat *params)
}
}
void State::getIntegerv(GLenum pname, GLint *params)
void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
{
if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
{
unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers);
ASSERT(colorAttachment < mMaxDrawBuffers);
Framebuffer *framebuffer = mDrawFramebuffer;
*params = framebuffer->getDrawBufferState(colorAttachment);
return;
@ -1238,12 +1247,12 @@ void State::getIntegerv(GLenum pname, GLint *params)
case GL_SAMPLES:
{
gl::Framebuffer *framebuffer = mDrawFramebuffer;
if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE)
{
switch (pname)
{
case GL_SAMPLE_BUFFERS:
if (framebuffer->getSamples() != 0)
if (framebuffer->getSamples(data) != 0)
{
*params = 1;
}
@ -1253,7 +1262,7 @@ void State::getIntegerv(GLenum pname, GLint *params)
}
break;
case GL_SAMPLES:
*params = framebuffer->getSamples();
*params = framebuffer->getSamples(data);
break;
}
}
@ -1332,19 +1341,19 @@ void State::getIntegerv(GLenum pname, GLint *params)
}
break;
case GL_TEXTURE_BINDING_2D:
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
break;
case GL_TEXTURE_BINDING_CUBE_MAP:
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
break;
case GL_TEXTURE_BINDING_3D:
ASSERT(mActiveSampler <mContext->getCaps().maxCombinedTextureImageUnits);
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
break;
case GL_TEXTURE_BINDING_2D_ARRAY:
ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits);
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
break;
case GL_UNIFORM_BUFFER_BINDING:
@ -1376,13 +1385,13 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
{
*data = mTransformFeedbackBuffers[index].id();
}
break;
case GL_UNIFORM_BUFFER_BINDING:
if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
if (static_cast<size_t>(index) < mUniformBuffers.size())
{
*data = mUniformBuffers[index].id();
}
@ -1399,25 +1408,25 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
{
*data = mTransformFeedbackBuffers[index].getOffset();
}
break;
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS)
if (static_cast<size_t>(index) < mTransformFeedbackBuffers.size())
{
*data = mTransformFeedbackBuffers[index].getSize();
}
break;
case GL_UNIFORM_BUFFER_START:
if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
if (static_cast<size_t>(index) < mUniformBuffers.size())
{
*data = mUniformBuffers[index].getOffset();
}
break;
case GL_UNIFORM_BUFFER_SIZE:
if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS)
if (static_cast<size_t>(index) < mUniformBuffers.size())
{
*data = mUniformBuffers[index].getSize();
}
@ -1433,9 +1442,9 @@ bool State::hasMappedBuffer(GLenum target) const
{
if (target == GL_ARRAY_BUFFER)
{
for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++)
for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++)
{
const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex);
const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast<unsigned int>(attribIndex));
gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
{

View File

@ -25,6 +25,9 @@ class Query;
class VertexArray;
class Context;
struct Caps;
struct Data;
typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
class State
{
@ -35,8 +38,6 @@ class State
void initialize(const Caps& caps, GLuint clientVersion);
void reset();
void setContext(Context *context) { mContext = context; }
// State chunk getters
const RasterizerState &getRasterizerState() const;
const BlendState &getBlendState() const;
@ -100,7 +101,7 @@ class State
bool isSampleCoverageEnabled() const;
void setSampleCoverage(bool enabled);
void setSampleCoverageParams(GLclampf value, bool invert);
void getSampleCoverageParams(GLclampf *value, bool *invert);
void getSampleCoverageParams(GLclampf *value, bool *invert) const;
// Scissor test state toggle & query
bool isScissorTestEnabled() const;
@ -133,7 +134,8 @@ class State
void setSamplerTexture(GLenum type, Texture *texture);
Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
void detachTexture(GLuint texture);
void detachTexture(const TextureMap &zeroTextures, GLuint texture);
void initializeZeroTextures(const TextureMap &zeroTextures);
// Sampler object binding manipulation
void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
@ -199,6 +201,7 @@ class State
GLuint getIndexedTransformFeedbackBufferId(GLuint index) const;
Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const;
GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const;
size_t getTransformFeedbackBufferIndexRange() const;
// GL_COPY_[READ/WRITE]_BUFFER
void setCopyReadBufferBinding(Buffer *buffer);
@ -220,7 +223,6 @@ class State
bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const;
const void *getVertexAttribPointer(unsigned int attribNum) const;
// Pixel pack state manipulation
@ -238,7 +240,7 @@ class State
// State query functions
void getBooleanv(GLenum pname, GLboolean *params);
void getFloatv(GLenum pname, GLfloat *params);
void getIntegerv(GLenum pname, GLint *params);
void getIntegerv(const gl::Data &data, GLenum pname, GLint *params);
bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
@ -247,7 +249,9 @@ class State
private:
DISALLOW_COPY_AND_ASSIGN(State);
Context *mContext;
// Cached values from Context's caps
GLuint mMaxDrawBuffers;
GLuint mMaxCombinedTextureImageUnits;
ColorF mColorClearValue;
GLclampf mDepthClearValue;
@ -283,7 +287,8 @@ class State
GLuint mCurrentProgramId;
BindingPointer<ProgramBinary> mCurrentProgramBinary;
VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib
typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
VertexArray *mVertexArray;
// Texture and sampler bindings
@ -300,11 +305,12 @@ class State
ActiveQueryMap mActiveQueries;
BindingPointer<Buffer> mGenericUniformBuffer;
OffsetBindingPointer<Buffer> mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
typedef std::vector< OffsetBindingPointer<Buffer> > BufferVector;
BufferVector mUniformBuffers;
BindingPointer<TransformFeedback> mTransformFeedback;
BindingPointer<Buffer> mGenericTransformFeedbackBuffer;
OffsetBindingPointer<Buffer> mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
BufferVector mTransformFeedbackBuffers;
BindingPointer<Buffer> mCopyReadBuffer;
BindingPointer<Buffer> mCopyWriteBuffer;

View File

@ -47,11 +47,14 @@ bool IsPointSampled(const gl::SamplerState &samplerState)
return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
}
unsigned int Texture::mCurrentTextureSerial = 1;
Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
: RefCountObject(id),
mTexture(impl),
mTextureSerial(issueTextureSerial()),
mUsage(GL_NONE),
mImmutable(false),
mImmutableLevelCount(0),
mTarget(target)
{
}
@ -72,16 +75,6 @@ void Texture::setUsage(GLenum usage)
getImplementation()->setUsage(usage);
}
void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler)
{
*sampler = mSamplerState;
// Offset the effective base level by the texture storage's top level
rx::TextureStorage *texture = getNativeTexture();
int topLevel = texture ? texture->getTopLevel() : 0;
sampler->baseLevel = topLevel + mSamplerState.baseLevel;
}
GLenum Texture::getUsage() const
{
return mUsage;
@ -138,35 +131,35 @@ GLenum Texture::getActualFormat(const ImageIndex &index) const
return image->getActualFormat();
}
rx::TextureStorage *Texture::getNativeTexture()
Error Texture::generateMipmaps()
{
return getImplementation()->getNativeTexture();
return getImplementation()->generateMipmaps();
}
void Texture::generateMipmaps()
Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
getImplementation()->generateMipmaps();
return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
}
void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
unsigned int Texture::getTextureSerial() const
{
getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
return mTextureSerial;
}
unsigned int Texture::getTextureSerial()
unsigned int Texture::issueTextureSerial()
{
rx::TextureStorage *texture = getNativeTexture();
return texture ? texture->getTextureSerial() : 0;
return mCurrentTextureSerial++;
}
bool Texture::isImmutable() const
{
return mImmutable;
return (mImmutableLevelCount > 0);
}
int Texture::immutableLevelCount()
{
return (mImmutable ? getNativeTexture()->getLevelCount() : 0);
return mImmutableLevelCount;
}
int Texture::mipLevels() const
@ -226,11 +219,11 @@ GLenum Texture2D::getActualFormat(GLint level) const
return GL_NONE;
}
void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
releaseTexImage();
mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
void Texture2D::bindTexImage(egl::Surface *surface)
@ -254,35 +247,44 @@ void Texture2D::releaseTexImage()
}
}
void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize,
const PixelUnpackState &unpack, const void *pixels)
{
releaseTexImage();
mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels);
return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels);
}
void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
}
void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
}
void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
Framebuffer *source)
{
releaseTexImage();
mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
}
void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
mImmutable = true;
Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
if (error.isError())
{
return error;
}
mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
mImmutableLevelCount = levels;
return Error(GL_NO_ERROR);
}
// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
@ -359,11 +361,11 @@ bool Texture2D::isDepth(GLint level) const
return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
void Texture2D::generateMipmaps()
Error Texture2D::generateMipmaps()
{
releaseTexImage();
mTexture->generateMipmaps();
return mTexture->generateMipmaps();
}
// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
@ -467,49 +469,27 @@ GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
return GL_NONE;
}
void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height,
GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels);
return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels);
}
void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
}
void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format,
GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels);
}
void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels);
}
void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
}
void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
{
mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels);
return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
}
// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
@ -549,16 +529,23 @@ bool TextureCubeMap::isDepth(GLenum target, GLint level) const
return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
}
void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
GLsizei width, GLsizei height, Framebuffer *source)
{
mTexture->copyImage(target, level, format, x, y, width, height, source);
return mTexture->copyImage(target, level, format, x, y, width, height, source);
}
void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
{
mImmutable = true;
Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
if (error.isError())
{
return error;
}
mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
mImmutableLevelCount = levels;
return Error(GL_NO_ERROR);
}
// Tests for texture sampling completeness
@ -734,31 +721,40 @@ bool Texture3D::isDepth(GLint level) const
return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
}
void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels);
return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels);
}
void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
}
void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format,
GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
}
void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
mImmutable = true;
Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
if (error.isError())
{
return error;
}
mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
mImmutableLevelCount = levels;
return Error(GL_NO_ERROR);
}
bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
@ -892,31 +888,40 @@ bool Texture2DArray::isDepth(GLint level) const
return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
}
void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels);
return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels);
}
void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
}
void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format,
GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
{
mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels);
return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
}
void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
mImmutable = true;
Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
if (error.isError())
{
return error;
}
mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
mImmutableLevelCount = levels;
return Error(GL_NO_ERROR);
}
bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const

View File

@ -14,7 +14,7 @@
#include "common/debug.h"
#include "common/RefCountObject.h"
#include "libGLESv2/angletypes.h"
#include "libGLESv2/constants.h"
#include "libGLESv2/Constants.h"
#include "libGLESv2/renderer/TextureImpl.h"
#include "libGLESv2/Caps.h"
@ -52,7 +52,6 @@ class Texture : public RefCountObject
const SamplerState &getSamplerState() const { return mSamplerState; }
SamplerState &getSamplerState() { return mSamplerState; }
void getSamplerStateWithNativeOffset(SamplerState *sampler);
void setUsage(GLenum usage);
GLenum getUsage() const;
@ -69,15 +68,16 @@ class Texture : public RefCountObject
virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0;
rx::TextureStorage *getNativeTexture();
virtual Error generateMipmaps();
virtual void generateMipmaps();
virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
unsigned int getTextureSerial();
// Texture serials provide a unique way of identifying a Texture that isn't a raw pointer.
// "id" is not good enough, as Textures can be deleted, then re-allocated with the same id.
unsigned int getTextureSerial() const;
bool isImmutable() const;
int immutableLevelCount();
GLsizei immutableLevelCount();
rx::TextureImpl *getImplementation() { return mTexture; }
const rx::TextureImpl *getImplementation() const { return mTexture; }
@ -86,17 +86,20 @@ class Texture : public RefCountObject
protected:
int mipLevels() const;
const rx::Image *getBaseLevelImage() const;
static unsigned int issueTextureSerial();
rx::TextureImpl *mTexture;
SamplerState mSamplerState;
GLenum mUsage;
bool mImmutable;
GLsizei mImmutableLevelCount;
GLenum mTarget;
const rx::Image *getBaseLevelImage() const;
const unsigned int mTextureSerial;
static unsigned int mCurrentTextureSerial;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
@ -116,18 +119,18 @@ class Texture2D : public Texture
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
virtual void generateMipmaps();
virtual Error generateMipmaps();
private:
DISALLOW_COPY_AND_ASSIGN(Texture2D);
@ -152,19 +155,12 @@ class TextureCubeMap : public Texture
bool isCompressed(GLenum target, GLint level) const;
bool isDepth(GLenum target, GLint level) const;
void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
void storage(GLsizei levels, GLenum internalformat, GLsizei size);
Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
Error storage(GLsizei levels, GLenum internalformat, GLsizei size);
virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
@ -195,11 +191,11 @@ class Texture3D : public Texture
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
@ -225,11 +221,11 @@ class Texture2DArray : public Texture
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels);
void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;

Some files were not shown because too many files have changed in this diff Show More