зеркало из https://github.com/AvaloniaUI/angle.git
translator: Remove non-sh scoped APIs.
Now that Chromium is switched over, we can remove the old global APIs so they no longer conflict with glslang/Vulkan. BUG=angleproject:1319 Change-Id: Ia673d47caa7ca40139e4989fac374acd48f52ab9 Reviewed-on: https://chromium-review.googlesource.com/408517 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
6be602dc69
Коммит
a818c327fe
|
@ -25,7 +25,7 @@
|
|||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented every time the API changes.
|
||||
#define ANGLE_SH_VERSION 170
|
||||
#define ANGLE_SH_VERSION 171
|
||||
|
||||
enum ShShaderSpec
|
||||
{
|
||||
|
@ -383,150 +383,6 @@ struct ShBuiltInResources
|
|||
//
|
||||
using ShHandle = void *;
|
||||
|
||||
//
|
||||
// Driver must call this first, once, before doing any other
|
||||
// compiler operations.
|
||||
// If the function succeeds, the return value is true, else false.
|
||||
//
|
||||
bool ShInitialize();
|
||||
//
|
||||
// Driver should call this at shutdown.
|
||||
// If the function succeeds, the return value is true, else false.
|
||||
//
|
||||
bool ShFinalize();
|
||||
|
||||
//
|
||||
// Initialize built-in resources with minimum expected values.
|
||||
// Parameters:
|
||||
// resources: The object to initialize. Will be comparable with memcmp.
|
||||
//
|
||||
void ShInitBuiltInResources(ShBuiltInResources *resources);
|
||||
|
||||
//
|
||||
// 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.
|
||||
const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
|
||||
|
||||
//
|
||||
// Driver calls these to create and destroy compiler objects.
|
||||
//
|
||||
// Returns the handle of constructed compiler, null if the requested compiler is
|
||||
// not supported.
|
||||
// Parameters:
|
||||
// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
|
||||
// spec: Specifies the language spec the compiler must conform to -
|
||||
// SH_GLES2_SPEC or SH_WEBGL_SPEC.
|
||||
// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
|
||||
// SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
|
||||
// be supported in some configurations.
|
||||
// resources: Specifies the built-in resources.
|
||||
ShHandle ShConstructCompiler(sh::GLenum type,
|
||||
ShShaderSpec spec,
|
||||
ShShaderOutput output,
|
||||
const ShBuiltInResources *resources);
|
||||
void ShDestruct(ShHandle handle);
|
||||
|
||||
//
|
||||
// Compiles the given shader source.
|
||||
// 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
|
||||
// containing the shader source code.
|
||||
// numStrings: Specifies the number of elements in shaderStrings array.
|
||||
// compileOptions: A mask containing the following parameters:
|
||||
// SH_VALIDATE: Validates shader to ensure that it conforms to the spec
|
||||
// specified during compiler construction.
|
||||
// SH_VALIDATE_LOOP_INDEXING: Validates loop and indexing in the shader to
|
||||
// ensure that they do not exceed the minimum
|
||||
// functionality mandated in GLSL 1.0 spec,
|
||||
// Appendix A, Section 4 and 5.
|
||||
// There is no need to specify this parameter when
|
||||
// compiling for WebGL - it is implied.
|
||||
// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
|
||||
// Can be queried by calling sh::GetInfoLog().
|
||||
// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
|
||||
// Can be queried by calling sh::GetObjectCode().
|
||||
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
|
||||
// Can be queried by calling ShGetVariableInfo().
|
||||
//
|
||||
bool ShCompile(const ShHandle handle,
|
||||
const char *const shaderStrings[],
|
||||
size_t numStrings,
|
||||
ShCompileOptions compileOptions);
|
||||
|
||||
// Clears the results from the previous compilation.
|
||||
void ShClearResults(const ShHandle handle);
|
||||
|
||||
// Return the version of the shader language.
|
||||
int ShGetShaderVersion(const ShHandle handle);
|
||||
|
||||
// Return the currently set language output type.
|
||||
ShShaderOutput ShGetShaderOutputType(const ShHandle handle);
|
||||
|
||||
// Returns null-terminated information log for a compiled shader.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
const std::string &ShGetInfoLog(const ShHandle handle);
|
||||
|
||||
// Returns null-terminated object code for a compiled shader.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
const std::string &ShGetObjectCode(const ShHandle handle);
|
||||
|
||||
// Returns a (original_name, hash) map containing all the user defined
|
||||
// names in the shader, including variable names, function names, struct
|
||||
// names, and struct field names.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
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.
|
||||
// (See ShaderVars.h for type definitions, included above)
|
||||
// Returns NULL on failure.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
|
||||
const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
|
||||
const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
|
||||
const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle);
|
||||
const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
|
||||
sh::WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle);
|
||||
int ShGetVertexShaderNumViews(const ShHandle handle);
|
||||
|
||||
// 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 false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
|
||||
// flag above.
|
||||
// Parameters:
|
||||
// maxVectors: the available rows of registers.
|
||||
// variables: an array of variables.
|
||||
bool ShCheckVariablesWithinPackingLimits(int maxVectors,
|
||||
const std::vector<sh::ShaderVariable> &variables);
|
||||
|
||||
// Gives the compiler-assigned register for an interface block.
|
||||
// The method writes the value to the output variable "indexOut".
|
||||
// Returns true if it found a valid interface block, false otherwise.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
// interfaceBlockName: Specifies the interface block
|
||||
// indexOut: output variable that stores the assigned register
|
||||
bool ShGetInterfaceBlockRegister(const ShHandle handle,
|
||||
const std::string &interfaceBlockName,
|
||||
unsigned int *indexOut);
|
||||
|
||||
// Gives a map from uniform names to compiler-assigned registers in the default
|
||||
// interface block. Note that the map contains also registers of samplers that
|
||||
// have been extracted from structs.
|
||||
const std::map<std::string, unsigned int> *ShGetUniformRegisterMap(const ShHandle handle);
|
||||
|
||||
// Temporary duplicate of the scoped APIs, to be removed when we roll ANGLE and fix Chromium.
|
||||
// TODO(jmadill): Consolidate with these APIs once we roll ANGLE.
|
||||
|
||||
namespace sh
|
||||
{
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||
size -= kHeaderSize;
|
||||
data += kHeaderSize;
|
||||
|
||||
if (!ShInitialize())
|
||||
if (!sh::Initialize())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||
}
|
||||
|
||||
ShBuiltInResources resources;
|
||||
ShInitBuiltInResources(&resources);
|
||||
sh::InitBuiltInResources(&resources);
|
||||
|
||||
// Enable all the extensions to have more coverage
|
||||
resources.OES_standard_derivatives = 1;
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
#include "compiler/translator/VariablePacker.h"
|
||||
#include "angle_gl.h"
|
||||
|
||||
using namespace sh;
|
||||
namespace sh
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -107,7 +108,7 @@ TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
|
|||
// Driver must call this first, once, before doing any other compiler operations.
|
||||
// Subsequent calls to this function are no-op.
|
||||
//
|
||||
bool ShInitialize()
|
||||
bool Initialize()
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
|
@ -119,7 +120,7 @@ bool ShInitialize()
|
|||
//
|
||||
// Cleanup symbol tables
|
||||
//
|
||||
bool ShFinalize()
|
||||
bool Finalize()
|
||||
{
|
||||
if (isInitialized)
|
||||
{
|
||||
|
@ -132,7 +133,7 @@ bool ShFinalize()
|
|||
//
|
||||
// Initialize built-in resources with minimum expected values.
|
||||
//
|
||||
void ShInitBuiltInResources(ShBuiltInResources *resources)
|
||||
void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
{
|
||||
// Make comparable.
|
||||
memset(resources, 0, sizeof(*resources));
|
||||
|
@ -223,10 +224,10 @@ void ShInitBuiltInResources(ShBuiltInResources *resources)
|
|||
//
|
||||
// Driver calls these to create and destroy compiler objects.
|
||||
//
|
||||
ShHandle ShConstructCompiler(sh::GLenum type,
|
||||
ShShaderSpec spec,
|
||||
ShShaderOutput output,
|
||||
const ShBuiltInResources *resources)
|
||||
ShHandle ConstructCompiler(sh::GLenum type,
|
||||
ShShaderSpec spec,
|
||||
ShShaderOutput output,
|
||||
const ShBuiltInResources *resources)
|
||||
{
|
||||
TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output));
|
||||
if (base == nullptr)
|
||||
|
@ -243,14 +244,14 @@ ShHandle ShConstructCompiler(sh::GLenum type,
|
|||
// Generate built-in symbol table.
|
||||
if (!compiler->Init(*resources))
|
||||
{
|
||||
sh::Destruct(base);
|
||||
Destruct(base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<void *>(base);
|
||||
}
|
||||
|
||||
void ShDestruct(ShHandle handle)
|
||||
void Destruct(ShHandle handle)
|
||||
{
|
||||
if (handle == 0)
|
||||
return;
|
||||
|
@ -261,7 +262,7 @@ void ShDestruct(ShHandle handle)
|
|||
DeleteCompiler(base->getAsCompiler());
|
||||
}
|
||||
|
||||
const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
|
||||
const std::string &GetBuiltInResourcesString(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
|
@ -275,10 +276,10 @@ const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
|
|||
// Return: The return value of ShCompile is really boolean, indicating
|
||||
// success or failure.
|
||||
//
|
||||
bool ShCompile(const ShHandle handle,
|
||||
const char *const shaderStrings[],
|
||||
size_t numStrings,
|
||||
ShCompileOptions compileOptions)
|
||||
bool Compile(const ShHandle handle,
|
||||
const char *const shaderStrings[],
|
||||
size_t numStrings,
|
||||
ShCompileOptions compileOptions)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
|
@ -286,21 +287,21 @@ bool ShCompile(const ShHandle handle,
|
|||
return compiler->compile(shaderStrings, numStrings, compileOptions);
|
||||
}
|
||||
|
||||
void ShClearResults(const ShHandle handle)
|
||||
void ClearResults(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
compiler->clearResults();
|
||||
}
|
||||
|
||||
int ShGetShaderVersion(const ShHandle handle)
|
||||
int GetShaderVersion(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
return compiler->getShaderVersion();
|
||||
}
|
||||
|
||||
ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
|
||||
ShShaderOutput GetShaderOutputType(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
|
@ -310,7 +311,7 @@ ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
|
|||
//
|
||||
// Return any compiler log of messages for the application.
|
||||
//
|
||||
const std::string &ShGetInfoLog(const ShHandle handle)
|
||||
const std::string &GetInfoLog(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
|
@ -322,7 +323,7 @@ const std::string &ShGetInfoLog(const ShHandle handle)
|
|||
//
|
||||
// Return any object code.
|
||||
//
|
||||
const std::string &ShGetObjectCode(const ShHandle handle)
|
||||
const std::string &GetObjectCode(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
|
@ -331,39 +332,39 @@ const std::string &ShGetObjectCode(const ShHandle handle)
|
|||
return infoSink.obj.str();
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string> *ShGetNameHashingMap(const ShHandle handle)
|
||||
const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
|
||||
{
|
||||
TCompiler *compiler = GetCompilerFromHandle(handle);
|
||||
ASSERT(compiler);
|
||||
return &(compiler->getNameMap());
|
||||
}
|
||||
|
||||
const std::vector<Uniform> *ShGetUniforms(const ShHandle handle)
|
||||
const std::vector<Uniform> *GetUniforms(const ShHandle handle)
|
||||
{
|
||||
return GetShaderVariables<Uniform>(handle);
|
||||
}
|
||||
|
||||
const std::vector<Varying> *ShGetVaryings(const ShHandle handle)
|
||||
const std::vector<Varying> *GetVaryings(const ShHandle handle)
|
||||
{
|
||||
return GetShaderVariables<Varying>(handle);
|
||||
}
|
||||
|
||||
const std::vector<Attribute> *ShGetAttributes(const ShHandle handle)
|
||||
const std::vector<Attribute> *GetAttributes(const ShHandle handle)
|
||||
{
|
||||
return GetShaderVariables<Attribute>(handle);
|
||||
}
|
||||
|
||||
const std::vector<OutputVariable> *ShGetOutputVariables(const ShHandle handle)
|
||||
const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
|
||||
{
|
||||
return GetShaderVariables<OutputVariable>(handle);
|
||||
}
|
||||
|
||||
const std::vector<InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle)
|
||||
const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
|
||||
{
|
||||
return GetShaderVariables<InterfaceBlock>(handle);
|
||||
}
|
||||
|
||||
WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle)
|
||||
WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
|
||||
{
|
||||
ASSERT(handle);
|
||||
|
||||
|
@ -374,7 +375,7 @@ WorkGroupSize ShGetComputeShaderLocalGroupSize(const ShHandle handle)
|
|||
return compiler->getComputeShaderLocalSize();
|
||||
}
|
||||
|
||||
int ShGetVertexShaderNumViews(const ShHandle handle)
|
||||
int GetVertexShaderNumViews(const ShHandle handle)
|
||||
{
|
||||
ASSERT(handle);
|
||||
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
|
||||
|
@ -384,16 +385,15 @@ int ShGetVertexShaderNumViews(const ShHandle handle)
|
|||
return compiler->getNumViews();
|
||||
}
|
||||
|
||||
bool ShCheckVariablesWithinPackingLimits(int maxVectors,
|
||||
const std::vector<ShaderVariable> &variables)
|
||||
bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
|
||||
{
|
||||
VariablePacker packer;
|
||||
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
|
||||
}
|
||||
|
||||
bool ShGetInterfaceBlockRegister(const ShHandle handle,
|
||||
const std::string &interfaceBlockName,
|
||||
unsigned int *indexOut)
|
||||
bool GetInterfaceBlockRegister(const ShHandle handle,
|
||||
const std::string &interfaceBlockName,
|
||||
unsigned int *indexOut)
|
||||
{
|
||||
#ifdef ANGLE_ENABLE_HLSL
|
||||
ASSERT(indexOut);
|
||||
|
@ -413,7 +413,7 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
|
|||
#endif // ANGLE_ENABLE_HLSL
|
||||
}
|
||||
|
||||
const std::map<std::string, unsigned int> *ShGetUniformRegisterMap(const ShHandle handle)
|
||||
const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
|
||||
{
|
||||
#ifdef ANGLE_ENABLE_HLSL
|
||||
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
|
||||
|
@ -425,127 +425,4 @@ const std::map<std::string, unsigned int> *ShGetUniformRegisterMap(const ShHandl
|
|||
#endif // ANGLE_ENABLE_HLSL
|
||||
}
|
||||
|
||||
namespace sh
|
||||
{
|
||||
bool Initialize()
|
||||
{
|
||||
return ShInitialize();
|
||||
}
|
||||
|
||||
bool Finalize()
|
||||
{
|
||||
return ShFinalize();
|
||||
}
|
||||
|
||||
void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
{
|
||||
ShInitBuiltInResources(resources);
|
||||
}
|
||||
|
||||
const std::string &GetBuiltInResourcesString(const ShHandle handle)
|
||||
{
|
||||
return ShGetBuiltInResourcesString(handle);
|
||||
}
|
||||
|
||||
ShHandle ConstructCompiler(sh::GLenum type,
|
||||
ShShaderSpec spec,
|
||||
ShShaderOutput output,
|
||||
const ShBuiltInResources *resources)
|
||||
{
|
||||
return ShConstructCompiler(type, spec, output, resources);
|
||||
}
|
||||
|
||||
void Destruct(ShHandle handle)
|
||||
{
|
||||
return ShDestruct(handle);
|
||||
}
|
||||
|
||||
bool Compile(const ShHandle handle,
|
||||
const char *const shaderStrings[],
|
||||
size_t numStrings,
|
||||
ShCompileOptions compileOptions)
|
||||
{
|
||||
return ShCompile(handle, shaderStrings, numStrings, compileOptions);
|
||||
}
|
||||
|
||||
void ClearResults(const ShHandle handle)
|
||||
{
|
||||
return ShClearResults(handle);
|
||||
}
|
||||
|
||||
int GetShaderVersion(const ShHandle handle)
|
||||
{
|
||||
return ShGetShaderVersion(handle);
|
||||
}
|
||||
|
||||
ShShaderOutput GetShaderOutputType(const ShHandle handle)
|
||||
{
|
||||
return ShGetShaderOutputType(handle);
|
||||
}
|
||||
|
||||
const std::string &GetInfoLog(const ShHandle handle)
|
||||
{
|
||||
return ShGetInfoLog(handle);
|
||||
}
|
||||
|
||||
const std::string &GetObjectCode(const ShHandle handle)
|
||||
{
|
||||
return ShGetObjectCode(handle);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
|
||||
{
|
||||
return ShGetNameHashingMap(handle);
|
||||
}
|
||||
|
||||
const std::vector<sh::Uniform> *GetUniforms(const ShHandle handle)
|
||||
{
|
||||
return ShGetUniforms(handle);
|
||||
}
|
||||
const std::vector<sh::Varying> *GetVaryings(const ShHandle handle)
|
||||
{
|
||||
return ShGetVaryings(handle);
|
||||
}
|
||||
const std::vector<sh::Attribute> *GetAttributes(const ShHandle handle)
|
||||
{
|
||||
return ShGetAttributes(handle);
|
||||
}
|
||||
|
||||
const std::vector<sh::OutputVariable> *GetOutputVariables(const ShHandle handle)
|
||||
{
|
||||
return ShGetOutputVariables(handle);
|
||||
}
|
||||
const std::vector<sh::InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
|
||||
{
|
||||
return ShGetInterfaceBlocks(handle);
|
||||
}
|
||||
|
||||
sh::WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
|
||||
{
|
||||
return ShGetComputeShaderLocalGroupSize(handle);
|
||||
}
|
||||
|
||||
int GetVertexShaderNumViews(const ShHandle handle)
|
||||
{
|
||||
return ShGetVertexShaderNumViews(handle);
|
||||
}
|
||||
|
||||
bool CheckVariablesWithinPackingLimits(int maxVectors,
|
||||
const std::vector<sh::ShaderVariable> &variables)
|
||||
{
|
||||
return ShCheckVariablesWithinPackingLimits(maxVectors, variables);
|
||||
}
|
||||
|
||||
bool GetInterfaceBlockRegister(const ShHandle handle,
|
||||
const std::string &interfaceBlockName,
|
||||
unsigned int *indexOut)
|
||||
{
|
||||
return ShGetInterfaceBlockRegister(handle, interfaceBlockName, indexOut);
|
||||
}
|
||||
|
||||
const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
|
||||
{
|
||||
return ShGetUniformRegisterMap(handle);
|
||||
}
|
||||
|
||||
} // namespace sh
|
||||
|
|
Загрузка…
Ссылка в новой задаче