mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-06 02:09:55 +03:00
Existing implementation uses single `GlobalMutex` for
- EGL calls
- GL calls for Contexts with concurrent access.
This CL introduces abstract `egl::ContextMutex` with two
implementations:
- SingleContextMutex;
- SharedContextMutex<Mutex>;
Note:
`std::mutex` is used in this commit. It is very easy to change mutex
type either at compile-time or at run-time (single type per Display).
When Context:
- is not Shared;
- does not use `EGLImage`s;
- does not use EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE
- does not use EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE
then it will be using `SingleContextMutex` with minimal overhead.
Before such Context is used as `shareContext` or uses `EGLImage`
its mutex replaced by `SharedContextMutex<Mutex>`.
The `GlobalMutex` is only used for EGL calls, while `egl::ContextMutex`
implementations for GL calls. Because some EGL calls use Context,
explicit `egl::ContextMutex` lock is required. This is implemented by
generating "egl_context_mutex_autogen.h" header, and insertion of
`ANGLE_EGL_SCOPED_CONTEXT_LOCK()` macro before `ANGLE_EGL_VALIDATE()`
in each EGL entry point. Implementation in "egl_context_lock_impl.h"
returns lock for required APIs. Special cases of `egl::ContextMutex`
lock handled separately. `std::unique_lock<>` is not used for
performance reasons.
`egl::ContextMutex` explicitly locked when capturing EGL calls.
Fixes EGLImage problem:
e18240d136
Mark contexts as shared when importing EGL images.
Details:
- EGLImage inherits Context's mutex when created.
Mutex is used when the EGLImage accessed or destroyed.
- When EGLImage is used in Context with other `egl::ContextMutex`,
two mutexes are merged into one.
- After the mutex merge, Context Groups will remain separate,
but will not be able to run in parallel.
Fixes race when checking `context->isShared()` in the
`SCOPED_SHARE_CONTEXT_LOCK()` macro. One Context may start executing GL
call while not "Shared", but become "Shared" inside the call. New
(second) "Shared" Context may immediately start using GL and potentially
corrupt some "Shared" state.
Possible performance benefit: allows parallel execution in some cases,
when single `GlobalMutex` would block.
Important note:
Process of replacing the `SingleContextMutex` by
`SharedContextMutex<Mutex>` is not 100% safe. This mean that
original Context may still be using `SingleContextMutex` after
activating `SharedContextMutex<Mutex>`. However, this was always
the case before introduction of this CL. Old `Context::mShared`
member update was not synchronized in any way at all. In other
words, this solution does not 100% fix the original problem.
For 100% safe solution `SingleContextMutex` should not be used
(always pass `SharedContextMutex<Mutex>` to the `gl::Context`
constructor). See `lockAndActivateSharedContextMutex()` for more
details.
CL adds new build option:
angle_enable_shared_context_mutex = true
Behavior with other build options:
- When:
`angle_enable_shared_context_mutex` is disabled or
`angle_enable_share_context_lock` is disabled or
`angle_force_context_check_every_call` is enabled,
Contexts will always have `SingleContextMutex`, however it will be
only used in special cases. `SCOPED_SHARE_CONTEXT_LOCK()` will use
`GlobalMutex` when applicable.
- Otherwise, `SCOPED_SHARE_CONTEXT_LOCK()` will use `egl::ContextMutex`.
Some GFXBench "1080p Driver Overhead 2 Offscreen" performance numbers.
Tested on S906B (Samsung Galaxy S22+) on old ANGLE base:
807c94ea85
Capture/Replay: Adjust tests do adhere to capture limits
Each test result is an average frame number from 6 runs.
SingleContextMutex 6579 ( +0.13%)
(old) GetContextLock() (mShared is false) 6570
Forced `mShared = true` or NOT using `SingleContextMutex`.
SharedContextMutex<std::mutex> FORCE 5061 (-22.97%)
(old) GetContextLock() FORCE 4766 (-27.46%)
Bug: angleproject:6957
Bug: chromium:1336126
Change-Id: Idcd919f9d4bf482b9ae489bd8b4415ec96048e32
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4374545
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
3499 lines
119 KiB
Python
Executable File
3499 lines
119 KiB
Python
Executable File
#!/usr/bin/python3
|
|
#
|
|
# Copyright 2017 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.
|
|
#
|
|
# generate_entry_points.py:
|
|
# Generates the OpenGL bindings and entry point layers for ANGLE.
|
|
# NOTE: don't run this script directly. Run scripts/run_code_generation.py.
|
|
|
|
import sys, os, pprint, json
|
|
import fnmatch
|
|
import registry_xml
|
|
from registry_xml import apis, script_relative, strip_api_prefix, api_enums
|
|
|
|
# Paths
|
|
CL_STUBS_HEADER_PATH = "../src/libGLESv2/cl_stubs_autogen.h"
|
|
EGL_GET_LABELED_OBJECT_DATA_PATH = "../src/libGLESv2/egl_get_labeled_object_data.json"
|
|
EGL_STUBS_HEADER_PATH = "../src/libGLESv2/egl_stubs_autogen.h"
|
|
EGL_EXT_STUBS_HEADER_PATH = "../src/libGLESv2/egl_ext_stubs_autogen.h"
|
|
|
|
# List of GLES1 extensions for which we don't need to add Context.h decls.
|
|
GLES1_NO_CONTEXT_DECL_EXTENSIONS = [
|
|
"GL_OES_framebuffer_object",
|
|
]
|
|
|
|
# This is a list of exceptions for entry points which don't want to have
|
|
# the EVENT macro. This is required for some debug marker entry points.
|
|
NO_EVENT_MARKER_EXCEPTIONS_LIST = sorted([
|
|
"glPushGroupMarkerEXT",
|
|
"glPopGroupMarkerEXT",
|
|
"glInsertEventMarkerEXT",
|
|
])
|
|
|
|
# glRenderbufferStorageMultisampleEXT aliases glRenderbufferStorageMultisample on desktop GL, and is
|
|
# marked as such in the registry. However, that is not correct for GLES where this entry point
|
|
# comes from GL_EXT_multisampled_render_to_texture which is never promoted to core GLES.
|
|
ALIASING_EXCEPTIONS = [
|
|
'glRenderbufferStorageMultisampleEXT', 'renderbufferStorageMultisampleEXT',
|
|
'drawArraysInstancedBaseInstanceANGLE', 'drawElementsInstancedBaseVertexBaseInstanceANGLE',
|
|
'glLogicOpANGLE', 'logicOpANGLE'
|
|
]
|
|
|
|
# These are the entry points which potentially are used first by an application
|
|
# and require that the back ends are initialized before the front end is called.
|
|
INIT_DICT = {
|
|
"clGetPlatformIDs": "false",
|
|
"clGetPlatformInfo": "false",
|
|
"clGetDeviceIDs": "false",
|
|
"clCreateContext": "false",
|
|
"clCreateContextFromType": "false",
|
|
"clIcdGetPlatformIDsKHR": "true",
|
|
}
|
|
|
|
# These are the only entry points that are allowed while pixel local storage is active.
|
|
PLS_ALLOW_LIST = {
|
|
"ActiveTexture",
|
|
"BindBuffer",
|
|
"BindBufferBase",
|
|
"BindBufferRange",
|
|
"BindSampler",
|
|
"BindTexture",
|
|
"BindVertexArray",
|
|
"BufferData",
|
|
"BufferSubData",
|
|
"CheckFramebufferStatus",
|
|
"ClipControlEXT",
|
|
"CullFace",
|
|
"DepthFunc",
|
|
"DepthMask",
|
|
"DepthRangef",
|
|
"Disable",
|
|
"DisableVertexAttribArray",
|
|
"DispatchComputeIndirect",
|
|
"Enable",
|
|
"EnableClientState",
|
|
"EnableVertexAttribArray",
|
|
"EndPixelLocalStorageANGLE",
|
|
"FramebufferPixelLocalStorageInterruptANGLE",
|
|
"FrontFace",
|
|
"MapBufferRange",
|
|
"PixelLocalStorageBarrierANGLE",
|
|
"Scissor",
|
|
"StencilFunc",
|
|
"StencilFuncSeparate",
|
|
"StencilMask",
|
|
"StencilMaskSeparate",
|
|
"StencilOp",
|
|
"StencilOpSeparate",
|
|
"UnmapBuffer",
|
|
"UseProgram",
|
|
"ValidateProgram",
|
|
"Viewport",
|
|
"ProvokingVertexANGLE",
|
|
"FenceSync",
|
|
"FlushMappedBufferRange",
|
|
}
|
|
PLS_ALLOW_WILDCARDS = [
|
|
"BlendEquationSeparatei*",
|
|
"BlendEquationi*",
|
|
"BlendFuncSeparatei*",
|
|
"BlendFunci*",
|
|
"ClearBuffer*",
|
|
"ColorMaski*",
|
|
"DebugMessageCallback*",
|
|
"DebugMessageControl*",
|
|
"DebugMessageInsert*",
|
|
"Delete*",
|
|
"Disablei*",
|
|
"DrawArrays*",
|
|
"DrawElements*",
|
|
"DrawRangeElements*",
|
|
"Enablei*",
|
|
"Gen*",
|
|
"Get*",
|
|
"Is*",
|
|
"ObjectLabel*",
|
|
"ObjectPtrLabel*",
|
|
"PolygonOffset*",
|
|
"PopDebugGroup*",
|
|
"PushDebugGroup*",
|
|
"SamplerParameter*",
|
|
"TexParameter*",
|
|
"Uniform*",
|
|
"VertexAttrib*",
|
|
]
|
|
|
|
TEMPLATE_ENTRY_POINT_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// entry_points_{annotation_lower}_autogen.h:
|
|
// Defines the {comment} entry points.
|
|
|
|
#ifndef {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
|
|
#define {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
|
|
|
|
{includes}
|
|
|
|
{entry_points}
|
|
|
|
#endif // {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_ENTRY_POINT_SOURCE = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// entry_points_{annotation_lower}_autogen.cpp:
|
|
// Defines the {comment} entry points.
|
|
|
|
{includes}
|
|
|
|
{entry_points}
|
|
"""
|
|
|
|
TEMPLATE_ENTRY_POINTS_ENUM_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// entry_points_enum_autogen.h:
|
|
// Defines the {lib} entry points enumeration.
|
|
|
|
#ifndef COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
|
|
#define COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
|
|
|
|
namespace angle
|
|
{{
|
|
enum class EntryPoint
|
|
{{
|
|
{entry_points_list}
|
|
}};
|
|
|
|
const char *GetEntryPointName(EntryPoint ep);
|
|
}} // namespace angle
|
|
#endif // COMMON_ENTRY_POINTS_ENUM_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_ENTRY_POINTS_NAME_CASE = """\
|
|
case EntryPoint::{enum}:
|
|
return "{cmd}";"""
|
|
|
|
TEMPLATE_ENTRY_POINTS_ENUM_SOURCE = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
//
|
|
// entry_points_enum_autogen.cpp:
|
|
// Helper methods for the {lib} entry points enumeration.
|
|
|
|
#include "common/entry_points_enum_autogen.h"
|
|
|
|
#include "common/debug.h"
|
|
|
|
namespace angle
|
|
{{
|
|
const char *GetEntryPointName(EntryPoint ep)
|
|
{{
|
|
switch (ep)
|
|
{{
|
|
{entry_points_name_cases}
|
|
default:
|
|
UNREACHABLE();
|
|
return "error";
|
|
}}
|
|
}}
|
|
}} // namespace angle
|
|
"""
|
|
|
|
TEMPLATE_LIB_ENTRY_POINT_SOURCE = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// {lib_name}_autogen.cpp: Implements the exported {lib_description} functions.
|
|
|
|
{includes}
|
|
extern "C" {{
|
|
{entry_points}
|
|
}} // extern "C"
|
|
"""
|
|
|
|
TEMPLATE_ENTRY_POINT_DECL = """{angle_export}{return_type} {export_def} {name}({params});"""
|
|
|
|
TEMPLATE_GLES_ENTRY_POINT_NO_RETURN = """\
|
|
void GL_APIENTRY GL_{name}({params})
|
|
{{
|
|
Context *context = {context_getter};
|
|
{event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
|
|
|
|
if ({valid_context_check})
|
|
{{{packed_gl_enum_conversions}
|
|
{context_lock}
|
|
bool isCallValid = (context->skipValidation() || {validation_expression});
|
|
if (isCallValid)
|
|
{{
|
|
context->{name_lower_no_suffix}({internal_params});
|
|
}}
|
|
ANGLE_CAPTURE_GL({name}, isCallValid, {gl_capture_params});
|
|
}}
|
|
else
|
|
{{
|
|
{constext_lost_error_generator}
|
|
}}
|
|
ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN = """\
|
|
{return_type} GL_APIENTRY GL_{name}({params})
|
|
{{
|
|
Context *context = {context_getter};
|
|
{event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
|
|
|
|
{return_type} returnValue;
|
|
if ({valid_context_check})
|
|
{{{packed_gl_enum_conversions}
|
|
{context_lock}
|
|
bool isCallValid = (context->skipValidation() || {validation_expression});
|
|
if (isCallValid)
|
|
{{
|
|
returnValue = context->{name_lower_no_suffix}({internal_params});
|
|
}}
|
|
else
|
|
{{
|
|
returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
|
|
}}
|
|
ANGLE_CAPTURE_GL({name}, isCallValid, {gl_capture_params}, returnValue);
|
|
}}
|
|
else
|
|
{{
|
|
{constext_lost_error_generator}
|
|
returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
|
|
}}
|
|
ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
|
|
return returnValue;
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_EGL_ENTRY_POINT_NO_RETURN = """\
|
|
void EGLAPIENTRY EGL_{name}({params})
|
|
{{
|
|
{preamble}
|
|
Thread *thread = egl::GetCurrentThread();
|
|
{{
|
|
ANGLE_SCOPED_GLOBAL_LOCK();
|
|
EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
|
|
|
|
{packed_gl_enum_conversions}
|
|
|
|
{{
|
|
ANGLE_EGL_SCOPED_CONTEXT_LOCK({name}, thread{comma_if_needed_context_lock}{internal_context_lock_params});
|
|
ANGLE_EGL_VALIDATE_VOID(thread, {name}, {labeled_object}, {internal_params});
|
|
|
|
{name}(thread{comma_if_needed}{internal_params});
|
|
}}
|
|
|
|
ANGLE_CAPTURE_EGL({name}, true, {egl_capture_params});
|
|
}}
|
|
{epilog}
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN = """\
|
|
{return_type} EGLAPIENTRY EGL_{name}({params})
|
|
{{
|
|
{preamble}
|
|
Thread *thread = egl::GetCurrentThread();
|
|
{return_type} returnValue;
|
|
{{
|
|
ANGLE_SCOPED_GLOBAL_LOCK();
|
|
EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
|
|
|
|
{packed_gl_enum_conversions}
|
|
|
|
{{
|
|
ANGLE_EGL_SCOPED_CONTEXT_LOCK({name}, thread{comma_if_needed_context_lock}{internal_context_lock_params});
|
|
ANGLE_EGL_VALIDATE(thread, {name}, {labeled_object}, {return_type}{comma_if_needed}{internal_params});
|
|
|
|
returnValue = {name}(thread{comma_if_needed}{internal_params});
|
|
}}
|
|
|
|
ANGLE_CAPTURE_EGL({name}, true, {egl_capture_params}, returnValue);
|
|
}}
|
|
{epilog}
|
|
return returnValue;
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_CL_ENTRY_POINT_NO_RETURN = """\
|
|
void CL_API_CALL cl{name}({params})
|
|
{{
|
|
CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
|
|
|
|
{packed_gl_enum_conversions}
|
|
|
|
ANGLE_CL_VALIDATE_VOID({name}{comma_if_needed}{internal_params});
|
|
|
|
{name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR = """\
|
|
cl_int CL_API_CALL cl{name}({params})
|
|
{{{initialization}
|
|
CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
|
|
|
|
{packed_gl_enum_conversions}
|
|
|
|
ANGLE_CL_VALIDATE_ERROR({name}{comma_if_needed}{internal_params});
|
|
|
|
return {name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET = """\
|
|
{return_type} CL_API_CALL cl{name}({params})
|
|
{{{initialization}
|
|
CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
|
|
|
|
{packed_gl_enum_conversions}
|
|
|
|
ANGLE_CL_VALIDATE_ERRCODE_RET({name}{comma_if_needed}{internal_params});
|
|
|
|
cl_int errorCode = CL_SUCCESS;
|
|
{return_type} object = {name}({internal_params}, errorCode);
|
|
|
|
ASSERT((errorCode == CL_SUCCESS) == (object != nullptr));
|
|
if (errcode_ret != nullptr)
|
|
{{
|
|
*errcode_ret = errorCode;
|
|
}}
|
|
return object;
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER = """\
|
|
{return_type} CL_API_CALL cl{name}({params})
|
|
{{{initialization}
|
|
CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
|
|
|
|
{packed_gl_enum_conversions}
|
|
|
|
ANGLE_CL_VALIDATE_POINTER({name}{comma_if_needed}{internal_params});
|
|
|
|
return {name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_CL_STUBS_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2021 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.
|
|
//
|
|
// {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
|
|
|
|
#ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
|
|
#define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
|
|
|
|
#include "libANGLE/CLtypes.h"
|
|
|
|
namespace cl
|
|
{{
|
|
{stubs}
|
|
}} // namespace cl
|
|
#endif // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_EGL_STUBS_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
|
|
|
|
#ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
|
|
#define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
|
|
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
|
|
#include "common/PackedEnums.h"
|
|
#include "common/PackedEGLEnums_autogen.h"
|
|
|
|
namespace gl
|
|
{{
|
|
class Context;
|
|
}} // namespace gl
|
|
|
|
namespace egl
|
|
{{
|
|
class AttributeMap;
|
|
class Device;
|
|
class Display;
|
|
class Image;
|
|
class Stream;
|
|
class Surface;
|
|
class Sync;
|
|
class Thread;
|
|
struct Config;
|
|
|
|
{stubs}
|
|
}} // namespace egl
|
|
#endif // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
|
|
"""
|
|
|
|
CONTEXT_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// Context_{annotation_lower}_autogen.h: Creates a macro for interfaces in Context.
|
|
|
|
#ifndef ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
|
|
#define ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
|
|
|
|
#define ANGLE_{annotation_upper}_CONTEXT_API \\
|
|
{interface}
|
|
|
|
#endif // ANGLE_CONTEXT_API_{version}_AUTOGEN_H_
|
|
"""
|
|
|
|
CONTEXT_DECL_FORMAT = """ {return_type} {name_lower_no_suffix}({internal_params}){maybe_const}; \\"""
|
|
|
|
TEMPLATE_CL_ENTRY_POINT_EXPORT = """\
|
|
{return_type} CL_API_CALL cl{name}({params})
|
|
{{
|
|
return cl::GetDispatch().cl{name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_GL_ENTRY_POINT_EXPORT = """\
|
|
{return_type} GL_APIENTRY gl{name}({params})
|
|
{{
|
|
return GL_{name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_EGL_ENTRY_POINT_EXPORT = """\
|
|
{return_type} EGLAPIENTRY egl{name}({params})
|
|
{{
|
|
EnsureEGLLoaded();
|
|
return EGL_{name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_GLX_ENTRY_POINT_EXPORT = """\
|
|
{return_type} GLXENTRY {name}({params})
|
|
{{
|
|
return GLX_{name}({internal_params});
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_GLEXT_FUNCTION_POINTER = """typedef {return_type}(GL_APIENTRYP PFN{name_upper}PROC)({params});"""
|
|
TEMPLATE_GLEXT_FUNCTION_PROTOTYPE = """{apicall} {return_type}GL_APIENTRY {name}({params});"""
|
|
|
|
TEMPLATE_GL_VALIDATION_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// validation{annotation}_autogen.h:
|
|
// Validation functions for the OpenGL {comment} entry points.
|
|
|
|
#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
|
|
#include "common/entry_points_enum_autogen.h"
|
|
#include "common/PackedEnums.h"
|
|
|
|
namespace gl
|
|
{{
|
|
class Context;
|
|
|
|
{prototypes}
|
|
}} // namespace gl
|
|
|
|
#endif // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_CL_VALIDATION_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2021 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.
|
|
//
|
|
// validation{annotation}_autogen.h:
|
|
// Validation functions for the {comment} entry points.
|
|
|
|
#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
|
|
#include "libANGLE/validationCL.h"
|
|
|
|
namespace cl
|
|
{{
|
|
{prototypes}
|
|
}} // namespace cl
|
|
|
|
#endif // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_EGL_VALIDATION_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// validation{annotation}_autogen.h:
|
|
// Validation functions for the {comment} entry points.
|
|
|
|
#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
|
|
#include "libANGLE/validationEGL.h"
|
|
|
|
namespace egl
|
|
{{
|
|
{prototypes}
|
|
}} // namespace egl
|
|
|
|
#endif // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_EGL_CONTEXT_LOCK_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2023 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.
|
|
//
|
|
// {annotation_lower}_context_lock_autogen.h:
|
|
// Context Lock functions for the {comment} entry points.
|
|
|
|
#ifndef LIBGLESV2_{annotation_upper}_CONTEXT_LOCK_AUTOGEN_H_
|
|
#define LIBGLESV2_{annotation_upper}_CONTEXT_LOCK_AUTOGEN_H_
|
|
|
|
#include "libGLESv2/global_state.h"
|
|
|
|
namespace egl
|
|
{{
|
|
{prototypes}
|
|
}} // namespace egl
|
|
|
|
#endif // LIBGLESV2_{annotation_upper}_CONTEXT_LOCK_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_CAPTURE_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// capture_{annotation_lower}_autogen.h:
|
|
// Capture functions for the OpenGL ES {comment} entry points.
|
|
|
|
#ifndef LIBANGLE_CAPTURE_{annotation_upper}_AUTOGEN_H_
|
|
#define LIBANGLE_CAPTURE_{annotation_upper}_AUTOGEN_H_
|
|
|
|
#include "common/PackedEnums.h"
|
|
#include "libANGLE/capture/FrameCapture.h"
|
|
|
|
namespace {namespace}
|
|
{{
|
|
{prototypes}
|
|
}} // namespace {namespace}
|
|
|
|
#endif // LIBANGLE_CAPTURE_{annotation_upper}_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_CAPTURE_SOURCE = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// capture_{annotation_with_dash}_autogen.cpp:
|
|
// Capture functions for the OpenGL ES {comment} entry points.
|
|
|
|
#include "libANGLE/capture/capture_{annotation_with_dash}_autogen.h"
|
|
|
|
#include "common/gl_enum_utils.h"
|
|
#include "libANGLE/Context.h"
|
|
#include "libANGLE/capture/FrameCapture.h"
|
|
#include "libANGLE/validation{annotation_no_dash}.h"
|
|
|
|
using namespace angle;
|
|
|
|
namespace {namespace}
|
|
{{
|
|
{capture_methods}
|
|
}} // namespace {namespace}
|
|
"""
|
|
|
|
TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE = """\
|
|
CallCapture Capture{short_name}({params_with_type}, {return_value_type_original} returnValue)
|
|
{{
|
|
ParamBuffer paramBuffer;
|
|
|
|
{parameter_captures}
|
|
|
|
ParamCapture returnValueCapture("returnValue", ParamType::T{return_value_type_custom});
|
|
InitParamValue(ParamType::T{return_value_type_custom}, returnValue, &returnValueCapture.value);
|
|
paramBuffer.addReturnValue(std::move(returnValueCapture));
|
|
|
|
return CallCapture(angle::EntryPoint::{api_upper}{short_name}, std::move(paramBuffer));
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE = """\
|
|
CallCapture Capture{short_name}({params_with_type})
|
|
{{
|
|
ParamBuffer paramBuffer;
|
|
|
|
{parameter_captures}
|
|
|
|
return CallCapture(angle::EntryPoint::{api_upper}{short_name}, std::move(paramBuffer));
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_PARAMETER_CAPTURE_VALUE = """paramBuffer.addValueParam("{name}", ParamType::T{type}, {name});"""
|
|
|
|
TEMPLATE_PARAMETER_CAPTURE_GL_ENUM = """paramBuffer.addEnumParam("{name}", {api_enum}::{group}, ParamType::T{type}, {name});"""
|
|
|
|
TEMPLATE_PARAMETER_CAPTURE_POINTER = """
|
|
if (isCallValid)
|
|
{{
|
|
ParamCapture {name}Param("{name}", ParamType::T{type});
|
|
InitParamValue(ParamType::T{type}, {name}, &{name}Param.value);
|
|
{capture_name}({params}, &{name}Param);
|
|
paramBuffer.addParam(std::move({name}Param));
|
|
}}
|
|
else
|
|
{{
|
|
ParamCapture {name}Param("{name}", ParamType::T{type});
|
|
InitParamValue(ParamType::T{type}, static_cast<{cast_type}>(nullptr), &{name}Param.value);
|
|
paramBuffer.addParam(std::move({name}Param));
|
|
}}
|
|
"""
|
|
|
|
TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC = """void {name}({params});"""
|
|
|
|
TEMPLATE_CAPTURE_REPLAY_SOURCE = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// frame_capture_replay_autogen.cpp:
|
|
// Replay captured GL calls.
|
|
|
|
#include "angle_trace_gl.h"
|
|
#include "common/debug.h"
|
|
#include "common/frame_capture_utils.h"
|
|
#include "frame_capture_test_utils.h"
|
|
|
|
namespace angle
|
|
{{
|
|
void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions)
|
|
{{
|
|
const ParamBuffer ¶ms = call.params;
|
|
const std::vector<ParamCapture> &captures = params.getParamCaptures();
|
|
|
|
switch (call.entryPoint)
|
|
{{
|
|
{call_replay_cases}
|
|
default:
|
|
ASSERT(!call.customFunctionName.empty());
|
|
ReplayCustomFunctionCall(call, customFunctions);
|
|
break;
|
|
}}
|
|
}}
|
|
|
|
}} // namespace angle
|
|
|
|
"""
|
|
|
|
TEMPLATE_REPLAY_CALL_CASE = """\
|
|
case angle::EntryPoint::{enum}:
|
|
{call}({params});
|
|
break;
|
|
"""
|
|
|
|
POINTER_FORMAT = "0x%016\" PRIxPTR \""
|
|
UNSIGNED_LONG_LONG_FORMAT = "%llu"
|
|
HEX_LONG_LONG_FORMAT = "0x%llX"
|
|
|
|
FORMAT_DICT = {
|
|
"GLbitfield": "%s",
|
|
"GLboolean": "%s",
|
|
"GLbyte": "%d",
|
|
"GLclampx": "0x%X",
|
|
"GLDEBUGPROC": POINTER_FORMAT,
|
|
"GLDEBUGPROCKHR": POINTER_FORMAT,
|
|
"GLdouble": "%f",
|
|
"GLeglClientBufferEXT": POINTER_FORMAT,
|
|
"GLeglImageOES": POINTER_FORMAT,
|
|
"GLenum": "%s",
|
|
"GLfixed": "0x%X",
|
|
"GLfloat": "%f",
|
|
"GLint": "%d",
|
|
"GLintptr": UNSIGNED_LONG_LONG_FORMAT,
|
|
"GLshort": "%d",
|
|
"GLsizei": "%d",
|
|
"GLsizeiptr": UNSIGNED_LONG_LONG_FORMAT,
|
|
"GLsync": POINTER_FORMAT,
|
|
"GLubyte": "%d",
|
|
"GLuint": "%u",
|
|
"GLuint64": UNSIGNED_LONG_LONG_FORMAT,
|
|
"GLushort": "%u",
|
|
"int": "%d",
|
|
# EGL-specific types
|
|
"EGLConfig": POINTER_FORMAT,
|
|
"EGLContext": POINTER_FORMAT,
|
|
"EGLDisplay": POINTER_FORMAT,
|
|
"EGLSurface": POINTER_FORMAT,
|
|
"EGLSync": POINTER_FORMAT,
|
|
"EGLNativeDisplayType": POINTER_FORMAT,
|
|
"EGLNativePixmapType": POINTER_FORMAT,
|
|
"EGLNativeWindowType": POINTER_FORMAT,
|
|
"EGLClientBuffer": POINTER_FORMAT,
|
|
"EGLenum": "0x%X",
|
|
"EGLint": "%d",
|
|
"EGLImage": POINTER_FORMAT,
|
|
"EGLTime": UNSIGNED_LONG_LONG_FORMAT,
|
|
"EGLGetBlobFuncANDROID": POINTER_FORMAT,
|
|
"EGLSetBlobFuncANDROID": POINTER_FORMAT,
|
|
"EGLuint64KHR": UNSIGNED_LONG_LONG_FORMAT,
|
|
"EGLSyncKHR": POINTER_FORMAT,
|
|
"EGLnsecsANDROID": UNSIGNED_LONG_LONG_FORMAT,
|
|
"EGLDeviceEXT": POINTER_FORMAT,
|
|
"EGLDEBUGPROCKHR": POINTER_FORMAT,
|
|
"EGLObjectKHR": POINTER_FORMAT,
|
|
"EGLLabelKHR": POINTER_FORMAT,
|
|
"EGLTimeKHR": UNSIGNED_LONG_LONG_FORMAT,
|
|
"EGLImageKHR": POINTER_FORMAT,
|
|
"EGLStreamKHR": POINTER_FORMAT,
|
|
"EGLFrameTokenANGLE": HEX_LONG_LONG_FORMAT,
|
|
# WGL-specific types
|
|
"BOOL": "%u",
|
|
"DWORD": POINTER_FORMAT,
|
|
"FLOAT": "%f",
|
|
"HDC": POINTER_FORMAT,
|
|
"HENHMETAFILE": POINTER_FORMAT,
|
|
"HGLRC": POINTER_FORMAT,
|
|
"LPCSTR": POINTER_FORMAT,
|
|
"LPGLYPHMETRICSFLOAT": POINTER_FORMAT,
|
|
"UINT": "%u",
|
|
# CL-specific types
|
|
"size_t": "%zu",
|
|
"cl_char": "%hhd",
|
|
"cl_uchar": "%hhu",
|
|
"cl_short": "%hd",
|
|
"cl_ushort": "%hu",
|
|
"cl_int": "%d",
|
|
"cl_uint": "%u",
|
|
"cl_long": "%lld",
|
|
"cl_ulong": "%llu",
|
|
"cl_half": "%hu",
|
|
"cl_float": "%f",
|
|
"cl_double": "%f",
|
|
"cl_platform_id": POINTER_FORMAT,
|
|
"cl_device_id": POINTER_FORMAT,
|
|
"cl_context": POINTER_FORMAT,
|
|
"cl_command_queue": POINTER_FORMAT,
|
|
"cl_mem": POINTER_FORMAT,
|
|
"cl_program": POINTER_FORMAT,
|
|
"cl_kernel": POINTER_FORMAT,
|
|
"cl_event": POINTER_FORMAT,
|
|
"cl_sampler": POINTER_FORMAT,
|
|
"cl_bool": "%u",
|
|
"cl_bitfield": "%llu",
|
|
"cl_properties": "%llu",
|
|
"cl_device_type": "%llu",
|
|
"cl_platform_info": "%u",
|
|
"cl_device_info": "%u",
|
|
"cl_device_fp_config": "%llu",
|
|
"cl_device_mem_cache_type": "%u",
|
|
"cl_device_local_mem_type": "%u",
|
|
"cl_device_exec_capabilities": "%llu",
|
|
"cl_device_svm_capabilities": "%llu",
|
|
"cl_command_queue_properties": "%llu",
|
|
"cl_device_partition_property": "%zu",
|
|
"cl_device_affinity_domain": "%llu",
|
|
"cl_context_properties": "%zu",
|
|
"cl_context_info": "%u",
|
|
"cl_queue_properties": "%llu",
|
|
"cl_command_queue_info": "%u",
|
|
"cl_channel_order": "%u",
|
|
"cl_channel_type": "%u",
|
|
"cl_mem_flags": "%llu",
|
|
"cl_svm_mem_flags": "%llu",
|
|
"cl_mem_object_type": "%u",
|
|
"cl_mem_info": "%u",
|
|
"cl_mem_migration_flags": "%llu",
|
|
"cl_mem_properties": "%llu",
|
|
"cl_image_info": "%u",
|
|
"cl_buffer_create_type": "%u",
|
|
"cl_addressing_mode": "%u",
|
|
"cl_filter_mode": "%u",
|
|
"cl_sampler_info": "%u",
|
|
"cl_map_flags": "%llu",
|
|
"cl_pipe_properties": "%zu",
|
|
"cl_pipe_info": "%u",
|
|
"cl_program_info": "%u",
|
|
"cl_program_build_info": "%u",
|
|
"cl_program_binary_type": "%u",
|
|
"cl_build_status": "%d",
|
|
"cl_kernel_info": "%u",
|
|
"cl_kernel_arg_info": "%u",
|
|
"cl_kernel_arg_address_qualifier": "%u",
|
|
"cl_kernel_arg_access_qualifier": "%u",
|
|
"cl_kernel_arg_type_qualifier": "%llu",
|
|
"cl_kernel_work_group_info": "%u",
|
|
"cl_kernel_sub_group_info": "%u",
|
|
"cl_event_info": "%u",
|
|
"cl_command_type": "%u",
|
|
"cl_profiling_info": "%u",
|
|
"cl_sampler_properties": "%llu",
|
|
"cl_kernel_exec_info": "%u",
|
|
"cl_device_atomic_capabilities": "%llu",
|
|
"cl_khronos_vendor_id": "%u",
|
|
"cl_version": "%u",
|
|
"cl_device_device_enqueue_capabilities": "%llu",
|
|
}
|
|
|
|
TEMPLATE_HEADER_INCLUDES = """\
|
|
#include <GLES{major}/gl{major}{minor}.h>
|
|
#include <export.h>"""
|
|
|
|
TEMPLATE_SOURCES_INCLUDES = """\
|
|
#include "libGLESv2/entry_points_{header_version}_autogen.h"
|
|
|
|
#include "common/entry_points_enum_autogen.h"
|
|
#include "common/gl_enum_utils.h"
|
|
#include "libANGLE/Context.h"
|
|
#include "libANGLE/Context.inl.h"
|
|
#include "libANGLE/capture/capture_{header_version}_autogen.h"
|
|
#include "libANGLE/validation{validation_header_version}.h"
|
|
#include "libANGLE/entry_points_utils.h"
|
|
#include "libGLESv2/global_state.h"
|
|
|
|
using namespace gl;
|
|
"""
|
|
|
|
GLES_EXT_HEADER_INCLUDES = TEMPLATE_HEADER_INCLUDES.format(
|
|
major="", minor="") + """
|
|
#include <GLES/glext.h>
|
|
#include <GLES2/gl2.h>
|
|
#include <GLES2/gl2ext.h>
|
|
#include <GLES3/gl32.h>
|
|
"""
|
|
|
|
GLES_EXT_SOURCE_INCLUDES = TEMPLATE_SOURCES_INCLUDES.format(
|
|
header_version="gles_ext", validation_header_version="ESEXT") + """
|
|
#include "libANGLE/capture/capture_gles_1_0_autogen.h"
|
|
#include "libANGLE/capture/capture_gles_2_0_autogen.h"
|
|
#include "libANGLE/capture/capture_gles_3_0_autogen.h"
|
|
#include "libANGLE/capture/capture_gles_3_1_autogen.h"
|
|
#include "libANGLE/capture/capture_gles_3_2_autogen.h"
|
|
#include "libANGLE/validationES1.h"
|
|
#include "libANGLE/validationES2.h"
|
|
#include "libANGLE/validationES3.h"
|
|
#include "libANGLE/validationES31.h"
|
|
#include "libANGLE/validationES32.h"
|
|
|
|
using namespace gl;
|
|
"""
|
|
|
|
DESKTOP_GL_HEADER_INCLUDES = """\
|
|
#include <export.h>
|
|
#include "angle_gl.h"
|
|
"""
|
|
|
|
TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES = """\
|
|
#include "libGLESv2/entry_points_{0}_autogen.h"
|
|
|
|
#include "common/gl_enum_utils.h"
|
|
#include "libANGLE/Context.h"
|
|
#include "libANGLE/Context.inl.h"
|
|
#include "libANGLE/capture/capture_gl_{1}_autogen.h"
|
|
#include "libANGLE/validationEGL.h"
|
|
#include "libANGLE/validationES.h"
|
|
#include "libANGLE/validationES1.h"
|
|
#include "libANGLE/validationES2.h"
|
|
#include "libANGLE/validationES3.h"
|
|
#include "libANGLE/validationES31.h"
|
|
#include "libANGLE/validationES32.h"
|
|
#include "libANGLE/validationESEXT.h"
|
|
#include "libANGLE/validationGL{1}_autogen.h"
|
|
#include "libANGLE/entry_points_utils.h"
|
|
#include "libGLESv2/global_state.h"
|
|
|
|
using namespace gl;
|
|
"""
|
|
|
|
EGL_HEADER_INCLUDES = """\
|
|
#include <EGL/egl.h>
|
|
#include <export.h>
|
|
"""
|
|
|
|
EGL_SOURCE_INCLUDES = """\
|
|
#include "libGLESv2/entry_points_egl_autogen.h"
|
|
#include "libGLESv2/entry_points_egl_ext_autogen.h"
|
|
|
|
#include "libANGLE/capture/capture_egl_autogen.h"
|
|
#include "libANGLE/entry_points_utils.h"
|
|
#include "libANGLE/validationEGL_autogen.h"
|
|
#include "libGLESv2/egl_context_lock_impl.h"
|
|
#include "libGLESv2/egl_stubs_autogen.h"
|
|
#include "libGLESv2/egl_ext_stubs_autogen.h"
|
|
#include "libGLESv2/global_state.h"
|
|
|
|
using namespace egl;
|
|
"""
|
|
|
|
EGL_EXT_HEADER_INCLUDES = """\
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <export.h>
|
|
"""
|
|
|
|
EGL_EXT_SOURCE_INCLUDES = """\
|
|
#include "libGLESv2/entry_points_egl_ext_autogen.h"
|
|
|
|
#include "libANGLE/capture/capture_egl_autogen.h"
|
|
#include "libANGLE/entry_points_utils.h"
|
|
#include "libANGLE/validationEGL_autogen.h"
|
|
#include "libGLESv2/egl_context_lock_impl.h"
|
|
#include "libGLESv2/egl_ext_stubs_autogen.h"
|
|
#include "libGLESv2/global_state.h"
|
|
|
|
using namespace egl;
|
|
"""
|
|
|
|
LIBCL_EXPORT_INCLUDES = """
|
|
#include "libOpenCL/dispatch.h"
|
|
"""
|
|
|
|
LIBGLESV2_EXPORT_INCLUDES = """
|
|
#include "angle_gl.h"
|
|
|
|
#include "libGLESv2/entry_points_gles_1_0_autogen.h"
|
|
#include "libGLESv2/entry_points_gles_2_0_autogen.h"
|
|
#include "libGLESv2/entry_points_gles_3_0_autogen.h"
|
|
#include "libGLESv2/entry_points_gles_3_1_autogen.h"
|
|
#include "libGLESv2/entry_points_gles_3_2_autogen.h"
|
|
#include "libGLESv2/entry_points_gles_ext_autogen.h"
|
|
|
|
#if defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)
|
|
# include "libGLESv2/entry_points_gl_1_autogen.h"
|
|
# include "libGLESv2/entry_points_gl_2_autogen.h"
|
|
# include "libGLESv2/entry_points_gl_3_autogen.h"
|
|
# include "libGLESv2/entry_points_gl_4_autogen.h"
|
|
#endif
|
|
|
|
#include "common/event_tracer.h"
|
|
"""
|
|
|
|
LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE = """
|
|
#include "anglebase/no_destructor.h"
|
|
#include "common/system_utils.h"
|
|
|
|
#include <memory>
|
|
|
|
#if defined(ANGLE_USE_EGL_LOADER)
|
|
# include "libEGL/egl_loader_autogen.h"
|
|
#else
|
|
# include "libGLESv2/entry_points_egl_autogen.h"
|
|
# include "libGLESv2/entry_points_egl_ext_autogen.h"
|
|
#endif // defined(ANGLE_USE_EGL_LOADER)
|
|
|
|
namespace
|
|
{
|
|
#if defined(ANGLE_USE_EGL_LOADER)
|
|
bool gLoaded = false;
|
|
void *gEntryPointsLib = nullptr;
|
|
|
|
GenericProc KHRONOS_APIENTRY GlobalLoad(const char *symbol)
|
|
{
|
|
return reinterpret_cast<GenericProc>(angle::GetLibrarySymbol(gEntryPointsLib, symbol));
|
|
}
|
|
|
|
void EnsureEGLLoaded()
|
|
{
|
|
if (gLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::string errorOut;
|
|
gEntryPointsLib = OpenSystemLibraryAndGetError(ANGLE_DISPATCH_LIBRARY, angle::SearchType::ModuleDir, &errorOut);
|
|
if (gEntryPointsLib)
|
|
{
|
|
LoadLibEGL_EGL(GlobalLoad);
|
|
gLoaded = true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Error loading EGL entry points: %s\\n", errorOut.c_str());
|
|
}
|
|
}
|
|
#else
|
|
void EnsureEGLLoaded() {}
|
|
#endif // defined(ANGLE_USE_EGL_LOADER)
|
|
} // anonymous namespace
|
|
"""
|
|
|
|
LIBCL_HEADER_INCLUDES = """\
|
|
#include "angle_cl.h"
|
|
"""
|
|
|
|
LIBCL_SOURCE_INCLUDES = """\
|
|
#include "libGLESv2/entry_points_cl_autogen.h"
|
|
|
|
#include "libANGLE/validationCL_autogen.h"
|
|
#include "libGLESv2/cl_stubs_autogen.h"
|
|
#include "libGLESv2/entry_points_cl_utils.h"
|
|
"""
|
|
|
|
TEMPLATE_EVENT_COMMENT = """\
|
|
// Don't run the EVENT() macro on the EXT_debug_marker entry points.
|
|
// It can interfere with the debug events being set by the caller.
|
|
// """
|
|
|
|
TEMPLATE_CAPTURE_PROTO = "angle::CallCapture Capture%s(%s);"
|
|
|
|
TEMPLATE_VALIDATION_PROTO = "%s Validate%s(%s);"
|
|
|
|
TEMPLATE_CONTEXT_LOCK_PROTO = "ScopedContextMutexLock GetContextLock_%s(%s);"
|
|
|
|
TEMPLATE_WINDOWS_DEF_FILE = """\
|
|
; GENERATED FILE - DO NOT EDIT.
|
|
; Generated by {script_name} using data from {data_source_name}.
|
|
;
|
|
; Copyright 2020 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.
|
|
LIBRARY {lib}
|
|
EXPORTS
|
|
{exports}
|
|
"""
|
|
|
|
TEMPLATE_FRAME_CAPTURE_UTILS_HEADER = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// frame_capture_utils_autogen.h:
|
|
// ANGLE Frame capture types and helper functions.
|
|
|
|
#ifndef COMMON_FRAME_CAPTURE_UTILS_AUTOGEN_H_
|
|
#define COMMON_FRAME_CAPTURE_UTILS_AUTOGEN_H_
|
|
|
|
#include "common/PackedEnums.h"
|
|
|
|
namespace angle
|
|
{{
|
|
enum class ParamType
|
|
{{
|
|
{param_types}
|
|
}};
|
|
|
|
constexpr uint32_t kParamTypeCount = {param_type_count};
|
|
|
|
union ParamValue
|
|
{{
|
|
{param_union_values}
|
|
}};
|
|
|
|
template <ParamType PType, typename T>
|
|
T GetParamVal(const ParamValue &value);
|
|
|
|
{get_param_val_specializations}
|
|
|
|
template <ParamType PType, typename T>
|
|
T GetParamVal(const ParamValue &value)
|
|
{{
|
|
UNREACHABLE();
|
|
return T();
|
|
}}
|
|
|
|
template <typename T>
|
|
T AccessParamValue(ParamType paramType, const ParamValue &value)
|
|
{{
|
|
switch (paramType)
|
|
{{
|
|
{access_param_value_cases}
|
|
}}
|
|
UNREACHABLE();
|
|
return T();
|
|
}}
|
|
|
|
template <ParamType PType, typename T>
|
|
void SetParamVal(T valueIn, ParamValue *valueOut);
|
|
|
|
{set_param_val_specializations}
|
|
|
|
template <ParamType PType, typename T>
|
|
void SetParamVal(T valueIn, ParamValue *valueOut)
|
|
{{
|
|
UNREACHABLE();
|
|
}}
|
|
|
|
template <typename T>
|
|
void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut)
|
|
{{
|
|
switch (paramType)
|
|
{{
|
|
{init_param_value_cases}
|
|
}}
|
|
}}
|
|
|
|
struct CallCapture;
|
|
struct ParamCapture;
|
|
|
|
void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture ¶m);
|
|
const char *ParamTypeToString(ParamType paramType);
|
|
|
|
enum class ResourceIDType
|
|
{{
|
|
{resource_id_types}
|
|
}};
|
|
|
|
ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType);
|
|
const char *GetResourceIDTypeName(ResourceIDType resourceIDType);
|
|
|
|
template <typename ResourceType>
|
|
struct GetResourceIDTypeFromType;
|
|
|
|
{type_to_resource_id_type_structs}
|
|
}} // namespace angle
|
|
|
|
#endif // COMMON_FRAME_CAPTURE_UTILS_AUTOGEN_H_
|
|
"""
|
|
|
|
TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE = """\
|
|
// GENERATED FILE - DO NOT EDIT.
|
|
// Generated by {script_name} using data from {data_source_name}.
|
|
//
|
|
// Copyright 2020 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.
|
|
//
|
|
// frame_capture_utils_autogen.cpp:
|
|
// ANGLE Frame capture types and helper functions.
|
|
|
|
#include "common/frame_capture_utils_autogen.h"
|
|
|
|
#include "common/frame_capture_utils.h"
|
|
|
|
namespace angle
|
|
{{
|
|
void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture ¶m)
|
|
{{
|
|
switch (param.type)
|
|
{{
|
|
{write_param_type_to_stream_cases}
|
|
default:
|
|
os << "unknown";
|
|
break;
|
|
}}
|
|
}}
|
|
|
|
const char *ParamTypeToString(ParamType paramType)
|
|
{{
|
|
switch (paramType)
|
|
{{
|
|
{param_type_to_string_cases}
|
|
default:
|
|
UNREACHABLE();
|
|
return "unknown";
|
|
}}
|
|
}}
|
|
|
|
ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType)
|
|
{{
|
|
switch (paramType)
|
|
{{
|
|
{param_type_resource_id_cases}
|
|
default:
|
|
return ResourceIDType::InvalidEnum;
|
|
}}
|
|
}}
|
|
|
|
const char *GetResourceIDTypeName(ResourceIDType resourceIDType)
|
|
{{
|
|
switch (resourceIDType)
|
|
{{
|
|
{resource_id_type_name_cases}
|
|
default:
|
|
UNREACHABLE();
|
|
return "GetResourceIDTypeName error";
|
|
}}
|
|
}}
|
|
}} // namespace angle
|
|
"""
|
|
|
|
TEMPLATE_GET_PARAM_VAL_SPECIALIZATION = """\
|
|
template <>
|
|
inline {type} GetParamVal<ParamType::T{enum}, {type}>(const ParamValue &value)
|
|
{{
|
|
return value.{union_name};
|
|
}}"""
|
|
|
|
TEMPLATE_ACCESS_PARAM_VALUE_CASE = """\
|
|
case ParamType::T{enum}:
|
|
return GetParamVal<ParamType::T{enum}, T>(value);"""
|
|
|
|
TEMPLATE_SET_PARAM_VAL_SPECIALIZATION = """\
|
|
template <>
|
|
inline void SetParamVal<ParamType::T{enum}>({type} valueIn, ParamValue *valueOut)
|
|
{{
|
|
valueOut->{union_name} = valueIn;
|
|
}}"""
|
|
|
|
TEMPLATE_INIT_PARAM_VALUE_CASE = """\
|
|
case ParamType::T{enum}:
|
|
SetParamVal<ParamType::T{enum}>(valueIn, valueOut);
|
|
break;"""
|
|
|
|
TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE = """\
|
|
case ParamType::T{enum_in}:
|
|
WriteParamValueReplay<ParamType::T{enum_out}>(os, call, param.value.{union_name});
|
|
break;"""
|
|
|
|
TEMPLATE_PARAM_TYPE_TO_STRING_CASE = """\
|
|
case ParamType::T{enum}:
|
|
return "{type}";"""
|
|
|
|
TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE = """\
|
|
case ParamType::T{enum}:
|
|
return ResourceIDType::{resource_id_type};"""
|
|
|
|
TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE = """\
|
|
case ResourceIDType::{resource_id_type}:
|
|
return "{resource_id_type}";"""
|
|
|
|
CL_PACKED_TYPES = {
|
|
# Enums
|
|
"cl_platform_info": "PlatformInfo",
|
|
"cl_device_info": "DeviceInfo",
|
|
"cl_context_info": "ContextInfo",
|
|
"cl_command_queue_info": "CommandQueueInfo",
|
|
"cl_mem_object_type": "MemObjectType",
|
|
"cl_mem_info": "MemInfo",
|
|
"cl_image_info": "ImageInfo",
|
|
"cl_pipe_info": "PipeInfo",
|
|
"cl_addressing_mode": "AddressingMode",
|
|
"cl_filter_mode": "FilterMode",
|
|
"cl_sampler_info": "SamplerInfo",
|
|
"cl_program_info": "ProgramInfo",
|
|
"cl_program_build_info": "ProgramBuildInfo",
|
|
"cl_kernel_info": "KernelInfo",
|
|
"cl_kernel_arg_info": "KernelArgInfo",
|
|
"cl_kernel_work_group_info": "KernelWorkGroupInfo",
|
|
"cl_kernel_sub_group_info": "KernelSubGroupInfo",
|
|
"cl_kernel_exec_info": "KernelExecInfo",
|
|
"cl_event_info": "EventInfo",
|
|
"cl_profiling_info": "ProfilingInfo",
|
|
# Bit fields
|
|
"cl_device_type": "DeviceType",
|
|
"cl_device_fp_config": "DeviceFpConfig",
|
|
"cl_device_exec_capabilities": "DeviceExecCapabilities",
|
|
"cl_device_svm_capabilities": "DeviceSvmCapabilities",
|
|
"cl_command_queue_properties": "CommandQueueProperties",
|
|
"cl_device_affinity_domain": "DeviceAffinityDomain",
|
|
"cl_mem_flags": "MemFlags",
|
|
"cl_svm_mem_flags": "SVM_MemFlags",
|
|
"cl_mem_migration_flags": "MemMigrationFlags",
|
|
"cl_map_flags": "MapFlags",
|
|
"cl_kernel_arg_type_qualifier": "KernelArgTypeQualifier",
|
|
"cl_device_atomic_capabilities": "DeviceAtomicCapabilities",
|
|
"cl_device_device_enqueue_capabilities": "DeviceEnqueueCapabilities",
|
|
}
|
|
|
|
EGL_PACKED_TYPES = {
|
|
"EGLContext": "gl::ContextID",
|
|
"EGLConfig": "egl::Config *",
|
|
"EGLDeviceEXT": "egl::Device *",
|
|
"EGLDisplay": "egl::Display *",
|
|
"EGLImage": "ImageID",
|
|
"EGLImageKHR": "ImageID",
|
|
"EGLStreamKHR": "egl::Stream *",
|
|
"EGLSurface": "SurfaceID",
|
|
"EGLSync": "egl::SyncID",
|
|
"EGLSyncKHR": "egl::SyncID",
|
|
}
|
|
|
|
CAPTURE_BLOCKLIST = ['eglGetProcAddress']
|
|
|
|
|
|
def is_aliasing_excepted(api, cmd_name):
|
|
return api == apis.GLES and cmd_name in ALIASING_EXCEPTIONS
|
|
|
|
|
|
def is_allowed_with_active_pixel_local_storage(name):
|
|
return name in PLS_ALLOW_LIST or any(
|
|
[fnmatch.fnmatchcase(name, x) for x in PLS_ALLOW_WILDCARDS])
|
|
|
|
|
|
def get_validation_expression(cmd_name, entry_point_name, internal_params):
|
|
name = strip_api_prefix(cmd_name)
|
|
expr = "Validate{name}({params})".format(
|
|
name=name, params=", ".join(["context", entry_point_name] + internal_params))
|
|
if not is_allowed_with_active_pixel_local_storage(name):
|
|
expr = "(ValidatePixelLocalStorageInactive(context, {entry_point_name}) && {expr})".format(
|
|
entry_point_name=entry_point_name, expr=expr)
|
|
return expr
|
|
|
|
|
|
def entry_point_export(api):
|
|
if api == apis.CL:
|
|
return ""
|
|
return "ANGLE_EXPORT "
|
|
|
|
|
|
def entry_point_prefix(api):
|
|
if api == apis.CL:
|
|
return "cl"
|
|
if api == apis.GLES:
|
|
return "GL_"
|
|
return api + "_"
|
|
|
|
|
|
def get_api_entry_def(api):
|
|
if api == apis.EGL:
|
|
return "EGLAPIENTRY"
|
|
elif api == apis.CL:
|
|
return "CL_API_CALL"
|
|
else:
|
|
return "GL_APIENTRY"
|
|
|
|
|
|
def get_stubs_header_template(api):
|
|
if api == apis.CL:
|
|
return TEMPLATE_CL_STUBS_HEADER
|
|
elif api == apis.EGL:
|
|
return TEMPLATE_EGL_STUBS_HEADER
|
|
else:
|
|
return ""
|
|
|
|
|
|
def format_entry_point_decl(api, cmd_name, proto, params):
|
|
comma_if_needed = ", " if len(params) > 0 else ""
|
|
stripped = strip_api_prefix(cmd_name)
|
|
return TEMPLATE_ENTRY_POINT_DECL.format(
|
|
angle_export=entry_point_export(api),
|
|
export_def=get_api_entry_def(api),
|
|
name="%s%s" % (entry_point_prefix(api), stripped),
|
|
return_type=proto[:-len(cmd_name)].strip(),
|
|
params=", ".join(params),
|
|
comma_if_needed=comma_if_needed)
|
|
|
|
|
|
# Returns index range of identifier in function parameter
|
|
def find_name_range(param):
|
|
|
|
def is_allowed_in_identifier(char):
|
|
return char.isalpha() or char.isdigit() or char == "_"
|
|
|
|
# If type is a function declaration, only search in first parentheses
|
|
left_paren = param.find("(")
|
|
if left_paren >= 0:
|
|
min = left_paren + 1
|
|
end = param.index(")")
|
|
else:
|
|
min = 0
|
|
end = len(param)
|
|
|
|
# Find last identifier in search range
|
|
while end > min and not is_allowed_in_identifier(param[end - 1]):
|
|
end -= 1
|
|
if end == min:
|
|
raise ValueError
|
|
start = end - 1
|
|
while start > min and is_allowed_in_identifier(param[start - 1]):
|
|
start -= 1
|
|
return start, end
|
|
|
|
|
|
def just_the_type(param):
|
|
start, end = find_name_range(param)
|
|
return param[:start].strip() + param[end:].strip()
|
|
|
|
|
|
def just_the_name(param):
|
|
start, end = find_name_range(param)
|
|
return param[start:end]
|
|
|
|
|
|
def make_param(param_type, param_name):
|
|
|
|
def insert_name(param_type, param_name, pos):
|
|
return param_type[:pos] + " " + param_name + param_type[pos:]
|
|
|
|
# If type is a function declaration, insert identifier before first closing parentheses
|
|
left_paren = param_type.find("(")
|
|
if left_paren >= 0:
|
|
right_paren = param_type.index(")")
|
|
return insert_name(param_type, param_name, right_paren)
|
|
|
|
# If type is an array declaration, insert identifier before brackets
|
|
brackets = param_type.find("[")
|
|
if brackets >= 0:
|
|
return insert_name(param_type, param_name, brackets)
|
|
|
|
# Otherwise just append identifier
|
|
return param_type + " " + param_name
|
|
|
|
|
|
def just_the_type_packed(param, entry):
|
|
name = just_the_name(param)
|
|
if name in entry:
|
|
return entry[name]
|
|
else:
|
|
return just_the_type(param)
|
|
|
|
|
|
def just_the_name_packed(param, reserved_set):
|
|
name = just_the_name(param)
|
|
if name in reserved_set:
|
|
return name + 'Packed'
|
|
else:
|
|
return name
|
|
|
|
|
|
def is_unsigned_long_format(fmt):
|
|
return fmt == UNSIGNED_LONG_LONG_FORMAT or fmt == HEX_LONG_LONG_FORMAT
|
|
|
|
|
|
def param_print_argument(api, command_node, param):
|
|
name_only = just_the_name(param)
|
|
type_only = just_the_type(param)
|
|
|
|
if "*" not in param and type_only not in FORMAT_DICT:
|
|
print(" ".join(param))
|
|
raise Exception("Missing '%s %s' from '%s' entry point" %
|
|
(type_only, name_only, registry_xml.get_cmd_name(command_node)))
|
|
|
|
if "*" in param or FORMAT_DICT[type_only] == POINTER_FORMAT:
|
|
return "(uintptr_t)%s" % name_only
|
|
|
|
if is_unsigned_long_format(FORMAT_DICT[type_only]):
|
|
return "static_cast<unsigned long long>(%s)" % name_only
|
|
|
|
if type_only == "GLboolean":
|
|
return "GLbooleanToString(%s)" % name_only
|
|
|
|
if type_only == "GLbitfield":
|
|
group_name = find_gl_enum_group_in_command(command_node, name_only)
|
|
return "GLbitfieldToString(%s::%s, %s).c_str()" % (api_enums[api], group_name, name_only)
|
|
|
|
if type_only == "GLenum":
|
|
group_name = find_gl_enum_group_in_command(command_node, name_only)
|
|
return "GLenumToString(%s::%s, %s)" % (api_enums[api], group_name, name_only)
|
|
|
|
return name_only
|
|
|
|
|
|
def param_format_string(param):
|
|
if "*" in param:
|
|
return just_the_name(param) + " = 0x%016\" PRIxPTR \""
|
|
else:
|
|
type_only = just_the_type(param)
|
|
if type_only not in FORMAT_DICT:
|
|
raise Exception(type_only + " is not a known type in 'FORMAT_DICT'")
|
|
|
|
return just_the_name(param) + " = " + FORMAT_DICT[type_only]
|
|
|
|
|
|
def is_context_lost_acceptable_cmd(cmd_name):
|
|
lost_context_acceptable_cmds = [
|
|
"glGetError",
|
|
"glGetSync",
|
|
"glGetQueryObjecti",
|
|
"glGetProgramiv",
|
|
"glGetGraphicsResetStatus",
|
|
"glGetShaderiv",
|
|
]
|
|
|
|
for context_lost_entry_pont in lost_context_acceptable_cmds:
|
|
if cmd_name.startswith(context_lost_entry_pont):
|
|
return True
|
|
return False
|
|
|
|
|
|
def get_context_getter_function(cmd_name):
|
|
if is_context_lost_acceptable_cmd(cmd_name):
|
|
return "GetGlobalContext()"
|
|
|
|
return "GetValidGlobalContext()"
|
|
|
|
|
|
def get_valid_context_check(cmd_name):
|
|
return "context"
|
|
|
|
|
|
def get_constext_lost_error_generator(cmd_name):
|
|
# Don't generate context lost errors on commands that accept lost contexts
|
|
if is_context_lost_acceptable_cmd(cmd_name):
|
|
return ""
|
|
|
|
return "GenerateContextLostErrorOnCurrentGlobalContext();"
|
|
|
|
|
|
def strip_suffix(api, name):
|
|
# For commands where aliasing is excepted, keep the suffix
|
|
if is_aliasing_excepted(api, name):
|
|
return name
|
|
|
|
for suffix in registry_xml.strip_suffixes:
|
|
if name.endswith(suffix):
|
|
name = name[0:-len(suffix)]
|
|
return name
|
|
|
|
|
|
def find_gl_enum_group_in_command(command_node, param_name):
|
|
group_name = None
|
|
for param_node in command_node.findall('./param'):
|
|
if param_node.find('./name').text == param_name:
|
|
group_name = param_node.attrib.get('group', None)
|
|
break
|
|
|
|
if group_name is None or group_name in registry_xml.unsupported_enum_group_names:
|
|
group_name = registry_xml.default_enum_group_name
|
|
|
|
return group_name
|
|
|
|
|
|
def get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types, params):
|
|
# Always strip the suffix when querying packed enums.
|
|
result = cmd_packed_gl_enums.get(strip_suffix(api, cmd_name), {})
|
|
for param in params:
|
|
param_type = just_the_type(param)
|
|
if param_type in packed_param_types:
|
|
result[just_the_name(param)] = packed_param_types[param_type]
|
|
return result
|
|
|
|
|
|
def get_def_template(api, cmd_name, return_type, has_errcode_ret):
|
|
if return_type == "void":
|
|
if api == apis.EGL:
|
|
return TEMPLATE_EGL_ENTRY_POINT_NO_RETURN
|
|
elif api == apis.CL:
|
|
return TEMPLATE_CL_ENTRY_POINT_NO_RETURN
|
|
else:
|
|
return TEMPLATE_GLES_ENTRY_POINT_NO_RETURN
|
|
elif return_type == "cl_int":
|
|
return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR
|
|
else:
|
|
if api == apis.EGL:
|
|
return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN
|
|
elif api == apis.CL:
|
|
if has_errcode_ret:
|
|
return TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET
|
|
else:
|
|
return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER
|
|
else:
|
|
return TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN
|
|
|
|
|
|
def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packed_enums,
|
|
packed_param_types, ep_to_object):
|
|
packed_enums = get_packed_enums(api, cmd_packed_enums, cmd_name, packed_param_types, params)
|
|
internal_params = [just_the_name_packed(param, packed_enums) for param in params]
|
|
if internal_params and internal_params[-1] == "errcode_ret":
|
|
internal_params.pop()
|
|
has_errcode_ret = True
|
|
else:
|
|
has_errcode_ret = False
|
|
|
|
internal_context_lock_params = [
|
|
just_the_name_packed(param, packed_enums) for param in params if just_the_type_packed(
|
|
param, packed_enums) in ["Thread *", "egl::Display *", "gl::ContextID"] or
|
|
just_the_name_packed(param, packed_enums) in ["attribute"]
|
|
]
|
|
|
|
packed_gl_enum_conversions = []
|
|
|
|
for param in params:
|
|
name = just_the_name(param)
|
|
|
|
if name in packed_enums:
|
|
internal_name = name + "Packed"
|
|
internal_type = packed_enums[name]
|
|
packed_gl_enum_conversions += [
|
|
"\n " + internal_type + " " + internal_name + " = PackParam<" +
|
|
internal_type + ">(" + name + ");"
|
|
]
|
|
|
|
pass_params = [param_print_argument(api, command_node, param) for param in params]
|
|
format_params = [param_format_string(param) for param in params]
|
|
return_type = proto[:-len(cmd_name)].strip()
|
|
initialization = "InitBackEnds(%s);\n" % INIT_DICT[cmd_name] if cmd_name in INIT_DICT else ""
|
|
event_comment = TEMPLATE_EVENT_COMMENT if cmd_name in NO_EVENT_MARKER_EXCEPTIONS_LIST else ""
|
|
name_lower_no_suffix = strip_suffix(api, cmd_name[2:3].lower() + cmd_name[3:])
|
|
entry_point_name = "angle::EntryPoint::GL" + strip_api_prefix(cmd_name)
|
|
|
|
format_params = {
|
|
"name":
|
|
strip_api_prefix(cmd_name),
|
|
"name_lower_no_suffix":
|
|
name_lower_no_suffix,
|
|
"return_type":
|
|
return_type,
|
|
"params":
|
|
", ".join(params),
|
|
"internal_params":
|
|
", ".join(internal_params),
|
|
"internal_context_lock_params":
|
|
", ".join(internal_context_lock_params),
|
|
"initialization":
|
|
initialization,
|
|
"packed_gl_enum_conversions":
|
|
"".join(packed_gl_enum_conversions),
|
|
"pass_params":
|
|
", ".join(pass_params),
|
|
"comma_if_needed":
|
|
", " if len(params) > 0 else "",
|
|
"comma_if_needed_context_lock":
|
|
", " if len(internal_context_lock_params) > 0 else "",
|
|
"gl_capture_params":
|
|
", ".join(["context"] + internal_params),
|
|
"egl_capture_params":
|
|
", ".join(["thread"] + internal_params),
|
|
"validation_expression":
|
|
get_validation_expression(cmd_name, entry_point_name, internal_params),
|
|
"format_params":
|
|
", ".join(format_params),
|
|
"context_getter":
|
|
get_context_getter_function(cmd_name),
|
|
"valid_context_check":
|
|
get_valid_context_check(cmd_name),
|
|
"constext_lost_error_generator":
|
|
get_constext_lost_error_generator(cmd_name),
|
|
"event_comment":
|
|
event_comment,
|
|
"labeled_object":
|
|
get_egl_entry_point_labeled_object(ep_to_object, cmd_name, params, packed_enums),
|
|
"context_lock":
|
|
get_context_lock(api, cmd_name),
|
|
"preamble":
|
|
get_preamble(api, cmd_name, params),
|
|
"epilog":
|
|
get_epilog(api, cmd_name),
|
|
}
|
|
|
|
template = get_def_template(api, cmd_name, return_type, has_errcode_ret)
|
|
return template.format(**format_params)
|
|
|
|
|
|
def get_capture_param_type_name(param_type):
|
|
pointer_count = param_type.count("*")
|
|
is_const = "const" in param_type.split()
|
|
|
|
param_type = param_type.replace("*", "")
|
|
param_type = param_type.replace("&", "")
|
|
param_type = param_type.replace("const", "")
|
|
param_type = param_type.replace("struct", "")
|
|
param_type = param_type.replace("egl::",
|
|
"egl_" if pointer_count or param_type == 'egl::SyncID' else "")
|
|
param_type = param_type.replace("gl::", "")
|
|
param_type = param_type.strip()
|
|
|
|
if is_const and param_type != 'AttributeMap':
|
|
param_type += "Const"
|
|
for x in range(pointer_count):
|
|
param_type += "Pointer"
|
|
|
|
return param_type
|
|
|
|
|
|
def format_capture_method(api, command, cmd_name, proto, params, all_param_types,
|
|
capture_pointer_funcs, cmd_packed_gl_enums, packed_param_types):
|
|
|
|
context_param_typed = 'egl::Thread *thread' if api == apis.EGL else 'const State &glState'
|
|
context_param_name = 'thread' if api == apis.EGL else 'glState'
|
|
|
|
packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
|
|
params)
|
|
|
|
params_with_type = get_internal_params(api, cmd_name,
|
|
[context_param_typed, "bool isCallValid"] + params,
|
|
cmd_packed_gl_enums, packed_param_types)
|
|
params_just_name = ", ".join(
|
|
[context_param_name, "isCallValid"] +
|
|
[just_the_name_packed(param, packed_gl_enums) for param in params])
|
|
|
|
parameter_captures = []
|
|
for param in params:
|
|
|
|
param_name = just_the_name_packed(param, packed_gl_enums)
|
|
param_type = just_the_type_packed(param, packed_gl_enums).strip()
|
|
|
|
if 'AttributeMap' in param_type:
|
|
capture = 'paramBuffer.addParam(CaptureAttributeMap(%s));' % param_name
|
|
parameter_captures += [capture]
|
|
continue
|
|
|
|
pointer_count = param_type.count("*")
|
|
capture_param_type = get_capture_param_type_name(param_type)
|
|
|
|
# With EGL capture, we don't currently support capturing specific pointer params.
|
|
if pointer_count > 0 and api != apis.EGL:
|
|
params = params_just_name
|
|
capture_name = "Capture%s_%s" % (strip_api_prefix(cmd_name), param_name)
|
|
capture = TEMPLATE_PARAMETER_CAPTURE_POINTER.format(
|
|
name=param_name,
|
|
type=capture_param_type,
|
|
capture_name=capture_name,
|
|
params=params,
|
|
cast_type=param_type)
|
|
|
|
capture_pointer_func = TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC.format(
|
|
name=capture_name, params=params_with_type + ", angle::ParamCapture *paramCapture")
|
|
capture_pointer_funcs += [capture_pointer_func]
|
|
elif capture_param_type in ('GLenum', 'GLbitfield'):
|
|
gl_enum_group = find_gl_enum_group_in_command(command, param_name)
|
|
capture = TEMPLATE_PARAMETER_CAPTURE_GL_ENUM.format(
|
|
name=param_name,
|
|
type=capture_param_type,
|
|
api_enum=api_enums[api],
|
|
group=gl_enum_group)
|
|
else:
|
|
capture = TEMPLATE_PARAMETER_CAPTURE_VALUE.format(
|
|
name=param_name, type=capture_param_type)
|
|
|
|
# For specific methods we can't easily parse their types. Work around this by omitting
|
|
# parameter captures, but keeping the capture method as a mostly empty stub.
|
|
if cmd_name not in CAPTURE_BLOCKLIST:
|
|
all_param_types.add(capture_param_type)
|
|
parameter_captures += [capture]
|
|
|
|
return_type = proto[:-len(cmd_name)].strip()
|
|
capture_return_type = get_capture_param_type_name(return_type)
|
|
if capture_return_type != 'void':
|
|
if cmd_name in CAPTURE_BLOCKLIST:
|
|
params_with_type += ", %s returnValue" % capture_return_type
|
|
else:
|
|
all_param_types.add(capture_return_type)
|
|
|
|
format_args = {
|
|
"api_upper": "EGL" if api == apis.EGL else "GL",
|
|
"full_name": cmd_name,
|
|
"short_name": strip_api_prefix(cmd_name),
|
|
"params_with_type": params_with_type,
|
|
"params_just_name": params_just_name,
|
|
"parameter_captures": "\n ".join(parameter_captures),
|
|
"return_value_type_original": return_type,
|
|
"return_value_type_custom": capture_return_type,
|
|
}
|
|
|
|
if return_type == "void" or cmd_name in CAPTURE_BLOCKLIST:
|
|
return TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE.format(**format_args)
|
|
else:
|
|
return TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE.format(**format_args)
|
|
|
|
|
|
def const_pointer_type(param, packed_gl_enums):
|
|
type = just_the_type_packed(param, packed_gl_enums)
|
|
if just_the_name(param) == "errcode_ret" or "(" in type:
|
|
return type
|
|
elif "**" in type and "const" not in type:
|
|
return type.replace("**", "* const *")
|
|
elif "*" in type and "const" not in type:
|
|
return type.replace("*", "*const ") if "[]" in type else "const " + type
|
|
else:
|
|
return type
|
|
|
|
|
|
def get_internal_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
|
|
packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
|
|
params)
|
|
return ", ".join([
|
|
make_param(
|
|
just_the_type_packed(param, packed_gl_enums),
|
|
just_the_name_packed(param, packed_gl_enums)) for param in params
|
|
])
|
|
|
|
|
|
def get_validation_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
|
|
packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
|
|
params)
|
|
last = -1 if params and just_the_name(params[-1]) == "errcode_ret" else None
|
|
return ", ".join([
|
|
make_param(
|
|
const_pointer_type(param, packed_gl_enums),
|
|
just_the_name_packed(param, packed_gl_enums)) for param in params[:last]
|
|
])
|
|
|
|
|
|
def get_context_lock_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
|
|
packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
|
|
params)
|
|
return ", ".join([
|
|
make_param(
|
|
just_the_type_packed(param, packed_gl_enums),
|
|
just_the_name_packed(param, packed_gl_enums))
|
|
for param in params
|
|
if just_the_type_packed(
|
|
param, packed_gl_enums) in ["Thread *", "egl::Display *", "gl::ContextID"] or
|
|
just_the_name_packed(param, packed_gl_enums) in ["attribute"]
|
|
])
|
|
|
|
|
|
def format_context_decl(api, cmd_name, proto, params, template, cmd_packed_gl_enums,
|
|
packed_param_types):
|
|
internal_params = get_internal_params(api, cmd_name, params, cmd_packed_gl_enums,
|
|
packed_param_types)
|
|
|
|
return_type = proto[:-len(cmd_name)].strip()
|
|
name_lower_no_suffix = cmd_name[2:3].lower() + cmd_name[3:]
|
|
name_lower_no_suffix = strip_suffix(api, name_lower_no_suffix)
|
|
maybe_const = " const" if name_lower_no_suffix.startswith(
|
|
"is") and name_lower_no_suffix[2].isupper() else ""
|
|
|
|
return template.format(
|
|
return_type=return_type,
|
|
name_lower_no_suffix=name_lower_no_suffix,
|
|
internal_params=internal_params,
|
|
maybe_const=maybe_const)
|
|
|
|
|
|
def format_entry_point_export(cmd_name, proto, params, template):
|
|
internal_params = [just_the_name(param) for param in params]
|
|
return_type = proto[:-len(cmd_name)].strip()
|
|
|
|
return template.format(
|
|
name=strip_api_prefix(cmd_name),
|
|
return_type=return_type,
|
|
params=", ".join(params),
|
|
internal_params=", ".join(internal_params))
|
|
|
|
|
|
def format_validation_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
|
|
if api == apis.CL:
|
|
return_type = "cl_int"
|
|
else:
|
|
return_type = "bool"
|
|
if api in [apis.GL, apis.GLES]:
|
|
with_extra_params = ["Context *context"] + ["angle::EntryPoint entryPoint"] + params
|
|
elif api == apis.EGL:
|
|
with_extra_params = ["ValidationContext *val"] + params
|
|
else:
|
|
with_extra_params = params
|
|
internal_params = get_validation_params(api, cmd_name, with_extra_params, cmd_packed_gl_enums,
|
|
packed_param_types)
|
|
return TEMPLATE_VALIDATION_PROTO % (return_type, strip_api_prefix(cmd_name), internal_params)
|
|
|
|
|
|
def format_context_lock_proto(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
|
|
with_extra_params = ["Thread *thread"] + params
|
|
internal_params = get_context_lock_params(api, cmd_name, with_extra_params,
|
|
cmd_packed_gl_enums, packed_param_types)
|
|
return TEMPLATE_CONTEXT_LOCK_PROTO % (strip_api_prefix(cmd_name), internal_params)
|
|
|
|
|
|
def format_capture_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
|
|
context_param_typed = 'egl::Thread *thread' if api == apis.EGL else 'const State &glState'
|
|
internal_params = get_internal_params(api, cmd_name,
|
|
[context_param_typed, "bool isCallValid"] + params,
|
|
cmd_packed_gl_enums, packed_param_types)
|
|
return_type = proto[:-len(cmd_name)].strip()
|
|
if return_type != "void":
|
|
internal_params += ", %s returnValue" % return_type
|
|
return TEMPLATE_CAPTURE_PROTO % (strip_api_prefix(cmd_name), internal_params)
|
|
|
|
|
|
def path_to(folder, file):
|
|
return os.path.join(script_relative(".."), "src", folder, file)
|
|
|
|
|
|
class ANGLEEntryPoints(registry_xml.EntryPoints):
|
|
|
|
def __init__(self,
|
|
api,
|
|
xml,
|
|
commands,
|
|
all_param_types,
|
|
cmd_packed_enums,
|
|
export_template=TEMPLATE_GL_ENTRY_POINT_EXPORT,
|
|
packed_param_types=[],
|
|
ep_to_object={}):
|
|
super().__init__(api, xml, commands)
|
|
|
|
self.decls = []
|
|
self.defs = []
|
|
self.export_defs = []
|
|
self.validation_protos = []
|
|
self.context_lock_protos = []
|
|
self.capture_protos = []
|
|
self.capture_methods = []
|
|
self.capture_pointer_funcs = []
|
|
|
|
for (cmd_name, command_node, param_text, proto_text) in self.get_infos():
|
|
self.decls.append(format_entry_point_decl(self.api, cmd_name, proto_text, param_text))
|
|
self.defs.append(
|
|
format_entry_point_def(self.api, command_node, cmd_name, proto_text, param_text,
|
|
cmd_packed_enums, packed_param_types, ep_to_object))
|
|
|
|
self.export_defs.append(
|
|
format_entry_point_export(cmd_name, proto_text, param_text, export_template))
|
|
|
|
self.validation_protos.append(
|
|
format_validation_proto(self.api, cmd_name, proto_text, param_text,
|
|
cmd_packed_enums, packed_param_types))
|
|
|
|
if api == apis.EGL:
|
|
self.context_lock_protos.append(
|
|
format_context_lock_proto(api, cmd_name, param_text, cmd_packed_enums,
|
|
packed_param_types))
|
|
|
|
self.capture_protos.append(
|
|
format_capture_proto(self.api, cmd_name, proto_text, param_text, cmd_packed_enums,
|
|
packed_param_types))
|
|
self.capture_methods.append(
|
|
format_capture_method(self.api, command_node, cmd_name, proto_text, param_text,
|
|
all_param_types, self.capture_pointer_funcs,
|
|
cmd_packed_enums, packed_param_types))
|
|
|
|
# Ensure we store GLint64 in the param types for use with the replay interpreter.
|
|
all_param_types.add('GLint64')
|
|
|
|
|
|
class GLEntryPoints(ANGLEEntryPoints):
|
|
|
|
all_param_types = set()
|
|
|
|
def __init__(self, api, xml, commands):
|
|
super().__init__(api, xml, commands, GLEntryPoints.all_param_types,
|
|
GLEntryPoints.get_packed_enums())
|
|
|
|
_packed_enums = None
|
|
|
|
@classmethod
|
|
def get_packed_enums(cls):
|
|
if not cls._packed_enums:
|
|
with open(script_relative('entry_point_packed_gl_enums.json')) as f:
|
|
cls._packed_enums = json.loads(f.read())
|
|
return cls._packed_enums
|
|
|
|
|
|
class EGLEntryPoints(ANGLEEntryPoints):
|
|
|
|
all_param_types = set()
|
|
|
|
def __init__(self, xml, commands):
|
|
super().__init__(
|
|
apis.EGL,
|
|
xml,
|
|
commands,
|
|
EGLEntryPoints.all_param_types,
|
|
EGLEntryPoints.get_packed_enums(),
|
|
export_template=TEMPLATE_EGL_ENTRY_POINT_EXPORT,
|
|
packed_param_types=EGL_PACKED_TYPES,
|
|
ep_to_object=EGLEntryPoints._get_ep_to_object())
|
|
|
|
_ep_to_object = None
|
|
|
|
@classmethod
|
|
def _get_ep_to_object(cls):
|
|
|
|
if cls._ep_to_object:
|
|
return cls._ep_to_object
|
|
|
|
with open(EGL_GET_LABELED_OBJECT_DATA_PATH) as f:
|
|
try:
|
|
spec_json = json.loads(f.read())
|
|
except ValueError:
|
|
raise Exception("Could not decode JSON from %s" % EGL_GET_LABELED_OBJECT_DATA_PATH)
|
|
|
|
# Construct a mapping from EP to type. Fill in the gaps with Display/None.
|
|
cls._ep_to_object = {}
|
|
|
|
for category, eps in spec_json.items():
|
|
if category == 'description':
|
|
continue
|
|
for ep in eps:
|
|
cls._ep_to_object[ep] = category
|
|
|
|
return cls._ep_to_object
|
|
|
|
_packed_enums = None
|
|
|
|
@classmethod
|
|
def get_packed_enums(cls):
|
|
if not cls._packed_enums:
|
|
with open(script_relative('entry_point_packed_egl_enums.json')) as f:
|
|
cls._packed_enums = json.loads(f.read())
|
|
return cls._packed_enums
|
|
|
|
|
|
class GLXEntryPoints(ANGLEEntryPoints):
|
|
|
|
all_param_types = set()
|
|
|
|
def __init__(self, xml, commands):
|
|
super().__init__(
|
|
apis.GLX,
|
|
xml,
|
|
commands,
|
|
GLXEntryPoints.all_param_types,
|
|
GLXEntryPoints.get_packed_enums(),
|
|
export_template=TEMPLATE_GLX_ENTRY_POINT_EXPORT,
|
|
packed_param_types=GLX_PACKED_TYPES)
|
|
|
|
|
|
class CLEntryPoints(ANGLEEntryPoints):
|
|
|
|
all_param_types = set()
|
|
|
|
def __init__(self, xml, commands):
|
|
super().__init__(
|
|
apis.CL,
|
|
xml,
|
|
commands,
|
|
CLEntryPoints.all_param_types,
|
|
CLEntryPoints.get_packed_enums(),
|
|
export_template=TEMPLATE_CL_ENTRY_POINT_EXPORT,
|
|
packed_param_types=CL_PACKED_TYPES)
|
|
|
|
@classmethod
|
|
def get_packed_enums(cls):
|
|
return {}
|
|
|
|
|
|
def get_decls(api,
|
|
formatter,
|
|
all_commands,
|
|
gles_commands,
|
|
already_included,
|
|
cmd_packed_gl_enums,
|
|
packed_param_types=[]):
|
|
decls = []
|
|
for command in all_commands:
|
|
proto = command.find('proto')
|
|
cmd_name = proto.find('name').text
|
|
|
|
if cmd_name not in gles_commands:
|
|
continue
|
|
|
|
name_no_suffix = strip_suffix(api, cmd_name)
|
|
if name_no_suffix in already_included:
|
|
continue
|
|
|
|
param_text = ["".join(param.itertext()) for param in command.findall('param')]
|
|
proto_text = "".join(proto.itertext())
|
|
decls.append(
|
|
format_context_decl(api, cmd_name, proto_text, param_text, formatter,
|
|
cmd_packed_gl_enums, packed_param_types))
|
|
|
|
return decls
|
|
|
|
|
|
def get_glext_decls(all_commands, gles_commands, version):
|
|
glext_ptrs = []
|
|
glext_protos = []
|
|
is_gles1 = False
|
|
|
|
if (version == ""):
|
|
is_gles1 = True
|
|
|
|
for command in all_commands:
|
|
proto = command.find('proto')
|
|
cmd_name = proto.find('name').text
|
|
|
|
if cmd_name not in gles_commands:
|
|
continue
|
|
|
|
param_text = ["".join(param.itertext()) for param in command.findall('param')]
|
|
proto_text = "".join(proto.itertext())
|
|
|
|
return_type = proto_text[:-len(cmd_name)]
|
|
params = ", ".join(param_text)
|
|
|
|
format_params = {
|
|
"apicall": "GL_API" if is_gles1 else "GL_APICALL",
|
|
"name": cmd_name,
|
|
"name_upper": cmd_name.upper(),
|
|
"return_type": return_type,
|
|
"params": params,
|
|
}
|
|
|
|
glext_ptrs.append(TEMPLATE_GLEXT_FUNCTION_POINTER.format(**format_params))
|
|
glext_protos.append(TEMPLATE_GLEXT_FUNCTION_PROTOTYPE.format(**format_params))
|
|
|
|
return glext_ptrs, glext_protos
|
|
|
|
|
|
def write_file(annotation, comment, template, entry_points, suffix, includes, lib, file):
|
|
|
|
content = template.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name=file,
|
|
annotation_lower=annotation.lower(),
|
|
annotation_upper=annotation.upper(),
|
|
comment=comment,
|
|
lib=lib.upper(),
|
|
includes=includes,
|
|
entry_points=entry_points)
|
|
|
|
path = path_to(lib, "entry_points_{}_autogen.{}".format(annotation.lower(), suffix))
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def write_export_files(entry_points, includes, source, lib_name, lib_description, lib_dir=None):
|
|
content = TEMPLATE_LIB_ENTRY_POINT_SOURCE.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name=source,
|
|
lib_name=lib_name,
|
|
lib_description=lib_description,
|
|
includes=includes,
|
|
entry_points=entry_points,
|
|
)
|
|
|
|
path = path_to(lib_name if not lib_dir else lib_dir, "{}_autogen.cpp".format(lib_name))
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def write_context_api_decls(decls, api):
|
|
for (major, minor), version_decls in sorted(decls['core'].items()):
|
|
if minor == "X":
|
|
annotation = '{}_{}'.format(api, major)
|
|
version = str(major)
|
|
else:
|
|
annotation = '{}_{}_{}'.format(api, major, minor)
|
|
version = '{}_{}'.format(major, minor)
|
|
content = CONTEXT_HEADER.format(
|
|
annotation_lower=annotation.lower(),
|
|
annotation_upper=annotation.upper(),
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml",
|
|
version=version,
|
|
interface="\n".join(version_decls))
|
|
|
|
path = path_to("libANGLE", "Context_%s_autogen.h" % annotation.lower())
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
if 'exts' in decls.keys():
|
|
interface_lines = []
|
|
for annotation in decls['exts'].keys():
|
|
interface_lines.append("\\\n /* " + annotation + " */ \\\n\\")
|
|
|
|
for extname in sorted(decls['exts'][annotation].keys()):
|
|
interface_lines.append(" /* " + extname + " */ \\")
|
|
interface_lines.extend(decls['exts'][annotation][extname])
|
|
|
|
content = CONTEXT_HEADER.format(
|
|
annotation_lower='gles_ext',
|
|
annotation_upper='GLES_EXT',
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml",
|
|
version='EXT',
|
|
interface="\n".join(interface_lines))
|
|
|
|
path = path_to("libANGLE", "Context_gles_ext_autogen.h")
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def write_validation_header(annotation, comment, protos, source, template):
|
|
content = template.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name=source,
|
|
annotation=annotation,
|
|
comment=comment,
|
|
prototypes="\n".join(protos))
|
|
|
|
path = path_to("libANGLE", "validation%s_autogen.h" % annotation)
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def write_context_lock_header(annotation, comment, protos, source, template):
|
|
content = template.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name=source,
|
|
annotation_lower=annotation.lower(),
|
|
annotation_upper=annotation.upper(),
|
|
comment=comment,
|
|
prototypes="\n".join(protos))
|
|
|
|
path = path_to("libGLESv2", "%s_context_lock_autogen.h" % annotation.lower())
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def write_gl_validation_header(annotation, comment, protos, source):
|
|
return write_validation_header(annotation, comment, protos, source,
|
|
TEMPLATE_GL_VALIDATION_HEADER)
|
|
|
|
|
|
def write_capture_header(api, annotation, comment, protos, capture_pointer_funcs):
|
|
ns = 'egl' if api == apis.EGL else 'gl'
|
|
combined_protos = ["\n// Method Captures\n"] + protos
|
|
if capture_pointer_funcs:
|
|
combined_protos += ["\n// Parameter Captures\n"] + capture_pointer_funcs
|
|
content = TEMPLATE_CAPTURE_HEADER.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="%s.xml and %s_angle_ext.xml" % (ns, ns),
|
|
annotation_lower=annotation.lower(),
|
|
annotation_upper=annotation.upper(),
|
|
comment=comment,
|
|
namespace=ns,
|
|
prototypes="\n".join(combined_protos))
|
|
|
|
path = path_to(os.path.join("libANGLE", "capture"), "capture_%s_autogen.h" % annotation)
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def write_capture_source(api, annotation_with_dash, annotation_no_dash, comment, capture_methods):
|
|
ns = 'egl' if api == apis.EGL else 'gl'
|
|
content = TEMPLATE_CAPTURE_SOURCE.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="%s.xml and %s_angle_ext.xml" % (ns, ns),
|
|
annotation_with_dash=annotation_with_dash,
|
|
annotation_no_dash=annotation_no_dash,
|
|
comment=comment,
|
|
namespace=ns,
|
|
capture_methods="\n".join(capture_methods))
|
|
|
|
path = path_to(
|
|
os.path.join("libANGLE", "capture"), "capture_%s_autogen.cpp" % annotation_with_dash)
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def is_packed_enum_param_type(param_type):
|
|
return not param_type.startswith("GL") and not param_type.startswith(
|
|
"EGL") and "void" not in param_type
|
|
|
|
|
|
def add_namespace(param_type):
|
|
param_type = param_type.strip()
|
|
|
|
if param_type == 'AHardwareBufferConstPointer' or param_type == 'charConstPointer':
|
|
return param_type
|
|
|
|
# ANGLE namespaced EGL types
|
|
egl_namespace = [
|
|
'CompositorTiming',
|
|
'ObjectType',
|
|
'Timestamp',
|
|
] + list(EGL_PACKED_TYPES.values())
|
|
|
|
if param_type[0:2] == "GL" or param_type[0:3] == "EGL" or "void" in param_type:
|
|
return param_type
|
|
|
|
if param_type.startswith('gl_'):
|
|
return param_type.replace('gl_', 'gl::')
|
|
elif param_type.startswith('egl_'):
|
|
return param_type.replace('egl_', 'egl::')
|
|
elif param_type.startswith('wl_'):
|
|
return param_type
|
|
elif param_type in egl_namespace:
|
|
return "egl::" + param_type
|
|
else:
|
|
return "gl::" + param_type
|
|
|
|
|
|
def get_gl_pointer_type(param_type):
|
|
|
|
if "ConstPointerPointer" in param_type:
|
|
return "const " + param_type.replace("ConstPointerPointer", "") + " * const *"
|
|
|
|
if "ConstPointer" in param_type:
|
|
return "const " + param_type.replace("ConstPointer", "") + " *"
|
|
|
|
if "PointerPointer" in param_type:
|
|
return param_type.replace("PointerPointer", "") + " **"
|
|
|
|
if "Pointer" in param_type:
|
|
return param_type.replace("Pointer", "") + " *"
|
|
|
|
return param_type
|
|
|
|
|
|
def get_param_type_type(param_type):
|
|
param_type = add_namespace(param_type)
|
|
return get_gl_pointer_type(param_type)
|
|
|
|
|
|
def is_id_type(t):
|
|
return t.endswith('ID') and not t.endswith('ANDROID')
|
|
|
|
|
|
def is_id_pointer_type(t):
|
|
return t.endswith("IDConstPointer") or t.endswith("IDPointer") and not 'ANDROID' in t
|
|
|
|
|
|
def get_gl_param_type_type(param_type):
|
|
if is_packed_enum_param_type(param_type):
|
|
base_type = param_type.replace("Pointer", "").replace("Const", "")
|
|
if is_id_type(base_type):
|
|
replace_type = "GLuint"
|
|
else:
|
|
replace_type = "GLenum"
|
|
param_type = param_type.replace(base_type, replace_type)
|
|
return get_gl_pointer_type(param_type)
|
|
|
|
|
|
def get_param_type_union_name(param_type):
|
|
return param_type + "Val"
|
|
|
|
|
|
def format_param_type_union_type(param_type):
|
|
return "%s %s;" % (get_param_type_type(param_type), get_param_type_union_name(param_type))
|
|
|
|
|
|
def format_get_param_val_specialization(param_type):
|
|
return TEMPLATE_GET_PARAM_VAL_SPECIALIZATION.format(
|
|
enum=param_type,
|
|
type=get_param_type_type(param_type),
|
|
union_name=get_param_type_union_name(param_type))
|
|
|
|
|
|
def format_access_param_value_case(param_type):
|
|
return TEMPLATE_ACCESS_PARAM_VALUE_CASE.format(enum=param_type)
|
|
|
|
|
|
def format_set_param_val_specialization(param_type):
|
|
return TEMPLATE_SET_PARAM_VAL_SPECIALIZATION.format(
|
|
enum=param_type,
|
|
type=get_param_type_type(param_type),
|
|
union_name=get_param_type_union_name(param_type))
|
|
|
|
|
|
def format_init_param_value_case(param_type):
|
|
return TEMPLATE_INIT_PARAM_VALUE_CASE.format(enum=param_type)
|
|
|
|
|
|
def format_write_param_type_to_stream_case(param_type):
|
|
return TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE.format(
|
|
enum_in=param_type, enum_out=param_type, union_name=get_param_type_union_name(param_type))
|
|
|
|
|
|
def get_resource_id_types(all_param_types):
|
|
return [t[:-2] for t in filter(lambda t: is_id_type(t), all_param_types)]
|
|
|
|
|
|
def format_resource_id_types(all_param_types):
|
|
resource_id_types = get_resource_id_types(all_param_types)
|
|
resource_id_types += ["EnumCount", "InvalidEnum = EnumCount"]
|
|
resource_id_types = ",\n ".join(resource_id_types)
|
|
return resource_id_types
|
|
|
|
|
|
def format_resource_id_convert_structs(all_param_types):
|
|
templ = """\
|
|
template <>
|
|
struct GetResourceIDTypeFromType<%s>
|
|
{
|
|
static constexpr ResourceIDType IDType = ResourceIDType::%s;
|
|
};
|
|
"""
|
|
resource_id_types = get_resource_id_types(all_param_types)
|
|
convert_struct_strings = [templ % (add_namespace('%sID' % id), id) for id in resource_id_types]
|
|
return "\n".join(convert_struct_strings)
|
|
|
|
|
|
def write_capture_helper_header(all_param_types):
|
|
|
|
param_types = "\n ".join(["T%s," % t for t in all_param_types])
|
|
param_union_values = "\n ".join([format_param_type_union_type(t) for t in all_param_types])
|
|
get_param_val_specializations = "\n\n".join(
|
|
[format_get_param_val_specialization(t) for t in all_param_types])
|
|
access_param_value_cases = "\n".join(
|
|
[format_access_param_value_case(t) for t in all_param_types])
|
|
set_param_val_specializations = "\n\n".join(
|
|
[format_set_param_val_specialization(t) for t in all_param_types])
|
|
init_param_value_cases = "\n".join([format_init_param_value_case(t) for t in all_param_types])
|
|
resource_id_types = format_resource_id_types(all_param_types)
|
|
convert_structs = format_resource_id_convert_structs(all_param_types)
|
|
|
|
content = TEMPLATE_FRAME_CAPTURE_UTILS_HEADER.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml and gl_angle_ext.xml",
|
|
param_types=param_types,
|
|
param_type_count=len(all_param_types),
|
|
param_union_values=param_union_values,
|
|
get_param_val_specializations=get_param_val_specializations,
|
|
access_param_value_cases=access_param_value_cases,
|
|
set_param_val_specializations=set_param_val_specializations,
|
|
init_param_value_cases=init_param_value_cases,
|
|
resource_id_types=resource_id_types,
|
|
type_to_resource_id_type_structs=convert_structs)
|
|
|
|
path = path_to("common", "frame_capture_utils_autogen.h")
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def format_param_type_to_string_case(param_type):
|
|
return TEMPLATE_PARAM_TYPE_TO_STRING_CASE.format(
|
|
enum=param_type, type=get_gl_param_type_type(param_type))
|
|
|
|
|
|
def get_resource_id_type_from_param_type(param_type):
|
|
if param_type.endswith("ConstPointer"):
|
|
return param_type.replace("ConstPointer", "")[:-2]
|
|
if param_type.endswith("Pointer"):
|
|
return param_type.replace("Pointer", "")[:-2]
|
|
return param_type[:-2]
|
|
|
|
|
|
def format_param_type_to_resource_id_type_case(param_type):
|
|
return TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE.format(
|
|
enum=param_type, resource_id_type=get_resource_id_type_from_param_type(param_type))
|
|
|
|
|
|
def format_param_type_resource_id_cases(all_param_types):
|
|
id_types = filter(lambda t: is_id_type(t) or is_id_pointer_type(t), all_param_types)
|
|
return "\n".join([format_param_type_to_resource_id_type_case(t) for t in id_types])
|
|
|
|
|
|
def format_resource_id_type_name_case(resource_id_type):
|
|
return TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE.format(resource_id_type=resource_id_type)
|
|
|
|
|
|
def write_capture_helper_source(all_param_types):
|
|
|
|
write_param_type_to_stream_cases = "\n".join(
|
|
[format_write_param_type_to_stream_case(t) for t in all_param_types])
|
|
param_type_to_string_cases = "\n".join(
|
|
[format_param_type_to_string_case(t) for t in all_param_types])
|
|
|
|
param_type_resource_id_cases = format_param_type_resource_id_cases(all_param_types)
|
|
|
|
resource_id_types = get_resource_id_types(all_param_types)
|
|
resource_id_type_name_cases = "\n".join(
|
|
[format_resource_id_type_name_case(t) for t in resource_id_types])
|
|
|
|
content = TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml and gl_angle_ext.xml",
|
|
write_param_type_to_stream_cases=write_param_type_to_stream_cases,
|
|
param_type_to_string_cases=param_type_to_string_cases,
|
|
param_type_resource_id_cases=param_type_resource_id_cases,
|
|
resource_id_type_name_cases=resource_id_type_name_cases)
|
|
|
|
path = path_to("common", "frame_capture_utils_autogen.cpp")
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def get_command_params_text(command_node, cmd_name):
|
|
param_text_list = list()
|
|
for param_node in command_node.findall('param'):
|
|
param_text_list.append("".join(param_node.itertext()))
|
|
return param_text_list
|
|
|
|
|
|
def is_get_pointer_command(command_name):
|
|
return command_name.endswith('Pointerv') and command_name.startswith('glGet')
|
|
|
|
|
|
def remove_id_suffix(t):
|
|
return t[:-2] if is_id_type(t) else t
|
|
|
|
|
|
def format_replay_params(api, command_name, param_text_list, packed_enums, resource_id_types):
|
|
param_access_strs = list()
|
|
for i, param_text in enumerate(param_text_list):
|
|
param_type = just_the_type(param_text)
|
|
if param_type in EGL_PACKED_TYPES:
|
|
param_type = 'void *'
|
|
param_name = just_the_name(param_text)
|
|
capture_type = get_capture_param_type_name(param_type)
|
|
union_name = get_param_type_union_name(capture_type)
|
|
param_access = 'captures[%d].value.%s' % (i, union_name)
|
|
# Workaround for https://github.com/KhronosGroup/OpenGL-Registry/issues/545
|
|
if command_name == 'glCreateShaderProgramvEXT' and i == 2:
|
|
param_access = 'const_cast<const char **>(%s)' % param_access
|
|
else:
|
|
cmd_no_suffix = strip_suffix(api, command_name)
|
|
if cmd_no_suffix in packed_enums and param_name in packed_enums[cmd_no_suffix]:
|
|
packed_type = remove_id_suffix(packed_enums[cmd_no_suffix][param_name])
|
|
if packed_type == 'Sync':
|
|
param_access = 'gSyncMap2[captures[%d].value.GLuintVal]' % i
|
|
elif packed_type in resource_id_types:
|
|
param_access = 'g%sMap[%s]' % (packed_type, param_access)
|
|
elif packed_type == 'UniformLocation':
|
|
param_access = 'gUniformLocations[gCurrentProgram][%s]' % param_access
|
|
elif packed_type == 'egl::Image':
|
|
param_access = 'gEGLImageMap2[captures[%d].value.GLuintVal]' % i
|
|
elif packed_type == 'egl::Sync':
|
|
param_access = 'gEGLSyncMap[captures[%d].value.egl_SyncIDVal]' % i
|
|
param_access_strs.append(param_access)
|
|
return ', '.join(param_access_strs)
|
|
|
|
|
|
def format_capture_replay_call_case(api, command_to_param_types_mapping, gl_packed_enums,
|
|
resource_id_types):
|
|
call_list = list()
|
|
for command_name, cmd_param_texts in sorted(command_to_param_types_mapping.items()):
|
|
entry_point_name = strip_api_prefix(command_name)
|
|
|
|
call_list.append(
|
|
TEMPLATE_REPLAY_CALL_CASE.format(
|
|
enum=('EGL' if api == 'EGL' else 'GL') + entry_point_name,
|
|
params=format_replay_params(api, command_name, cmd_param_texts, gl_packed_enums,
|
|
resource_id_types),
|
|
call=command_name,
|
|
))
|
|
|
|
return ''.join(call_list)
|
|
|
|
|
|
def write_capture_replay_source(gl_command_nodes, gl_command_names, gl_packed_enums,
|
|
egl_command_nodes, egl_command_names, egl_packed_enums,
|
|
resource_id_types):
|
|
|
|
call_replay_cases = ''
|
|
|
|
for api, nodes, names, packed_enums in [
|
|
(apis.GLES, gl_command_nodes, gl_command_names, gl_packed_enums),
|
|
(apis.EGL, egl_command_nodes, egl_command_names, egl_packed_enums)
|
|
]:
|
|
command_to_param_types_mapping = dict()
|
|
all_commands_names = set(names)
|
|
for command_node in nodes:
|
|
command_name = command_node.find('proto').find('name').text
|
|
if command_name not in all_commands_names:
|
|
continue
|
|
command_to_param_types_mapping[command_name] = get_command_params_text(
|
|
command_node, command_name)
|
|
|
|
call_replay_cases += format_capture_replay_call_case(api, command_to_param_types_mapping,
|
|
packed_enums, resource_id_types)
|
|
|
|
source_content = TEMPLATE_CAPTURE_REPLAY_SOURCE.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml and gl_angle_ext.xml",
|
|
call_replay_cases=call_replay_cases,
|
|
)
|
|
source_file_path = registry_xml.script_relative(
|
|
"../util/capture/frame_capture_replay_autogen.cpp")
|
|
with open(source_file_path, 'w') as f:
|
|
f.write(source_content)
|
|
|
|
|
|
def write_windows_def_file(data_source_name, lib, libexport, folder, exports):
|
|
|
|
content = TEMPLATE_WINDOWS_DEF_FILE.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name=data_source_name,
|
|
exports="\n".join(exports),
|
|
lib=libexport)
|
|
|
|
path = path_to(folder, "%s_autogen.def" % lib)
|
|
|
|
with open(path, "w") as out:
|
|
out.write(content)
|
|
out.close()
|
|
|
|
|
|
def get_exports(commands, fmt=None):
|
|
if fmt:
|
|
return [" %s" % fmt(cmd) for cmd in sorted(commands)]
|
|
else:
|
|
return [" %s" % cmd for cmd in sorted(commands)]
|
|
|
|
|
|
# Get EGL exports
|
|
def get_egl_exports():
|
|
|
|
egl = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
|
|
exports = []
|
|
|
|
capser = lambda fn: "EGL_" + fn[3:]
|
|
|
|
for major, minor in registry_xml.EGL_VERSIONS:
|
|
annotation = "{}_{}".format(major, minor)
|
|
name_prefix = "EGL_VERSION_"
|
|
|
|
feature_name = "{}{}".format(name_prefix, annotation)
|
|
|
|
egl.AddCommands(feature_name, annotation)
|
|
|
|
commands = egl.commands[annotation]
|
|
|
|
if len(commands) == 0:
|
|
continue
|
|
|
|
exports.append("\n ; EGL %d.%d" % (major, minor))
|
|
exports += get_exports(commands, capser)
|
|
|
|
egl.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
|
|
|
|
for extension_name, ext_cmd_names in sorted(egl.ext_data.items()):
|
|
|
|
if len(ext_cmd_names) == 0:
|
|
continue
|
|
|
|
exports.append("\n ; %s" % extension_name)
|
|
exports += get_exports(ext_cmd_names, capser)
|
|
|
|
return exports
|
|
|
|
|
|
# Construct a mapping from an EGL EP to object function
|
|
def get_egl_entry_point_labeled_object(ep_to_object, cmd_stripped, params, packed_enums):
|
|
|
|
if not ep_to_object:
|
|
return ""
|
|
|
|
# Finds a packed parameter name in a list of params
|
|
def find_param(params, type_name, packed_enums):
|
|
for param in params:
|
|
if just_the_type_packed(param, packed_enums).split(' ')[0] == type_name:
|
|
return just_the_name_packed(param, packed_enums)
|
|
return None
|
|
|
|
display_param = find_param(params, "egl::Display", packed_enums)
|
|
|
|
# For entry points not listed in the JSON file, they default to an EGLDisplay or nothing.
|
|
if cmd_stripped not in ep_to_object:
|
|
if display_param:
|
|
return "GetDisplayIfValid(%s)" % display_param
|
|
return "nullptr"
|
|
|
|
# We first handle a few special cases for certain type categories.
|
|
category = ep_to_object[cmd_stripped]
|
|
if category == "Thread":
|
|
return "GetThreadIfValid(thread)"
|
|
found_param = find_param(params, category, packed_enums)
|
|
if category == "Context" and not found_param:
|
|
return "GetContextIfValid(thread->getDisplay(), thread->getContext())"
|
|
assert found_param, "Did not find %s for %s: %s" % (category, cmd_stripped, str(params))
|
|
if category == "Device":
|
|
return "GetDeviceIfValid(%s)" % found_param
|
|
if category == "LabeledObject":
|
|
object_type_param = find_param(params, "ObjectType", packed_enums)
|
|
return "GetLabeledObjectIfValid(thread, %s, %s, %s)" % (display_param, object_type_param,
|
|
found_param)
|
|
|
|
# We then handle the general case which handles the rest of the type categories.
|
|
return "Get%sIfValid(%s, %s)" % (category, display_param, found_param)
|
|
|
|
|
|
def get_context_lock(api, cmd_name):
|
|
# EGLImage related commands need to access EGLImage and Display which should
|
|
# be protected with global lock
|
|
# Also handles ContexMutex marging when SharedContextMutex is enabled.
|
|
if api == apis.GLES and cmd_name.startswith("glEGLImage"):
|
|
return "SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked);"
|
|
|
|
return "SCOPED_SHARE_CONTEXT_LOCK(context);"
|
|
|
|
|
|
def get_prepare_swap_buffers_call(api, cmd_name, params):
|
|
if cmd_name not in [
|
|
"eglSwapBuffers", "eglSwapBuffersWithDamageKHR", "eglSwapBuffersWithFrameTokenANGLE"
|
|
]:
|
|
return ""
|
|
|
|
passed_params = [None, None]
|
|
|
|
for param in params:
|
|
param_type = just_the_type(param)
|
|
if param_type == "EGLDisplay":
|
|
passed_params[0] = param
|
|
if param_type == "EGLSurface":
|
|
passed_params[1] = param
|
|
|
|
return "ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(%s));" % (", ".join(
|
|
[just_the_name(param) for param in passed_params]))
|
|
|
|
|
|
def get_preamble(api, cmd_name, params):
|
|
preamble = ""
|
|
preamble += get_prepare_swap_buffers_call(api, cmd_name, params)
|
|
# TODO: others?
|
|
return preamble
|
|
|
|
|
|
def get_unlocked_tail_call(api, cmd_name):
|
|
# Only the following can generate tail calls:
|
|
#
|
|
# - eglDestroySurface, eglMakeCurrent and eglReleaseThread -> May destroy
|
|
# VkSurfaceKHR in tail call
|
|
# - eglCreateWindowSurface and eglCreatePlatformWindowSurface[EXT] -> May
|
|
# destroy VkSurfaceKHR in tail call if surface initialization fails
|
|
#
|
|
# - eglPrepareSwapBuffersANGLE -> Calls vkAcquireNextImageKHR in tail call
|
|
#
|
|
# - eglSwapBuffers, eglSwapBuffersWithDamageKHR and
|
|
# eglSwapBuffersWithFrameTokenANGLE -> May throttle the CPU in tail call
|
|
#
|
|
if cmd_name in [
|
|
'eglDestroySurface', 'eglMakeCurrent', 'eglReleaseThread', 'eglCreateWindowSurface',
|
|
'eglCreatePlatformWindowSurface', 'eglCreatePlatformWindowSurfaceEXT',
|
|
'eglPrepareSwapBuffersANGLE', 'eglSwapBuffers', 'eglSwapBuffersWithDamageKHR',
|
|
'eglSwapBuffersWithFrameTokenANGLE'
|
|
]:
|
|
return 'egl::Display::GetCurrentThreadUnlockedTailCall()->run();'
|
|
|
|
# Otherwise assert that no tail calls where generated
|
|
return 'ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());'
|
|
|
|
|
|
def get_epilog(api, cmd_name):
|
|
epilog = get_unlocked_tail_call(api, cmd_name)
|
|
return epilog
|
|
|
|
|
|
def write_stubs_header(api, annotation, title, data_source, out_file, all_commands, commands,
|
|
cmd_packed_egl_enums, packed_param_types):
|
|
|
|
stubs = []
|
|
|
|
for command in all_commands:
|
|
proto = command.find('proto')
|
|
cmd_name = proto.find('name').text
|
|
|
|
if cmd_name not in commands:
|
|
continue
|
|
|
|
proto_text = "".join(proto.itertext())
|
|
|
|
params = [] if api == apis.CL else ["Thread *thread"]
|
|
params += ["".join(param.itertext()) for param in command.findall('param')]
|
|
if params and just_the_name(params[-1]) == "errcode_ret":
|
|
params[-1] = "cl_int &errorCode"
|
|
return_type = proto_text[:-len(cmd_name)].strip()
|
|
|
|
internal_params = get_internal_params(api, cmd_name, params, cmd_packed_egl_enums,
|
|
packed_param_types)
|
|
stubs.append("%s %s(%s);" % (return_type, strip_api_prefix(cmd_name), internal_params))
|
|
|
|
args = {
|
|
"annotation_lower": annotation.lower(),
|
|
"annotation_upper": annotation.upper(),
|
|
"data_source_name": data_source,
|
|
"script_name": os.path.basename(sys.argv[0]),
|
|
"stubs": "\n".join(stubs),
|
|
"title": title,
|
|
}
|
|
|
|
output = get_stubs_header_template(api).format(**args)
|
|
|
|
with open(out_file, "w") as f:
|
|
f.write(output)
|
|
|
|
|
|
def main():
|
|
|
|
# auto_script parameters.
|
|
if len(sys.argv) > 1:
|
|
inputs = [
|
|
'entry_point_packed_egl_enums.json', 'entry_point_packed_gl_enums.json',
|
|
EGL_GET_LABELED_OBJECT_DATA_PATH
|
|
] + registry_xml.xml_inputs
|
|
outputs = [
|
|
CL_STUBS_HEADER_PATH,
|
|
EGL_STUBS_HEADER_PATH,
|
|
EGL_EXT_STUBS_HEADER_PATH,
|
|
'../src/libOpenCL/libOpenCL_autogen.cpp',
|
|
'../src/common/entry_points_enum_autogen.cpp',
|
|
'../src/common/entry_points_enum_autogen.h',
|
|
'../src/common/frame_capture_utils_autogen.cpp',
|
|
'../src/common/frame_capture_utils_autogen.h',
|
|
'../src/libANGLE/Context_gl_1_autogen.h',
|
|
'../src/libANGLE/Context_gl_2_autogen.h',
|
|
'../src/libANGLE/Context_gl_3_autogen.h',
|
|
'../src/libANGLE/Context_gl_4_autogen.h',
|
|
'../src/libANGLE/Context_gles_1_0_autogen.h',
|
|
'../src/libANGLE/Context_gles_2_0_autogen.h',
|
|
'../src/libANGLE/Context_gles_3_0_autogen.h',
|
|
'../src/libANGLE/Context_gles_3_1_autogen.h',
|
|
'../src/libANGLE/Context_gles_3_2_autogen.h',
|
|
'../src/libANGLE/Context_gles_ext_autogen.h',
|
|
'../src/libANGLE/capture/capture_egl_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_egl_autogen.h',
|
|
'../src/libANGLE/capture/capture_gl_1_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gl_1_autogen.h',
|
|
'../src/libANGLE/capture/capture_gl_2_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gl_2_autogen.h',
|
|
'../src/libANGLE/capture/capture_gl_3_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gl_3_autogen.h',
|
|
'../src/libANGLE/capture/capture_gl_4_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gl_4_autogen.h',
|
|
'../src/libANGLE/capture/capture_gles_1_0_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gles_1_0_autogen.h',
|
|
'../src/libANGLE/capture/capture_gles_2_0_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gles_2_0_autogen.h',
|
|
'../src/libANGLE/capture/capture_gles_3_0_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gles_3_0_autogen.h',
|
|
'../src/libANGLE/capture/capture_gles_3_1_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gles_3_1_autogen.h',
|
|
'../src/libANGLE/capture/capture_gles_3_2_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gles_3_2_autogen.h',
|
|
'../src/libANGLE/capture/capture_gles_ext_autogen.cpp',
|
|
'../src/libANGLE/capture/capture_gles_ext_autogen.h',
|
|
'../src/libANGLE/validationCL_autogen.h',
|
|
'../src/libANGLE/validationEGL_autogen.h',
|
|
'../src/libANGLE/validationES1_autogen.h',
|
|
'../src/libANGLE/validationES2_autogen.h',
|
|
'../src/libANGLE/validationES31_autogen.h',
|
|
'../src/libANGLE/validationES32_autogen.h',
|
|
'../src/libANGLE/validationES3_autogen.h',
|
|
'../src/libANGLE/validationESEXT_autogen.h',
|
|
'../src/libANGLE/validationGL1_autogen.h',
|
|
'../src/libANGLE/validationGL2_autogen.h',
|
|
'../src/libANGLE/validationGL3_autogen.h',
|
|
'../src/libANGLE/validationGL4_autogen.h',
|
|
'../src/libEGL/libEGL_autogen.cpp',
|
|
'../src/libEGL/libEGL_autogen.def',
|
|
'../src/libGLESv2/entry_points_cl_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_cl_autogen.h',
|
|
'../src/libGLESv2/entry_points_egl_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_egl_autogen.h',
|
|
'../src/libGLESv2/entry_points_egl_ext_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_egl_ext_autogen.h',
|
|
'../src/libGLESv2/entry_points_gles_1_0_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gles_1_0_autogen.h',
|
|
'../src/libGLESv2/entry_points_gles_2_0_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gles_2_0_autogen.h',
|
|
'../src/libGLESv2/entry_points_gles_3_0_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gles_3_0_autogen.h',
|
|
'../src/libGLESv2/entry_points_gles_3_1_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gles_3_1_autogen.h',
|
|
'../src/libGLESv2/entry_points_gles_3_2_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gles_3_2_autogen.h',
|
|
'../src/libGLESv2/entry_points_gles_ext_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gles_ext_autogen.h',
|
|
'../src/libGLESv2/libGLESv2_autogen.cpp',
|
|
'../src/libGLESv2/libGLESv2_autogen.def',
|
|
'../src/libGLESv2/libGLESv2_no_capture_autogen.def',
|
|
'../src/libGLESv2/libGLESv2_with_capture_autogen.def',
|
|
'../src/libGLESv2/entry_points_gl_1_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gl_1_autogen.h',
|
|
'../src/libGLESv2/entry_points_gl_2_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gl_2_autogen.h',
|
|
'../src/libGLESv2/entry_points_gl_3_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gl_3_autogen.h',
|
|
'../src/libGLESv2/entry_points_gl_4_autogen.cpp',
|
|
'../src/libGLESv2/entry_points_gl_4_autogen.h',
|
|
'../src/libGLESv2/egl_context_lock_autogen.h',
|
|
'../util/capture/frame_capture_replay_autogen.cpp',
|
|
]
|
|
|
|
if sys.argv[1] == 'inputs':
|
|
print(','.join(inputs))
|
|
elif sys.argv[1] == 'outputs':
|
|
print(','.join(outputs))
|
|
else:
|
|
print('Invalid script parameters')
|
|
return 1
|
|
return 0
|
|
|
|
glesdecls = {}
|
|
glesdecls['core'] = {}
|
|
glesdecls['exts'] = {}
|
|
for ver in registry_xml.GLES_VERSIONS:
|
|
glesdecls['core'][ver] = []
|
|
for ver in ['GLES1 Extensions', 'GLES2+ Extensions', 'ANGLE Extensions']:
|
|
glesdecls['exts'][ver] = {}
|
|
|
|
libgles_ep_defs = []
|
|
libgles_ep_exports = []
|
|
|
|
xml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')
|
|
|
|
# Stores core commands to keep track of duplicates
|
|
all_commands_no_suffix = []
|
|
all_commands_with_suffix = []
|
|
|
|
# Collect all GL+GLES validation declarations
|
|
glesv2_validation_protos = []
|
|
|
|
# First run through the main GLES entry points. Since ES2+ is the primary use
|
|
# case, we go through those first and then add ES1-only APIs at the end.
|
|
for major_version, minor_version in registry_xml.GLES_VERSIONS:
|
|
version = "{}_{}".format(major_version, minor_version)
|
|
annotation = "GLES_{}".format(version)
|
|
name_prefix = "GL_ES_VERSION_"
|
|
|
|
if major_version == 1:
|
|
name_prefix = "GL_VERSION_ES_CM_"
|
|
|
|
comment = version.replace("_", ".")
|
|
feature_name = "{}{}".format(name_prefix, version)
|
|
|
|
xml.AddCommands(feature_name, version)
|
|
|
|
version_commands = xml.commands[version]
|
|
all_commands_no_suffix.extend(xml.commands[version])
|
|
all_commands_with_suffix.extend(xml.commands[version])
|
|
|
|
eps = GLEntryPoints(apis.GLES, xml, version_commands)
|
|
eps.decls.insert(0, "extern \"C\" {")
|
|
eps.decls.append("} // extern \"C\"")
|
|
eps.defs.insert(0, "extern \"C\" {")
|
|
eps.defs.append("} // extern \"C\"")
|
|
|
|
# Write the version as a comment before the first EP.
|
|
libgles_ep_exports.append("\n ; OpenGL ES %s" % comment)
|
|
|
|
libgles_ep_defs += ["\n// OpenGL ES %s" % comment] + eps.export_defs
|
|
libgles_ep_exports += get_exports(version_commands)
|
|
|
|
major_if_not_one = major_version if major_version != 1 else ""
|
|
minor_if_not_zero = minor_version if minor_version != 0 else ""
|
|
|
|
header_includes = TEMPLATE_HEADER_INCLUDES.format(
|
|
major=major_if_not_one, minor=minor_if_not_zero)
|
|
|
|
version_annotation = "%s%s" % (major_version, minor_if_not_zero)
|
|
source_includes = TEMPLATE_SOURCES_INCLUDES.format(
|
|
header_version=annotation.lower(), validation_header_version="ES" + version_annotation)
|
|
|
|
write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_HEADER,
|
|
"\n".join(eps.decls), "h", header_includes, "libGLESv2", "gl.xml")
|
|
write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(eps.defs),
|
|
"cpp", source_includes, "libGLESv2", "gl.xml")
|
|
|
|
glesdecls['core'][(major_version,
|
|
minor_version)] = get_decls(apis.GLES, CONTEXT_DECL_FORMAT,
|
|
xml.all_commands, version_commands, [],
|
|
GLEntryPoints.get_packed_enums())
|
|
|
|
validation_annotation = "ES%s%s" % (major_version, minor_if_not_zero)
|
|
write_gl_validation_header(validation_annotation, "ES %s" % comment, eps.validation_protos,
|
|
"gl.xml and gl_angle_ext.xml")
|
|
|
|
write_capture_header(apis.GLES, 'gles_' + version, comment, eps.capture_protos,
|
|
eps.capture_pointer_funcs)
|
|
write_capture_source(apis.GLES, 'gles_' + version, validation_annotation, comment,
|
|
eps.capture_methods)
|
|
|
|
# After we finish with the main entry points, we process the extensions.
|
|
extension_decls = ["extern \"C\" {"]
|
|
extension_defs = ["extern \"C\" {"]
|
|
extension_commands = []
|
|
|
|
# Accumulated validation prototypes.
|
|
ext_validation_protos = []
|
|
ext_capture_protos = []
|
|
ext_capture_methods = []
|
|
ext_capture_pointer_funcs = []
|
|
|
|
for gles1ext in registry_xml.gles1_extensions:
|
|
glesdecls['exts']['GLES1 Extensions'][gles1ext] = []
|
|
for glesext in registry_xml.gles_extensions:
|
|
glesdecls['exts']['GLES2+ Extensions'][glesext] = []
|
|
for angle_ext in registry_xml.angle_extensions:
|
|
glesdecls['exts']['ANGLE Extensions'][angle_ext] = []
|
|
|
|
xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
|
|
|
|
for extension_name, ext_cmd_names in sorted(xml.ext_data.items()):
|
|
extension_commands.extend(xml.ext_data[extension_name])
|
|
|
|
# Detect and filter duplicate extensions.
|
|
eps = GLEntryPoints(apis.GLES, xml, ext_cmd_names)
|
|
|
|
# Write the extension name as a comment before the first EP.
|
|
comment = "\n// {}".format(extension_name)
|
|
libgles_ep_exports.append("\n ; %s" % extension_name)
|
|
|
|
extension_defs += [comment] + eps.defs
|
|
extension_decls += [comment] + eps.decls
|
|
|
|
# Avoid writing out entry points defined by a prior extension.
|
|
for dupe in xml.ext_dupes[extension_name]:
|
|
msg = "// {} is already defined.\n".format(strip_api_prefix(dupe))
|
|
extension_defs.append(msg)
|
|
|
|
ext_validation_protos += [comment] + eps.validation_protos
|
|
ext_capture_protos += [comment] + eps.capture_protos
|
|
ext_capture_methods += eps.capture_methods
|
|
ext_capture_pointer_funcs += eps.capture_pointer_funcs
|
|
|
|
libgles_ep_defs += [comment] + eps.export_defs
|
|
libgles_ep_exports += get_exports(ext_cmd_names)
|
|
|
|
if (extension_name in registry_xml.gles1_extensions and
|
|
extension_name not in GLES1_NO_CONTEXT_DECL_EXTENSIONS):
|
|
glesdecls['exts']['GLES1 Extensions'][extension_name] = get_decls(
|
|
apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
|
|
all_commands_no_suffix, GLEntryPoints.get_packed_enums())
|
|
if extension_name in registry_xml.gles_extensions:
|
|
glesdecls['exts']['GLES2+ Extensions'][extension_name] = get_decls(
|
|
apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
|
|
all_commands_no_suffix, GLEntryPoints.get_packed_enums())
|
|
if extension_name in registry_xml.angle_extensions:
|
|
glesdecls['exts']['ANGLE Extensions'][extension_name] = get_decls(
|
|
apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
|
|
all_commands_no_suffix, GLEntryPoints.get_packed_enums())
|
|
|
|
for name in extension_commands:
|
|
all_commands_with_suffix.append(name)
|
|
all_commands_no_suffix.append(strip_suffix(apis.GLES, name))
|
|
|
|
# Now we generate entry points for the desktop implementation
|
|
desktop_gl_decls = {}
|
|
desktop_gl_decls['core'] = {}
|
|
for major, _ in registry_xml.DESKTOP_GL_VERSIONS:
|
|
desktop_gl_decls['core'][(major, "X")] = []
|
|
|
|
libgles_ep_defs.append('#if defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)')
|
|
libgl_ep_exports = libgles_ep_exports.copy()
|
|
|
|
glxml = registry_xml.RegistryXML('gl.xml')
|
|
|
|
for major_version in sorted(
|
|
set([major for (major, minor) in registry_xml.DESKTOP_GL_VERSIONS])):
|
|
is_major = lambda ver: ver[0] == major_version
|
|
|
|
ver_decls = ["extern \"C\" {"]
|
|
ver_defs = ["extern \"C\" {"]
|
|
validation_protos = []
|
|
capture_protos = []
|
|
capture_pointer_funcs = []
|
|
capture_defs = []
|
|
|
|
for _, minor_version in filter(is_major, registry_xml.DESKTOP_GL_VERSIONS):
|
|
version = "{}_{}".format(major_version, minor_version)
|
|
annotation = "GL_{}".format(version)
|
|
name_prefix = "GL_VERSION_"
|
|
|
|
comment = version.replace("_", ".")
|
|
feature_name = "{}{}".format(name_prefix, version)
|
|
|
|
glxml.AddCommands(feature_name, version)
|
|
|
|
all_libgl_commands = glxml.commands[version]
|
|
just_libgl_commands_suffix = [
|
|
cmd for cmd in all_libgl_commands if cmd not in all_commands_with_suffix
|
|
]
|
|
|
|
# Validation duplicates handled with suffix
|
|
eps = GLEntryPoints(apis.GL, glxml, just_libgl_commands_suffix)
|
|
|
|
desktop_gl_decls['core'][(major_version, "X")] += get_decls(
|
|
apis.GL, CONTEXT_DECL_FORMAT, glxml.all_commands, just_libgl_commands_suffix,
|
|
all_commands_no_suffix, GLEntryPoints.get_packed_enums())
|
|
|
|
# Write the version as a comment before the first EP.
|
|
cpp_comment = "\n// GL %s" % comment
|
|
def_comment = "\n ; GL %s" % comment
|
|
|
|
libgles_ep_defs += [cpp_comment] + eps.export_defs
|
|
libgl_ep_exports += [def_comment] + get_exports(all_libgl_commands)
|
|
validation_protos += [cpp_comment] + eps.validation_protos
|
|
capture_protos += [cpp_comment] + eps.capture_protos
|
|
capture_pointer_funcs += [cpp_comment] + eps.capture_pointer_funcs
|
|
capture_defs += [cpp_comment] + eps.capture_methods
|
|
ver_decls += [cpp_comment] + eps.decls
|
|
ver_defs += [cpp_comment] + eps.defs
|
|
|
|
ver_decls.append("} // extern \"C\"")
|
|
ver_defs.append("} // extern \"C\"")
|
|
annotation = "GL_%d" % major_version
|
|
name = "Desktop GL %s.x" % major_version
|
|
|
|
source_includes = TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES.format(annotation.lower(),
|
|
major_version)
|
|
|
|
# Entry point files
|
|
write_file(annotation, name, TEMPLATE_ENTRY_POINT_HEADER, "\n".join(ver_decls), "h",
|
|
DESKTOP_GL_HEADER_INCLUDES, "libGLESv2", "gl.xml")
|
|
write_file(annotation, name, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(ver_defs), "cpp",
|
|
source_includes, "libGLESv2", "gl.xml")
|
|
|
|
# Capture files
|
|
write_capture_header(apis.GL, annotation.lower(), name, capture_protos,
|
|
capture_pointer_funcs)
|
|
write_capture_source(apis.GL, annotation.lower(), 'GL' + str(major_version) + '_autogen',
|
|
name, capture_defs)
|
|
|
|
# Validation files
|
|
write_gl_validation_header("GL%s" % major_version, name, validation_protos, "gl.xml")
|
|
|
|
libgles_ep_defs.append('#endif // defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)')
|
|
|
|
# GLX
|
|
glxxml = registry_xml.RegistryXML('glx.xml')
|
|
glx_validation_protos = []
|
|
glx_decls = ["namespace glx\n{"]
|
|
glx_defs = ["namespace glx\n{"]
|
|
libglx_ep_defs = []
|
|
glx_commands = []
|
|
for major_version, minor_version in registry_xml.GLX_VERSIONS:
|
|
version = "{}_{}".format(major_version, minor_version)
|
|
annotation = "GLX_{}".format(version)
|
|
name_prefix = "GLX_VERSION_"
|
|
|
|
comment = version.replace("_", ".")
|
|
feature_name = "{}{}".format(name_prefix, version)
|
|
|
|
glxxml.AddCommands(feature_name, version)
|
|
glx_version_commands = glxxml.commands[version]
|
|
glx_commands += glx_version_commands
|
|
|
|
if not glx_version_commands:
|
|
continue
|
|
|
|
|
|
|
|
# OpenCL
|
|
clxml = registry_xml.RegistryXML('cl.xml')
|
|
|
|
cl_validation_protos = []
|
|
cl_decls = ["namespace cl\n{"]
|
|
cl_defs = ["namespace cl\n{"]
|
|
libcl_ep_defs = []
|
|
libcl_windows_def_exports = []
|
|
cl_commands = []
|
|
|
|
for major_version, minor_version in registry_xml.CL_VERSIONS:
|
|
version = "%d_%d" % (major_version, minor_version)
|
|
annotation = "CL_%s" % version
|
|
name_prefix = "CL_VERSION_"
|
|
|
|
comment = version.replace("_", ".")
|
|
feature_name = "%s%s" % (name_prefix, version)
|
|
|
|
clxml.AddCommands(feature_name, version)
|
|
|
|
cl_version_commands = clxml.commands[version]
|
|
cl_commands += cl_version_commands
|
|
|
|
# Spec revs may have no new commands.
|
|
if not cl_version_commands:
|
|
continue
|
|
|
|
eps = CLEntryPoints(clxml, cl_version_commands)
|
|
|
|
comment = "\n// CL %d.%d" % (major_version, minor_version)
|
|
win_def_comment = "\n ; CL %d.%d" % (major_version, minor_version)
|
|
|
|
cl_decls += [comment] + eps.decls
|
|
cl_defs += [comment] + eps.defs
|
|
libcl_ep_defs += [comment] + eps.export_defs
|
|
cl_validation_protos += [comment] + eps.validation_protos
|
|
libcl_windows_def_exports += [win_def_comment] + get_exports(clxml.commands[version])
|
|
|
|
clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl'])
|
|
for extension_name, ext_cmd_names in sorted(clxml.ext_data.items()):
|
|
|
|
# Extensions may have no new commands.
|
|
if not ext_cmd_names:
|
|
continue
|
|
|
|
# Detect and filter duplicate extensions.
|
|
eps = CLEntryPoints(clxml, ext_cmd_names)
|
|
|
|
comment = "\n// %s" % extension_name
|
|
win_def_comment = "\n ; %s" % (extension_name)
|
|
|
|
cl_commands += ext_cmd_names
|
|
|
|
cl_decls += [comment] + eps.decls
|
|
cl_defs += [comment] + eps.defs
|
|
libcl_ep_defs += [comment] + eps.export_defs
|
|
cl_validation_protos += [comment] + eps.validation_protos
|
|
libcl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
|
|
|
|
# Avoid writing out entry points defined by a prior extension.
|
|
for dupe in clxml.ext_dupes[extension_name]:
|
|
msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
|
|
cl_defs.append(msg)
|
|
|
|
cl_decls.append("} // namespace cl")
|
|
cl_defs.append("} // namespace cl")
|
|
|
|
write_file("cl", "CL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(cl_decls), "h",
|
|
LIBCL_HEADER_INCLUDES, "libGLESv2", "cl.xml")
|
|
write_file("cl", "CL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(cl_defs), "cpp",
|
|
LIBCL_SOURCE_INCLUDES, "libGLESv2", "cl.xml")
|
|
write_validation_header("CL", "CL", cl_validation_protos, "cl.xml",
|
|
TEMPLATE_CL_VALIDATION_HEADER)
|
|
write_stubs_header("CL", "cl", "CL", "cl.xml", CL_STUBS_HEADER_PATH, clxml.all_commands,
|
|
cl_commands, CLEntryPoints.get_packed_enums(), CL_PACKED_TYPES)
|
|
|
|
# EGL
|
|
eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
|
|
|
|
egl_validation_protos = []
|
|
egl_context_lock_protos = []
|
|
egl_decls = ["extern \"C\" {"]
|
|
egl_defs = ["extern \"C\" {"]
|
|
libegl_ep_defs = []
|
|
libegl_windows_def_exports = []
|
|
egl_commands = []
|
|
egl_capture_protos = []
|
|
egl_capture_methods = []
|
|
|
|
for major_version, minor_version in registry_xml.EGL_VERSIONS:
|
|
version = "%d_%d" % (major_version, minor_version)
|
|
annotation = "EGL_%s" % version
|
|
name_prefix = "EGL_VERSION_"
|
|
|
|
comment = version.replace("_", ".")
|
|
feature_name = "%s%s" % (name_prefix, version)
|
|
|
|
eglxml.AddCommands(feature_name, version)
|
|
|
|
egl_version_commands = eglxml.commands[version]
|
|
egl_commands += egl_version_commands
|
|
|
|
# Spec revs may have no new commands.
|
|
if not egl_version_commands:
|
|
continue
|
|
|
|
eps = EGLEntryPoints(eglxml, egl_version_commands)
|
|
|
|
comment = "\n// EGL %d.%d" % (major_version, minor_version)
|
|
win_def_comment = "\n ; EGL %d.%d" % (major_version, minor_version)
|
|
|
|
egl_decls += [comment] + eps.decls
|
|
egl_defs += [comment] + eps.defs
|
|
libegl_ep_defs += [comment] + eps.export_defs
|
|
egl_validation_protos += [comment] + eps.validation_protos
|
|
egl_context_lock_protos += [comment] + eps.context_lock_protos
|
|
libegl_windows_def_exports += [win_def_comment] + get_exports(eglxml.commands[version])
|
|
egl_capture_protos += eps.capture_protos
|
|
egl_capture_methods += eps.capture_methods
|
|
|
|
egl_decls.append("} // extern \"C\"")
|
|
egl_defs.append("} // extern \"C\"")
|
|
|
|
write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_decls), "h",
|
|
EGL_HEADER_INCLUDES, "libGLESv2", "egl.xml")
|
|
write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_defs), "cpp",
|
|
EGL_SOURCE_INCLUDES, "libGLESv2", "egl.xml")
|
|
write_stubs_header("EGL", "egl", "EGL", "egl.xml", EGL_STUBS_HEADER_PATH, eglxml.all_commands,
|
|
egl_commands, EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
|
|
|
|
eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
|
|
egl_ext_decls = ["extern \"C\" {"]
|
|
egl_ext_defs = ["extern \"C\" {"]
|
|
egl_ext_commands = []
|
|
|
|
for extension_name, ext_cmd_names in sorted(eglxml.ext_data.items()):
|
|
|
|
# Extensions may have no new commands.
|
|
if not ext_cmd_names:
|
|
continue
|
|
|
|
# Detect and filter duplicate extensions.
|
|
eps = EGLEntryPoints(eglxml, ext_cmd_names)
|
|
|
|
comment = "\n// %s" % extension_name
|
|
win_def_comment = "\n ; %s" % (extension_name)
|
|
|
|
egl_ext_commands += ext_cmd_names
|
|
|
|
egl_ext_decls += [comment] + eps.decls
|
|
egl_ext_defs += [comment] + eps.defs
|
|
libegl_ep_defs += [comment] + eps.export_defs
|
|
egl_validation_protos += [comment] + eps.validation_protos
|
|
egl_context_lock_protos += [comment] + eps.context_lock_protos
|
|
libegl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
|
|
egl_capture_protos += eps.capture_protos
|
|
egl_capture_methods += eps.capture_methods
|
|
|
|
# Avoid writing out entry points defined by a prior extension.
|
|
for dupe in eglxml.ext_dupes[extension_name]:
|
|
msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
|
|
egl_ext_defs.append(msg)
|
|
|
|
egl_ext_decls.append("} // extern \"C\"")
|
|
egl_ext_defs.append("} // extern \"C\"")
|
|
|
|
write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_ext_decls),
|
|
"h", EGL_EXT_HEADER_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
|
|
write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_ext_defs),
|
|
"cpp", EGL_EXT_SOURCE_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
|
|
write_validation_header("EGL", "EGL", egl_validation_protos, "egl.xml and egl_angle_ext.xml",
|
|
TEMPLATE_EGL_VALIDATION_HEADER)
|
|
write_context_lock_header("EGL", "EGL", egl_context_lock_protos,
|
|
"egl.xml and egl_angle_ext.xml", TEMPLATE_EGL_CONTEXT_LOCK_HEADER)
|
|
write_stubs_header("EGL", "egl_ext", "EXT extension", "egl.xml and egl_angle_ext.xml",
|
|
EGL_EXT_STUBS_HEADER_PATH, eglxml.all_commands, egl_ext_commands,
|
|
EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
|
|
|
|
write_capture_header(apis.EGL, 'egl', 'EGL', egl_capture_protos, [])
|
|
write_capture_source(apis.EGL, 'egl', 'EGL', 'all', egl_capture_methods)
|
|
|
|
wglxml = registry_xml.RegistryXML('wgl.xml')
|
|
|
|
name_prefix = "WGL_VERSION_"
|
|
version = "1_0"
|
|
comment = version.replace("_", ".")
|
|
feature_name = "{}{}".format(name_prefix, version)
|
|
wglxml.AddCommands(feature_name, version)
|
|
wgl_commands = wglxml.commands[version]
|
|
|
|
|
|
# Other versions of these functions are used
|
|
wgl_commands.remove("wglUseFontBitmaps")
|
|
wgl_commands.remove("wglUseFontOutlines")
|
|
|
|
# Formatting for outputting to def file
|
|
wgl_commands = [cmd if cmd.startswith('wgl') else 'wgl' + cmd for cmd in wgl_commands]
|
|
wgl_commands = ['\n ; WGL 1.0'] + [' {}'.format(cmd) for cmd in wgl_commands]
|
|
|
|
extension_decls.append("} // extern \"C\"")
|
|
extension_defs.append("} // extern \"C\"")
|
|
|
|
write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_HEADER,
|
|
"\n".join([item for item in extension_decls]), "h", GLES_EXT_HEADER_INCLUDES,
|
|
"libGLESv2", "gl.xml and gl_angle_ext.xml")
|
|
write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_SOURCE,
|
|
"\n".join([item for item in extension_defs]), "cpp", GLES_EXT_SOURCE_INCLUDES,
|
|
"libGLESv2", "gl.xml and gl_angle_ext.xml")
|
|
|
|
write_gl_validation_header("ESEXT", "ES extension", ext_validation_protos,
|
|
"gl.xml and gl_angle_ext.xml")
|
|
write_capture_header(apis.GLES, "gles_ext", "extension", ext_capture_protos,
|
|
ext_capture_pointer_funcs)
|
|
write_capture_source(apis.GLES, "gles_ext", "ESEXT", "extension", ext_capture_methods)
|
|
|
|
write_context_api_decls(glesdecls, "gles")
|
|
write_context_api_decls(desktop_gl_decls, "gl")
|
|
|
|
# Entry point enum
|
|
unsorted_enums = clxml.GetEnums() + eglxml.GetEnums() + xml.GetEnums() + glxml.GetEnums(
|
|
) + wglxml.GetEnums('wgl')
|
|
all_enums = [('Invalid', 'Invalid')] + sorted(list(set(unsorted_enums)))
|
|
|
|
entry_points_enum_header = TEMPLATE_ENTRY_POINTS_ENUM_HEADER.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml and gl_angle_ext.xml",
|
|
lib="GL/GLES",
|
|
entry_points_list=",\n".join([" " + enum for (enum, _) in all_enums]))
|
|
|
|
entry_points_enum_header_path = path_to("common", "entry_points_enum_autogen.h")
|
|
with open(entry_points_enum_header_path, "w") as out:
|
|
out.write(entry_points_enum_header)
|
|
out.close()
|
|
|
|
entry_points_cases = [
|
|
TEMPLATE_ENTRY_POINTS_NAME_CASE.format(enum=enum, cmd=cmd) for (enum, cmd) in all_enums
|
|
]
|
|
entry_points_enum_source = TEMPLATE_ENTRY_POINTS_ENUM_SOURCE.format(
|
|
script_name=os.path.basename(sys.argv[0]),
|
|
data_source_name="gl.xml and gl_angle_ext.xml",
|
|
lib="GL/GLES",
|
|
entry_points_name_cases="\n".join(entry_points_cases))
|
|
|
|
entry_points_enum_source_path = path_to("common", "entry_points_enum_autogen.cpp")
|
|
with open(entry_points_enum_source_path, "w") as out:
|
|
out.write(entry_points_enum_source)
|
|
out.close()
|
|
|
|
write_export_files("\n".join([item for item in libgles_ep_defs]), LIBGLESV2_EXPORT_INCLUDES,
|
|
"gl.xml and gl_angle_ext.xml", "libGLESv2", "OpenGL ES")
|
|
write_export_files("\n".join([item for item in libegl_ep_defs]),
|
|
LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE, "egl.xml and egl_angle_ext.xml",
|
|
"libEGL", "EGL")
|
|
write_export_files("\n".join([item for item in libcl_ep_defs]), LIBCL_EXPORT_INCLUDES,
|
|
"cl.xml", "libOpenCL", "CL")
|
|
|
|
libgles_ep_exports += get_egl_exports()
|
|
|
|
everything = "Khronos and ANGLE XML files"
|
|
|
|
for lib in [
|
|
"libGLESv2" + suffix
|
|
for suffix in ["", "_no_capture", "_with_capture", "_vulkan_secondaries"]
|
|
]:
|
|
write_windows_def_file(everything, lib, lib, "libGLESv2", libgles_ep_exports)
|
|
|
|
write_windows_def_file(everything, "opengl32_with_wgl", "opengl32", "libGLESv2",
|
|
libgl_ep_exports + sorted(wgl_commands))
|
|
write_windows_def_file(everything, "opengl32", "opengl32", "libGLESv2", libgl_ep_exports)
|
|
|
|
for lib in ["libEGL" + suffix for suffix in ["", "_vulkan_secondaries"]]:
|
|
write_windows_def_file("egl.xml and egl_angle_ext.xml", lib, lib, "libEGL",
|
|
libegl_windows_def_exports)
|
|
|
|
all_gles_param_types = sorted(GLEntryPoints.all_param_types)
|
|
all_egl_param_types = sorted(EGLEntryPoints.all_param_types)
|
|
resource_id_types = get_resource_id_types(GLEntryPoints.all_param_types)
|
|
# Get a sorted list of param types without duplicates
|
|
all_param_types = sorted(list(set(all_gles_param_types + all_egl_param_types)))
|
|
write_capture_helper_header(all_param_types)
|
|
write_capture_helper_source(all_param_types)
|
|
write_capture_replay_source(xml.all_commands, all_commands_with_suffix,
|
|
GLEntryPoints.get_packed_enums(), eglxml.all_commands,
|
|
egl_commands, EGLEntryPoints.get_packed_enums(), resource_id_types)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|