Update from chromium 62675d9fb31fb8cedc40f68e78e8445a74f362e7
This is Cr-Commit-Position: refs/heads/master@{#300999}
Review URL: https://codereview.chromium.org/670183003
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 14c778a..94c3b34 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1546,6 +1546,12 @@
'type': 'StateSet',
'state': 'BlendFunc',
},
+ 'BlendBarrierKHR': {
+ 'gl_test_func': 'glBlendBarrierKHR',
+ 'extension': True,
+ 'extension_flag': 'blend_equation_advanced',
+ 'client_test': False,
+ },
'SampleCoverage': {'decoder_func': 'DoSampleCoverage'},
'StencilFunc': {
'type': 'StateSetFrontBack',
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 71e3c82..392bb22 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -958,6 +958,9 @@
void GLES2MatrixLoadIdentityCHROMIUM(GLenum matrixMode) {
gles2::GetGLContext()->MatrixLoadIdentityCHROMIUM(matrixMode);
}
+void GLES2BlendBarrierKHR() {
+ gles2::GetGLContext()->BlendBarrierKHR();
+}
namespace gles2 {
@@ -1817,6 +1820,10 @@
reinterpret_cast<GLES2FunctionPointer>(glMatrixLoadIdentityCHROMIUM),
},
{
+ "glBlendBarrierKHR",
+ reinterpret_cast<GLES2FunctionPointer>(glBlendBarrierKHR),
+ },
+ {
NULL,
NULL,
},
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index c8432da..24d8be2 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -1929,4 +1929,11 @@
}
}
+void BlendBarrierKHR() {
+ gles2::cmds::BlendBarrierKHR* c = GetCmdSpace<gles2::cmds::BlendBarrierKHR>();
+ if (c) {
+ c->Init();
+ }
+}
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 5177941..3ef98dd 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -691,4 +691,6 @@
void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override;
+virtual void BlendBarrierKHR() override;
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index 50d7f82..32b1347 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -2162,4 +2162,12 @@
CheckGLError();
}
+void GLES2Implementation::BlendBarrierKHR() {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBlendBarrierKHR("
+ << ")");
+ helper_->BlendBarrierKHR();
+ CheckGLError();
+}
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 595bde1..d840804 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -495,4 +495,5 @@
GLfloat uv_height) = 0;
virtual void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) = 0;
virtual void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) = 0;
+virtual void BlendBarrierKHR() = 0;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index bd1a73e..687ff48 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -486,4 +486,5 @@
GLfloat uv_height) override;
void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override;
void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override;
+void BlendBarrierKHR() override;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
index 0936086..e78b07c 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -851,4 +851,6 @@
}
void GLES2InterfaceStub::MatrixLoadIdentityCHROMIUM(GLenum /* matrixMode */) {
}
+void GLES2InterfaceStub::BlendBarrierKHR() {
+}
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_INTERFACE_STUB_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index 22c12bc..a599eb4 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -486,4 +486,5 @@
GLfloat uv_height) override;
void MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat* m) override;
void MatrixLoadIdentityCHROMIUM(GLenum matrixMode) override;
+void BlendBarrierKHR() override;
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
index d1b5fce..3173a25 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -1509,4 +1509,9 @@
gl_->MatrixLoadIdentityCHROMIUM(matrixMode);
}
+void GLES2TraceImplementation::BlendBarrierKHR() {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BlendBarrierKHR");
+ gl_->BlendBarrierKHR();
+}
+
#endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_TRACE_IMPLEMENTATION_IMPL_AUTOGEN_H_
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index 49cb433..37c33be 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -222,3 +222,5 @@
GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM (GLenumMatrixMode matrixMode, const GLfloat* m);
GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM (GLenumMatrixMode matrixMode);
+// Extension KHR_blend_equation_advanced
+GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void);
diff --git a/gpu/command_buffer/command_buffer_nacl.gyp b/gpu/command_buffer/command_buffer_nacl.gyp
index aabd1c8..319fc67 100644
--- a/gpu/command_buffer/command_buffer_nacl.gyp
+++ b/gpu/command_buffer/command_buffer_nacl.gyp
@@ -23,10 +23,13 @@
'build_glibc': 0,
'build_newlib': 0,
'build_irt': 1,
+ 'build_pnacl_newlib': 0,
+ 'build_nonsfi_helper': 1,
},
'dependencies': [
'../../native_client/tools.gyp:prep_toolchain',
'../../base/base_nacl.gyp:base_nacl',
+ '../../base/base_nacl.gyp:base_nacl_nonsfi',
'../../third_party/khronos/khronos.gyp:khronos_headers',
],
},
diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc
index f51071a..eacf10c 100644
--- a/gpu/command_buffer/common/capabilities.cc
+++ b/gpu/command_buffer/common/capabilities.cc
@@ -20,7 +20,9 @@
sync_query(false),
image(false),
future_sync_points(false),
- blend_minmax(false) {
+ blend_minmax(false),
+ blend_equation_advanced(false),
+ blend_equation_advanced_coherent(false) {
}
} // namespace gpu
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index df97d1f..9de6023 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -24,6 +24,8 @@
bool image;
bool future_sync_points;
bool blend_minmax;
+ bool blend_equation_advanced;
+ bool blend_equation_advanced_coherent;
Capabilities();
};
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index ccdc040..487e8b7 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -9014,4 +9014,30 @@
COMPILE_ASSERT(offsetof(MatrixLoadIdentityCHROMIUM, matrixMode) == 4,
OffsetOf_MatrixLoadIdentityCHROMIUM_matrixMode_not_4);
+struct BlendBarrierKHR {
+ typedef BlendBarrierKHR ValueType;
+ static const CommandId kCmdId = kBlendBarrierKHR;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init() { SetHeader(); }
+
+ void* Set(void* cmd) {
+ static_cast<ValueType*>(cmd)->Init();
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+};
+
+COMPILE_ASSERT(sizeof(BlendBarrierKHR) == 4, Sizeof_BlendBarrierKHR_is_not_4);
+COMPILE_ASSERT(offsetof(BlendBarrierKHR, header) == 0,
+ OffsetOf_BlendBarrierKHR_header_not_0);
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 7b7845b..b26afb1 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3432,4 +3432,13 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, BlendBarrierKHR) {
+ cmds::BlendBarrierKHR& cmd = *GetBufferAs<cmds::BlendBarrierKHR>();
+ void* next_cmd = cmd.Set(&cmd);
+ EXPECT_EQ(static_cast<uint32_t>(cmds::BlendBarrierKHR::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
#endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 030ada2..8bd5c0a 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -209,7 +209,8 @@
OP(DiscardBackbufferCHROMIUM) /* 450 */ \
OP(ScheduleOverlayPlaneCHROMIUM) /* 451 */ \
OP(MatrixLoadfCHROMIUMImmediate) /* 452 */ \
- OP(MatrixLoadIdentityCHROMIUM) /* 453 */
+ OP(MatrixLoadIdentityCHROMIUM) /* 453 */ \
+ OP(BlendBarrierKHR) /* 454 */
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index bda7a82..a21f630 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -144,7 +144,9 @@
angle_texture_usage(false),
ext_texture_storage(false),
chromium_path_rendering(false),
- ext_blend_minmax(false) {
+ ext_blend_minmax(false),
+ blend_equation_advanced(false),
+ blend_equation_advanced_coherent(false) {
}
FeatureInfo::Workarounds::Workarounds() :
@@ -880,6 +882,40 @@
feature_flags_.chromium_sync_query = true;
}
+ bool blend_equation_advanced_coherent =
+ extensions.Contains("GL_NV_blend_equation_advanced_coherent") ||
+ extensions.Contains("GL_KHR_blend_equation_advanced_coherent");
+
+ if (blend_equation_advanced_coherent ||
+ extensions.Contains("GL_NV_blend_equation_advanced") ||
+ extensions.Contains("GL_KHR_blend_equation_advanced")) {
+ const GLenum equations[] = {GL_MULTIPLY_KHR,
+ GL_SCREEN_KHR,
+ GL_OVERLAY_KHR,
+ GL_DARKEN_KHR,
+ GL_LIGHTEN_KHR,
+ GL_COLORDODGE_KHR,
+ GL_COLORBURN_KHR,
+ GL_HARDLIGHT_KHR,
+ GL_SOFTLIGHT_KHR,
+ GL_DIFFERENCE_KHR,
+ GL_EXCLUSION_KHR,
+ GL_HSL_HUE_KHR,
+ GL_HSL_SATURATION_KHR,
+ GL_HSL_COLOR_KHR,
+ GL_HSL_LUMINOSITY_KHR};
+
+ for (GLenum equation : equations)
+ validators_.equation.AddValue(equation);
+ if (blend_equation_advanced_coherent)
+ AddExtensionString("GL_KHR_blend_equation_advanced_coherent");
+
+ AddExtensionString("GL_KHR_blend_equation_advanced");
+ feature_flags_.blend_equation_advanced = true;
+ feature_flags_.blend_equation_advanced_coherent =
+ blend_equation_advanced_coherent;
+ }
+
if (extensions.Contains("GL_NV_path_rendering")) {
if (extensions.Contains("GL_EXT_direct_state_access") || is_es3) {
AddExtensionString("GL_CHROMIUM_path_rendering");
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index a30581a..0bc00a0 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -72,6 +72,8 @@
bool ext_texture_storage;
bool chromium_path_rendering;
bool ext_blend_minmax;
+ bool blend_equation_advanced;
+ bool blend_equation_advanced_coherent;
};
struct Workarounds {
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc
index 004eeee..a97188f 100644
--- a/gpu/command_buffer/service/feature_info_unittest.cc
+++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -1347,5 +1347,39 @@
Not(HasSubstr("GL_CHROMIUM_path_rendering")));
}
+TEST_F(FeatureInfoTest, InitializeNoKHR_blend_equation_advanced) {
+ SetupInitExpectationsWithGLVersion("", "", "4.3");
+ EXPECT_FALSE(info_->feature_flags().blend_equation_advanced);
+ EXPECT_THAT(info_->extensions(),
+ Not(HasSubstr("GL_KHR_blend_equation_advanced")));
+}
+
+TEST_F(FeatureInfoTest, InitializeKHR_blend_equations_advanced) {
+ SetupInitExpectations("GL_KHR_blend_equation_advanced");
+ EXPECT_THAT(info_->extensions(), HasSubstr("GL_KHR_blend_equation_advanced"));
+ EXPECT_TRUE(info_->feature_flags().blend_equation_advanced);
+}
+
+TEST_F(FeatureInfoTest, InitializeNV_blend_equations_advanced) {
+ SetupInitExpectations("GL_NV_blend_equation_advanced");
+ EXPECT_THAT(info_->extensions(), HasSubstr("GL_KHR_blend_equation_advanced"));
+ EXPECT_TRUE(info_->feature_flags().blend_equation_advanced);
+}
+
+TEST_F(FeatureInfoTest, InitializeNoKHR_blend_equation_advanced_coherent) {
+ SetupInitExpectationsWithGLVersion("", "", "4.3");
+ EXPECT_FALSE(info_->feature_flags().blend_equation_advanced_coherent);
+ EXPECT_THAT(info_->extensions(),
+ Not(HasSubstr("GL_KHR_blend_equation_advanced_coherent")));
+}
+
+TEST_F(FeatureInfoTest, InitializeKHR_blend_equations_advanced_coherent) {
+ SetupInitExpectations("GL_KHR_blend_equation_advanced_coherent");
+ EXPECT_THAT(info_->extensions(),
+ HasSubstr("GL_KHR_blend_equation_advanced_coherent"));
+ EXPECT_TRUE(info_->feature_flags().blend_equation_advanced);
+ EXPECT_TRUE(info_->feature_flags().blend_equation_advanced_coherent);
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0b8d68d..01d20c7 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2742,6 +2742,10 @@
caps.image = true;
caps.blend_minmax = feature_info_->feature_flags().ext_blend_minmax;
+ caps.blend_equation_advanced =
+ feature_info_->feature_flags().blend_equation_advanced;
+ caps.blend_equation_advanced_coherent =
+ feature_info_->feature_flags().blend_equation_advanced_coherent;
return caps;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index dade363..02d914f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -3302,6 +3302,22 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleBlendBarrierKHR(
+ uint32_t immediate_data_size,
+ const void* cmd_data) {
+ const gles2::cmds::BlendBarrierKHR& c =
+ *static_cast<const gles2::cmds::BlendBarrierKHR*>(cmd_data);
+ (void)c;
+ if (!features().blend_equation_advanced) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, "glBlendBarrierKHR", "function not available");
+ return error::kNoError;
+ }
+
+ glBlendBarrierKHR();
+ return error::kNoError;
+}
+
bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
switch (cap) {
case GL_BLEND:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
index 311e798..ac80190 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
@@ -35,6 +35,27 @@
INSTANTIATE_TEST_CASE_P(Service,
GLES2DecoderTestWithCHROMIUMPathRendering,
::testing::Bool());
+
+class GLES2DecoderTestWithBlendEquationAdvanced : public GLES2DecoderTest {
+ public:
+ GLES2DecoderTestWithBlendEquationAdvanced() {}
+ virtual void SetUp() override {
+ InitState init;
+ init.gl_version = "opengl es 2.0";
+ init.has_alpha = true;
+ init.has_depth = true;
+ init.request_alpha = true;
+ init.request_depth = true;
+ init.bind_generates_resource = true;
+ init.extensions = "GL_KHR_blend_equation_advanced";
+ InitDecoder(init);
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(Service,
+ GLES2DecoderTestWithBlendEquationAdvanced,
+ ::testing::Bool());
+
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h"
} // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h
index a81be2f..57db672 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h
@@ -44,4 +44,13 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
+
+TEST_P(GLES2DecoderTestWithBlendEquationAdvanced, BlendBarrierKHRValidArgs) {
+ EXPECT_CALL(*gl_, BlendBarrierKHR());
+ SpecializedSetup<cmds::BlendBarrierKHR, 0>(true);
+ cmds::BlendBarrierKHR cmd;
+ cmd.Init();
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_EXTENSIONS_AUTOGEN_H_