diff options
author | zmo <zmo@chromium.org> | 2015-01-29 12:17:39 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-29 20:18:42 +0000 |
commit | 38923567f136fb3dda353b84700cd47ac0077fbd (patch) | |
tree | 3984643b5eba34d765b6fd1364cf22919d6e5bbe /gpu | |
parent | 836b0aaeae4a2984c9f0c10c69fbe9627b15a542 (diff) | |
download | chromium_src-38923567f136fb3dda353b84700cd47ac0077fbd.zip chromium_src-38923567f136fb3dda353b84700cd47ac0077fbd.tar.gz chromium_src-38923567f136fb3dda353b84700cd47ac0077fbd.tar.bz2 |
Add glTransformFeedbackVaryings to GPU command buffer.
BUG=429053
TEST=gpu_unittests
R=vmiura@chromium.org
Review URL: https://codereview.chromium.org/872713004
Cr-Commit-Position: refs/heads/master@{#313771}
Diffstat (limited to 'gpu')
24 files changed, 617 insertions, 184 deletions
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index f84d959..88bed32 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -163,6 +163,7 @@ #define glTexStorage3D GLES2_GET_FUN(TexStorage3D) #define glTexSubImage2D GLES2_GET_FUN(TexSubImage2D) #define glTexSubImage3D GLES2_GET_FUN(TexSubImage3D) +#define glTransformFeedbackVaryings GLES2_GET_FUN(TransformFeedbackVaryings) #define glUniform1f GLES2_GET_FUN(Uniform1f) #define glUniform1fv GLES2_GET_FUN(Uniform1fv) #define glUniform1i GLES2_GET_FUN(Uniform1i) diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index a2dc137..b0884b6 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -939,6 +939,16 @@ _NAMED_TYPE_INFO = { 'GL_PIXEL_PACK_BUFFER', ], }, + 'BufferMode': { + 'type': 'GLenum', + 'valid': [ + 'GL_INTERLEAVED_ATTRIBS', + 'GL_SEPARATE_ATTRIBS', + ], + 'invalid': [ + 'GL_PIXEL_PACK_BUFFER', + ], + }, 'FrameBufferParameter': { 'type': 'GLenum', 'valid': [ @@ -2452,6 +2462,7 @@ _FUNCTION_INFO = { 'ShaderSource': { 'type': 'PUTSTR', 'decoder_func': 'DoShaderSource', + 'expectation': False, 'data_transfer_methods': ['bucket'], 'cmd_args': 'GLuint shader, const char** str', @@ -2549,6 +2560,14 @@ _FUNCTION_INFO = { 'const void* pixels, GLboolean internal', 'unsafe': True, }, + 'TransformFeedbackVaryings': { + 'type': 'PUTSTR', + 'data_transfer_methods': ['bucket'], + 'decoder_func': 'DoTransformFeedbackVaryings', + 'cmd_args': + 'GLuint program, const char** varyings, GLenum buffermode', + 'unsafe': True, + }, 'Uniform1f': {'type': 'PUTXn', 'count': 1}, 'Uniform1fv': { 'type': 'PUTn', @@ -6426,7 +6445,7 @@ class PUTSTRHandler(ArrayArgTypeHandler): total_size += 1; total_size *= sizeof(GLint); if (!total_size.IsValid()) { - SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow"); + SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow"); return; } size_t header_size = total_size.ValueOrDefault(0); @@ -6437,7 +6456,7 @@ class PUTSTRHandler(ArrayArgTypeHandler): if (%(data)s[ii]) {""" if length_arg == None: size_code_block += """ - len = base::static_cast<GLint>(strlen(%(data)s[ii]));""" + len = static_cast<GLint>(strlen(%(data)s[ii]));""" else: size_code_block += """ len = (%(length)s && %(length)s[ii] >= 0) ? @@ -6447,15 +6466,16 @@ class PUTSTRHandler(ArrayArgTypeHandler): total_size += len; total_size += 1; // NULL at the end of each char array. if (!total_size.IsValid()) { - SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow"); + SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow"); return; } header[ii + 1] = len; } """ file.Write(size_code_block % { - 'data': data_arg.name, - 'length': length_arg.name if not length_arg == None else '' + 'data': data_arg.name, + 'length': length_arg.name if not length_arg == None else '', + 'func_name': func.name, }) data_code_block = """ // Pack data into a bucket on the service. helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0)); @@ -6469,14 +6489,14 @@ class PUTSTRHandler(ArrayArgTypeHandler): checked_size += 1; // NULL in the end. } if (!checked_size.IsValid()) { - SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow"); + SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow"); return; } size_t size = checked_size.ValueOrDefault(0); while (size) { ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); if (!buffer.valid() || buffer.size() == 0) { - SetGLError(GL_OUT_OF_MEMORY, "glShaderSource", "too large"); + SetGLError(GL_OUT_OF_MEMORY, "gl%(func_name)s", "too large"); return; } size_t copy_size = buffer.size(); @@ -6500,19 +6520,20 @@ class PUTSTRHandler(ArrayArgTypeHandler): DCHECK_EQ(total_size.ValueOrDefault(0), offset); """ file.Write(data_code_block % { - 'data': data_arg.name, - 'length': length_arg.name if not length_arg == None else '' + 'data': data_arg.name, + 'length': length_arg.name if not length_arg == None else '', + 'func_name': func.name, }) - bucket_cmd_arg_string = "" - for arg in func.GetCmdArgs()[0:-2]: - if bucket_cmd_arg_string: - bucket_cmd_arg_string += ", " - bucket_cmd_arg_string += arg.name - if bucket_cmd_arg_string: - bucket_cmd_arg_string += ", " - bucket_cmd_arg_string += 'kResultBucketId' + bucket_args = [] + for arg in func.GetOriginalArgs(): + if arg.name == 'count' or arg == self.__GetLengthArg(func): + continue + if arg == self.__GetDataArg(func): + bucket_args.append('kResultBucketId') + else: + bucket_args.append(arg.name) file.Write(" helper_->%sBucket(%s);\n" % - (func.name, bucket_cmd_arg_string)) + (func.name, ", ".join(bucket_args))) file.Write(" helper_->SetBucketSize(kResultBucketId, 0);"); file.Write(" CheckGLError();\n") file.Write("}\n") @@ -6543,7 +6564,7 @@ TEST_F(GLES2ImplementationTest, %(name)s) { cmd::SetToken set_token2; cmd::SetBucketData set_bucket_data2; cmd::SetToken set_token3; - cmds::ShaderSourceBucket shader_source_bucket; + cmds::%(name)sBucket cmd_bucket; cmd::SetBucketSize clear_bucket_size; }; @@ -6563,7 +6584,7 @@ TEST_F(GLES2ImplementationTest, %(name)s) { kBucketId, kHeaderSize + kString1Size, kString2Size, mem2.id, mem2.offset); expected.set_token3.Init(GetNextToken()); - expected.shader_source_bucket.Init(%(cmd_args)s, kBucketId); + expected.cmd_bucket.Init(%(bucket_args)s); expected.clear_bucket_size.Init(kBucketId, 0); const char* kStrings[] = { kString1, kString2 }; gl_->%(name)s(%(gl_args)s); @@ -6571,21 +6592,22 @@ TEST_F(GLES2ImplementationTest, %(name)s) { } """ gl_args = [] - cmd_args = [] + bucket_args = [] for arg in func.GetOriginalArgs(): if arg == self.__GetDataArg(func): gl_args.append('kStrings') + bucket_args.append('kBucketId') elif arg == self.__GetLengthArg(func): gl_args.append('NULL') elif arg.name == 'count': gl_args.append('2') else: gl_args.append(arg.GetValidClientSideArg(func)) - cmd_args.append(arg.GetValidClientSideArg(func)) + bucket_args.append(arg.GetValidClientSideArg(func)) file.Write(code % { 'name': func.name, 'gl_args': ", ".join(gl_args), - 'cmd_args': ", ".join(cmd_args), + 'bucket_args': ", ".join(bucket_args), }) if self.__GetLengthArg(func) == None: @@ -6622,7 +6644,7 @@ TEST_F(GLES2ImplementationTest, %(name)sWithLength) { expected.set_bucket_data.Init( kBucketId, kHeaderSize, kStringSize + 1, mem1.id, mem1.offset); expected.set_token2.Init(GetNextToken()); - expected.shader_source_bucket.Init(%(cmd_args)s, kBucketId); + expected.shader_source_bucket.Init(%(bucket_args)s); expected.clear_bucket_size.Init(kBucketId, 0); const char* kStrings[] = { kString }; const GLint kLength[] = { kStringSize }; @@ -6643,33 +6665,42 @@ TEST_F(GLES2ImplementationTest, %(name)sWithLength) { file.Write(code % { 'name': func.name, 'gl_args': ", ".join(gl_args), - 'cmd_args': ", ".join(cmd_args), + 'bucket_args': ", ".join(bucket_args), }) def WriteBucketServiceUnitTest(self, func, file, *extras): """Overrriden from TypeHandler.""" cmd_args = [] cmd_args_with_invalid_id = [] + gl_args = [] for index, arg in enumerate(func.GetOriginalArgs()): - if (arg == self.__GetLengthArg(func) or - arg == self.__GetDataArg(func) or arg.name == 'count'): - continue - if index == 0: # Resource ID arg + if arg == self.__GetLengthArg(func): + gl_args.append('_') + elif arg.name == 'count': + gl_args.append('1') + elif arg == self.__GetDataArg(func): + cmd_args.append('kBucketId') + cmd_args_with_invalid_id.append('kBucketId') + gl_args.append('_') + elif index == 0: # Resource ID arg cmd_args.append(arg.GetValidArg(func)) cmd_args_with_invalid_id.append('kInvalidClientId') + gl_args.append(arg.GetValidGLArg(func)) else: cmd_args.append(arg.GetValidArg(func)) cmd_args_with_invalid_id.append(arg.GetValidArg(func)) + gl_args.append(arg.GetValidGLArg(func)) test = """ TEST_P(%(test_name)s, %(name)sValidArgs) { + EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)); const uint32 kBucketId = 123; const char kSource0[] = "hello"; const char* kSource[] = { kSource0 }; const char kValidStrEnd = 0; SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); cmds::%(name)s cmd; - cmd.Init(%(cmd_args)s, kBucketId); + cmd.Init(%(cmd_args)s); decoder_->set_unsafe_es3_apis_enabled(true); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));""" if func.IsUnsafe(): @@ -6682,6 +6713,7 @@ TEST_P(%(test_name)s, %(name)sValidArgs) { """ self.WriteValidUnitTest(func, file, test, { 'cmd_args': ", ".join(cmd_args), + 'gl_args': ", ".join(gl_args), }, *extras) test = """ @@ -6693,11 +6725,11 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs) { decoder_->set_unsafe_es3_apis_enabled(true); cmds::%(name)s cmd; // Test no bucket. - cmd.Init(%(cmd_args)s, kBucketId); + cmd.Init(%(cmd_args)s); EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); // Test invalid client. SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); - cmd.Init(%(cmd_args_with_invalid_id)s, kBucketId); + cmd.Init(%(cmd_args_with_invalid_id)s); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } @@ -6715,24 +6747,18 @@ TEST_P(%(test_name)s, %(name)sInvalidHeader) { const char kValidStrEnd = 0; const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource)); const GLsizei kTests[] = { - kCount, + kCount + 1, 0, std::numeric_limits<GLsizei>::max(), -1, - kCount, }; decoder_->set_unsafe_es3_apis_enabled(true); for (size_t ii = 0; ii < arraysize(kTests); ++ii) { SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd); cmds::%(name)s cmd; - cmd.Init(%(cmd_args)s, kBucketId); - if (kTests[ii] == kCount) { - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } else { - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - } + cmd.Init(%(cmd_args)s); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); } - EXPECT_EQ(GL_NO_ERROR, GetGLError()); } """ self.WriteValidUnitTest(func, file, test, { @@ -6747,10 +6773,9 @@ TEST_P(%(test_name)s, %(name)sInvalidStringEnding) { const char kInvalidStrEnd = '*'; SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd); cmds::%(name)s cmd; - cmd.Init(%(cmd_args)s, kBucketId); + cmd.Init(%(cmd_args)s); decoder_->set_unsafe_es3_apis_enabled(true); EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); } """ self.WriteValidUnitTest(func, file, test, { diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 3834527..503fff0 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -676,6 +676,13 @@ void GLES2TexSubImage3D(GLenum target, width, height, depth, format, type, pixels); } +void GLES2TransformFeedbackVaryings(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) { + gles2::GetGLContext()->TransformFeedbackVaryings(program, count, varyings, + buffermode); +} void GLES2Uniform1f(GLint location, GLfloat x) { gles2::GetGLContext()->Uniform1f(location, x); } @@ -1837,6 +1844,10 @@ extern const NameToFunc g_gles2_function_table[] = { reinterpret_cast<GLES2FunctionPointer>(glTexSubImage3D), }, { + "glTransformFeedbackVaryings", + reinterpret_cast<GLES2FunctionPointer>(glTransformFeedbackVaryings), + }, + { "glUniform1f", reinterpret_cast<GLES2FunctionPointer>(glUniform1f), }, diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 186a5a5..2ac4d69 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1435,6 +1435,16 @@ void TexSubImage3D(GLenum target, } } +void TransformFeedbackVaryingsBucket(GLuint program, + uint32_t varyings_bucket_id, + GLenum buffermode) { + gles2::cmds::TransformFeedbackVaryingsBucket* c = + GetCmdSpace<gles2::cmds::TransformFeedbackVaryingsBucket>(); + if (c) { + c->Init(program, varyings_bucket_id, buffermode); + } +} + void Uniform1f(GLint location, GLfloat x) { gles2::cmds::Uniform1f* c = GetCmdSpace<gles2::cmds::Uniform1f>(); if (c) { diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 7d7b0a7..3a6e5f3 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -509,6 +509,11 @@ void TexSubImage3D(GLenum target, GLenum type, const void* pixels) override; +void TransformFeedbackVaryings(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) override; + void Uniform1f(GLint location, GLfloat x) override; void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) override; diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 67b88bf..d84c123 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -1968,6 +1968,100 @@ void GLES2Implementation::TexStorage3D(GLenum target, CheckGLError(); } +void GLES2Implementation::TransformFeedbackVaryings(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTransformFeedbackVaryings(" + << program << ", " << count << ", " + << static_cast<const void*>(varyings) << ", " + << GLES2Util::GetStringBufferMode(buffermode) << ")"); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei ii = 0; ii < count; ++ii) { + if (varyings[ii]) { + GPU_CLIENT_LOG(" " << ii << ": ---\n" << varyings[ii] << "\n---"); + } else { + GPU_CLIENT_LOG(" " << ii << ": NULL"); + } + } + }); + if (count < 0) { + SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "count < 0"); + return; + } + // Compute the total size. + base::CheckedNumeric<size_t> total_size = count; + total_size += 1; + total_size *= sizeof(GLint); + if (!total_size.IsValid()) { + SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "overflow"); + return; + } + size_t header_size = total_size.ValueOrDefault(0); + std::vector<GLint> header(count + 1); + header[0] = static_cast<GLint>(count); + for (GLsizei ii = 0; ii < count; ++ii) { + GLint len = 0; + if (varyings[ii]) { + len = static_cast<GLint>(strlen(varyings[ii])); + } + total_size += len; + total_size += 1; // NULL at the end of each char array. + if (!total_size.IsValid()) { + SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "overflow"); + return; + } + header[ii + 1] = len; + } + // Pack data into a bucket on the service. + helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0)); + size_t offset = 0; + for (GLsizei ii = 0; ii <= count; ++ii) { + const char* src = (ii == 0) ? reinterpret_cast<const char*>(&header[0]) + : varyings[ii - 1]; + base::CheckedNumeric<size_t> checked_size = + (ii == 0) ? header_size : static_cast<size_t>(header[ii]); + if (ii > 0) { + checked_size += 1; // NULL in the end. + } + if (!checked_size.IsValid()) { + SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "overflow"); + return; + } + size_t size = checked_size.ValueOrDefault(0); + while (size) { + ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); + if (!buffer.valid() || buffer.size() == 0) { + SetGLError(GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings", + "too large"); + return; + } + size_t copy_size = buffer.size(); + if (ii > 0 && buffer.size() == size) + --copy_size; + if (copy_size) + memcpy(buffer.address(), src, copy_size); + if (copy_size < buffer.size()) { + // Append NULL in the end. + DCHECK(copy_size + 1 == buffer.size()); + char* str = reinterpret_cast<char*>(buffer.address()); + str[copy_size] = 0; + } + helper_->SetBucketData(kResultBucketId, offset, buffer.size(), + buffer.shm_id(), buffer.offset()); + offset += buffer.size(); + src += buffer.size(); + size -= buffer.size(); + } + } + DCHECK_EQ(total_size.ValueOrDefault(0), offset); + helper_->TransformFeedbackVaryingsBucket(program, kResultBucketId, + buffermode); + helper_->SetBucketSize(kResultBucketId, 0); + CheckGLError(); +} + void GLES2Implementation::Uniform1f(GLint location, GLfloat x) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniform1f(" << location << ", " diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index cc9c795..743458b 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h @@ -1438,7 +1438,7 @@ TEST_F(GLES2ImplementationTest, ShaderSource) { cmd::SetToken set_token2; cmd::SetBucketData set_bucket_data2; cmd::SetToken set_token3; - cmds::ShaderSourceBucket shader_source_bucket; + cmds::ShaderSourceBucket cmd_bucket; cmd::SetBucketSize clear_bucket_size; }; @@ -1457,7 +1457,7 @@ TEST_F(GLES2ImplementationTest, ShaderSource) { expected.set_bucket_data2.Init(kBucketId, kHeaderSize + kString1Size, kString2Size, mem2.id, mem2.offset); expected.set_token3.Init(GetNextToken()); - expected.shader_source_bucket.Init(1, kBucketId); + expected.cmd_bucket.Init(1, kBucketId); expected.clear_bucket_size.Init(kBucketId, 0); const char* kStrings[] = {kString1, kString2}; gl_->ShaderSource(1, 2, kStrings, NULL); @@ -1634,6 +1634,54 @@ TEST_F(GLES2ImplementationTest, TexStorage3D) { EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, TransformFeedbackVaryings) { + const uint32 kBucketId = GLES2Implementation::kResultBucketId; + const char* kString1 = "happy"; + const char* kString2 = "ending"; + const size_t kString1Size = ::strlen(kString1) + 1; + const size_t kString2Size = ::strlen(kString2) + 1; + const size_t kHeaderSize = sizeof(GLint) * 3; + const size_t kSourceSize = kHeaderSize + kString1Size + kString2Size; + const size_t kPaddedHeaderSize = + transfer_buffer_->RoundToAlignment(kHeaderSize); + const size_t kPaddedString1Size = + transfer_buffer_->RoundToAlignment(kString1Size); + const size_t kPaddedString2Size = + transfer_buffer_->RoundToAlignment(kString2Size); + struct Cmds { + cmd::SetBucketSize set_bucket_size; + cmd::SetBucketData set_bucket_header; + cmd::SetToken set_token1; + cmd::SetBucketData set_bucket_data1; + cmd::SetToken set_token2; + cmd::SetBucketData set_bucket_data2; + cmd::SetToken set_token3; + cmds::TransformFeedbackVaryingsBucket cmd_bucket; + cmd::SetBucketSize clear_bucket_size; + }; + + ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); + ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); + ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); + + Cmds expected; + expected.set_bucket_size.Init(kBucketId, kSourceSize); + expected.set_bucket_header.Init(kBucketId, 0, kHeaderSize, mem0.id, + mem0.offset); + expected.set_token1.Init(GetNextToken()); + expected.set_bucket_data1.Init(kBucketId, kHeaderSize, kString1Size, mem1.id, + mem1.offset); + expected.set_token2.Init(GetNextToken()); + expected.set_bucket_data2.Init(kBucketId, kHeaderSize + kString1Size, + kString2Size, mem2.id, mem2.offset); + expected.set_token3.Init(GetNextToken()); + expected.cmd_bucket.Init(1, kBucketId, GL_INTERLEAVED_ATTRIBS); + expected.clear_bucket_size.Init(kBucketId, 0); + const char* kStrings[] = {kString1, kString2}; + gl_->TransformFeedbackVaryings(1, 2, kStrings, GL_INTERLEAVED_ATTRIBS); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, Uniform1f) { struct Cmds { cmds::Uniform1f cmd; diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 4de273d..c3a2c3e 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -374,6 +374,10 @@ virtual void TexSubImage3D(GLenum target, GLenum format, GLenum type, const void* pixels) = 0; +virtual void TransformFeedbackVaryings(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) = 0; virtual void Uniform1f(GLint location, GLfloat x) = 0; virtual void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) = 0; virtual void Uniform1i(GLint location, GLint x) = 0; diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 8bc24d0..34a0c426 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -367,6 +367,10 @@ void TexSubImage3D(GLenum target, GLenum format, GLenum type, const void* pixels) override; +void TransformFeedbackVaryings(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) override; void Uniform1f(GLint location, GLfloat x) override; void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) override; void Uniform1i(GLint location, GLint x) override; 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 44a0ec1..cf121fc 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -605,6 +605,12 @@ void GLES2InterfaceStub::TexSubImage3D(GLenum /* target */, GLenum /* type */, const void* /* pixels */) { } +void GLES2InterfaceStub::TransformFeedbackVaryings( + GLuint /* program */, + GLsizei /* count */, + const char* const* /* varyings */, + GLenum /* buffermode */) { +} void GLES2InterfaceStub::Uniform1f(GLint /* location */, GLfloat /* x */) { } void GLES2InterfaceStub::Uniform1fv(GLint /* location */, diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index aae81ef..db9b375 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -367,6 +367,10 @@ void TexSubImage3D(GLenum target, GLenum format, GLenum type, const void* pixels) override; +void TransformFeedbackVaryings(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) override; void Uniform1f(GLint location, GLfloat x) override; void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) override; void Uniform1i(GLint location, GLint x) override; 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 85be302..33bc3ae 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -1036,6 +1036,15 @@ void GLES2TraceImplementation::TexSubImage3D(GLenum target, depth, format, type, pixels); } +void GLES2TraceImplementation::TransformFeedbackVaryings( + GLuint program, + GLsizei count, + const char* const* varyings, + GLenum buffermode) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::TransformFeedbackVaryings"); + gl_->TransformFeedbackVaryings(program, count, varyings, buffermode); +} + void GLES2TraceImplementation::Uniform1f(GLint location, GLfloat x) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::Uniform1f"); gl_->Uniform1f(location, x); diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 720e8db..dc4ce3a 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -153,6 +153,7 @@ GL_APICALL void GL_APIENTRY glTexParameteriv (GLenumTextureBindTarget ta GL_APICALL void GL_APIENTRY glTexStorage3D (GLenumTexture3DTarget target, GLsizei levels, GLenumTextureInternalFormatStorage internalFormat, GLsizei width, GLsizei height, GLsizei depth); GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenumTextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenumTextureFormat format, GLenumPixelType type, const void* pixels); GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenumTexture3DTarget target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenumTextureFormat format, GLenumPixelType type, const void* pixels); +GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLidProgram program, GLsizeiNotNegative count, const char* const* varyings, GLenumBufferMode buffermode); GL_APICALL void GL_APIENTRY glUniform1f (GLintUniformLocation location, GLfloat x); GL_APICALL void GL_APIENTRY glUniform1fv (GLintUniformLocation location, GLsizeiNotNegative count, const GLfloat* v); GL_APICALL void GL_APIENTRY glUniform1i (GLintUniformLocation location, GLint x); diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index 5d9a818..47c2b68 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -7095,6 +7095,53 @@ static_assert(offsetof(TexSubImage3D, pixels_shm_offset) == 48, static_assert(offsetof(TexSubImage3D, internal) == 52, "offset of TexSubImage3D internal should be 52"); +struct TransformFeedbackVaryingsBucket { + typedef TransformFeedbackVaryingsBucket ValueType; + static const CommandId kCmdId = kTransformFeedbackVaryingsBucket; + 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(GLuint _program, uint32_t _varyings_bucket_id, GLenum _buffermode) { + SetHeader(); + program = _program; + varyings_bucket_id = _varyings_bucket_id; + buffermode = _buffermode; + } + + void* Set(void* cmd, + GLuint _program, + uint32_t _varyings_bucket_id, + GLenum _buffermode) { + static_cast<ValueType*>(cmd) + ->Init(_program, _varyings_bucket_id, _buffermode); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t program; + uint32_t varyings_bucket_id; + uint32_t buffermode; +}; + +static_assert(sizeof(TransformFeedbackVaryingsBucket) == 16, + "size of TransformFeedbackVaryingsBucket should be 16"); +static_assert(offsetof(TransformFeedbackVaryingsBucket, header) == 0, + "offset of TransformFeedbackVaryingsBucket header should be 0"); +static_assert(offsetof(TransformFeedbackVaryingsBucket, program) == 4, + "offset of TransformFeedbackVaryingsBucket program should be 4"); +static_assert( + offsetof(TransformFeedbackVaryingsBucket, varyings_bucket_id) == 8, + "offset of TransformFeedbackVaryingsBucket varyings_bucket_id should be 8"); +static_assert( + offsetof(TransformFeedbackVaryingsBucket, buffermode) == 12, + "offset of TransformFeedbackVaryingsBucket buffermode should be 12"); + struct Uniform1f { typedef Uniform1f ValueType; static const CommandId kCmdId = kUniform1f; 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 67f6dd8..804bebc 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -2209,6 +2209,21 @@ TEST_F(GLES2FormatTest, TexSubImage3D) { CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, TransformFeedbackVaryingsBucket) { + cmds::TransformFeedbackVaryingsBucket& cmd = + *GetBufferAs<cmds::TransformFeedbackVaryingsBucket>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11), + static_cast<uint32_t>(12), static_cast<GLenum>(13)); + EXPECT_EQ( + static_cast<uint32_t>(cmds::TransformFeedbackVaryingsBucket::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.program); + EXPECT_EQ(static_cast<uint32_t>(12), cmd.varyings_bucket_id); + EXPECT_EQ(static_cast<GLenum>(13), cmd.buffermode); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, Uniform1f) { cmds::Uniform1f& cmd = *GetBufferAs<cmds::Uniform1f>(); void* next_cmd = diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 2a9a0fe..df996d8 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -161,120 +161,121 @@ OP(TexStorage3D) /* 402 */ \ OP(TexSubImage2D) /* 403 */ \ OP(TexSubImage3D) /* 404 */ \ - OP(Uniform1f) /* 405 */ \ - OP(Uniform1fvImmediate) /* 406 */ \ - OP(Uniform1i) /* 407 */ \ - OP(Uniform1ivImmediate) /* 408 */ \ - OP(Uniform1ui) /* 409 */ \ - OP(Uniform1uivImmediate) /* 410 */ \ - OP(Uniform2f) /* 411 */ \ - OP(Uniform2fvImmediate) /* 412 */ \ - OP(Uniform2i) /* 413 */ \ - OP(Uniform2ivImmediate) /* 414 */ \ - OP(Uniform2ui) /* 415 */ \ - OP(Uniform2uivImmediate) /* 416 */ \ - OP(Uniform3f) /* 417 */ \ - OP(Uniform3fvImmediate) /* 418 */ \ - OP(Uniform3i) /* 419 */ \ - OP(Uniform3ivImmediate) /* 420 */ \ - OP(Uniform3ui) /* 421 */ \ - OP(Uniform3uivImmediate) /* 422 */ \ - OP(Uniform4f) /* 423 */ \ - OP(Uniform4fvImmediate) /* 424 */ \ - OP(Uniform4i) /* 425 */ \ - OP(Uniform4ivImmediate) /* 426 */ \ - OP(Uniform4ui) /* 427 */ \ - OP(Uniform4uivImmediate) /* 428 */ \ - OP(UniformMatrix2fvImmediate) /* 429 */ \ - OP(UniformMatrix2x3fvImmediate) /* 430 */ \ - OP(UniformMatrix2x4fvImmediate) /* 431 */ \ - OP(UniformMatrix3fvImmediate) /* 432 */ \ - OP(UniformMatrix3x2fvImmediate) /* 433 */ \ - OP(UniformMatrix3x4fvImmediate) /* 434 */ \ - OP(UniformMatrix4fvImmediate) /* 435 */ \ - OP(UniformMatrix4x2fvImmediate) /* 436 */ \ - OP(UniformMatrix4x3fvImmediate) /* 437 */ \ - OP(UseProgram) /* 438 */ \ - OP(ValidateProgram) /* 439 */ \ - OP(VertexAttrib1f) /* 440 */ \ - OP(VertexAttrib1fvImmediate) /* 441 */ \ - OP(VertexAttrib2f) /* 442 */ \ - OP(VertexAttrib2fvImmediate) /* 443 */ \ - OP(VertexAttrib3f) /* 444 */ \ - OP(VertexAttrib3fvImmediate) /* 445 */ \ - OP(VertexAttrib4f) /* 446 */ \ - OP(VertexAttrib4fvImmediate) /* 447 */ \ - OP(VertexAttribI4i) /* 448 */ \ - OP(VertexAttribI4ivImmediate) /* 449 */ \ - OP(VertexAttribI4ui) /* 450 */ \ - OP(VertexAttribI4uivImmediate) /* 451 */ \ - OP(VertexAttribIPointer) /* 452 */ \ - OP(VertexAttribPointer) /* 453 */ \ - OP(Viewport) /* 454 */ \ - OP(BlitFramebufferCHROMIUM) /* 455 */ \ - OP(RenderbufferStorageMultisampleCHROMIUM) /* 456 */ \ - OP(RenderbufferStorageMultisampleEXT) /* 457 */ \ - OP(FramebufferTexture2DMultisampleEXT) /* 458 */ \ - OP(TexStorage2DEXT) /* 459 */ \ - OP(GenQueriesEXTImmediate) /* 460 */ \ - OP(DeleteQueriesEXTImmediate) /* 461 */ \ - OP(BeginQueryEXT) /* 462 */ \ - OP(BeginTransformFeedback) /* 463 */ \ - OP(EndQueryEXT) /* 464 */ \ - OP(EndTransformFeedback) /* 465 */ \ - OP(InsertEventMarkerEXT) /* 466 */ \ - OP(PushGroupMarkerEXT) /* 467 */ \ - OP(PopGroupMarkerEXT) /* 468 */ \ - OP(GenVertexArraysOESImmediate) /* 469 */ \ - OP(DeleteVertexArraysOESImmediate) /* 470 */ \ - OP(IsVertexArrayOES) /* 471 */ \ - OP(BindVertexArrayOES) /* 472 */ \ - OP(SwapBuffers) /* 473 */ \ - OP(GetMaxValueInBufferCHROMIUM) /* 474 */ \ - OP(EnableFeatureCHROMIUM) /* 475 */ \ - OP(ResizeCHROMIUM) /* 476 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 477 */ \ - OP(RequestExtensionCHROMIUM) /* 478 */ \ - OP(GetProgramInfoCHROMIUM) /* 479 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 480 */ \ - OP(PostSubBufferCHROMIUM) /* 481 */ \ - OP(TexImageIOSurface2DCHROMIUM) /* 482 */ \ - OP(CopyTextureCHROMIUM) /* 483 */ \ - OP(DrawArraysInstancedANGLE) /* 484 */ \ - OP(DrawElementsInstancedANGLE) /* 485 */ \ - OP(VertexAttribDivisorANGLE) /* 486 */ \ - OP(GenMailboxCHROMIUM) /* 487 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 488 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 489 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 490 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 491 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 492 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 493 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 494 */ \ - OP(IsValuebufferCHROMIUM) /* 495 */ \ - OP(BindValuebufferCHROMIUM) /* 496 */ \ - OP(SubscribeValueCHROMIUM) /* 497 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 498 */ \ - OP(UniformValuebufferCHROMIUM) /* 499 */ \ - OP(BindTexImage2DCHROMIUM) /* 500 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 501 */ \ - OP(TraceBeginCHROMIUM) /* 502 */ \ - OP(TraceEndCHROMIUM) /* 503 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 504 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 505 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 506 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 507 */ \ - OP(DiscardFramebufferEXTImmediate) /* 508 */ \ - OP(LoseContextCHROMIUM) /* 509 */ \ - OP(InsertSyncPointCHROMIUM) /* 510 */ \ - OP(WaitSyncPointCHROMIUM) /* 511 */ \ - OP(DrawBuffersEXTImmediate) /* 512 */ \ - OP(DiscardBackbufferCHROMIUM) /* 513 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 514 */ \ - OP(SwapInterval) /* 515 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 516 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 517 */ \ - OP(BlendBarrierKHR) /* 518 */ + OP(TransformFeedbackVaryingsBucket) /* 405 */ \ + OP(Uniform1f) /* 406 */ \ + OP(Uniform1fvImmediate) /* 407 */ \ + OP(Uniform1i) /* 408 */ \ + OP(Uniform1ivImmediate) /* 409 */ \ + OP(Uniform1ui) /* 410 */ \ + OP(Uniform1uivImmediate) /* 411 */ \ + OP(Uniform2f) /* 412 */ \ + OP(Uniform2fvImmediate) /* 413 */ \ + OP(Uniform2i) /* 414 */ \ + OP(Uniform2ivImmediate) /* 415 */ \ + OP(Uniform2ui) /* 416 */ \ + OP(Uniform2uivImmediate) /* 417 */ \ + OP(Uniform3f) /* 418 */ \ + OP(Uniform3fvImmediate) /* 419 */ \ + OP(Uniform3i) /* 420 */ \ + OP(Uniform3ivImmediate) /* 421 */ \ + OP(Uniform3ui) /* 422 */ \ + OP(Uniform3uivImmediate) /* 423 */ \ + OP(Uniform4f) /* 424 */ \ + OP(Uniform4fvImmediate) /* 425 */ \ + OP(Uniform4i) /* 426 */ \ + OP(Uniform4ivImmediate) /* 427 */ \ + OP(Uniform4ui) /* 428 */ \ + OP(Uniform4uivImmediate) /* 429 */ \ + OP(UniformMatrix2fvImmediate) /* 430 */ \ + OP(UniformMatrix2x3fvImmediate) /* 431 */ \ + OP(UniformMatrix2x4fvImmediate) /* 432 */ \ + OP(UniformMatrix3fvImmediate) /* 433 */ \ + OP(UniformMatrix3x2fvImmediate) /* 434 */ \ + OP(UniformMatrix3x4fvImmediate) /* 435 */ \ + OP(UniformMatrix4fvImmediate) /* 436 */ \ + OP(UniformMatrix4x2fvImmediate) /* 437 */ \ + OP(UniformMatrix4x3fvImmediate) /* 438 */ \ + OP(UseProgram) /* 439 */ \ + OP(ValidateProgram) /* 440 */ \ + OP(VertexAttrib1f) /* 441 */ \ + OP(VertexAttrib1fvImmediate) /* 442 */ \ + OP(VertexAttrib2f) /* 443 */ \ + OP(VertexAttrib2fvImmediate) /* 444 */ \ + OP(VertexAttrib3f) /* 445 */ \ + OP(VertexAttrib3fvImmediate) /* 446 */ \ + OP(VertexAttrib4f) /* 447 */ \ + OP(VertexAttrib4fvImmediate) /* 448 */ \ + OP(VertexAttribI4i) /* 449 */ \ + OP(VertexAttribI4ivImmediate) /* 450 */ \ + OP(VertexAttribI4ui) /* 451 */ \ + OP(VertexAttribI4uivImmediate) /* 452 */ \ + OP(VertexAttribIPointer) /* 453 */ \ + OP(VertexAttribPointer) /* 454 */ \ + OP(Viewport) /* 455 */ \ + OP(BlitFramebufferCHROMIUM) /* 456 */ \ + OP(RenderbufferStorageMultisampleCHROMIUM) /* 457 */ \ + OP(RenderbufferStorageMultisampleEXT) /* 458 */ \ + OP(FramebufferTexture2DMultisampleEXT) /* 459 */ \ + OP(TexStorage2DEXT) /* 460 */ \ + OP(GenQueriesEXTImmediate) /* 461 */ \ + OP(DeleteQueriesEXTImmediate) /* 462 */ \ + OP(BeginQueryEXT) /* 463 */ \ + OP(BeginTransformFeedback) /* 464 */ \ + OP(EndQueryEXT) /* 465 */ \ + OP(EndTransformFeedback) /* 466 */ \ + OP(InsertEventMarkerEXT) /* 467 */ \ + OP(PushGroupMarkerEXT) /* 468 */ \ + OP(PopGroupMarkerEXT) /* 469 */ \ + OP(GenVertexArraysOESImmediate) /* 470 */ \ + OP(DeleteVertexArraysOESImmediate) /* 471 */ \ + OP(IsVertexArrayOES) /* 472 */ \ + OP(BindVertexArrayOES) /* 473 */ \ + OP(SwapBuffers) /* 474 */ \ + OP(GetMaxValueInBufferCHROMIUM) /* 475 */ \ + OP(EnableFeatureCHROMIUM) /* 476 */ \ + OP(ResizeCHROMIUM) /* 477 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 478 */ \ + OP(RequestExtensionCHROMIUM) /* 479 */ \ + OP(GetProgramInfoCHROMIUM) /* 480 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 481 */ \ + OP(PostSubBufferCHROMIUM) /* 482 */ \ + OP(TexImageIOSurface2DCHROMIUM) /* 483 */ \ + OP(CopyTextureCHROMIUM) /* 484 */ \ + OP(DrawArraysInstancedANGLE) /* 485 */ \ + OP(DrawElementsInstancedANGLE) /* 486 */ \ + OP(VertexAttribDivisorANGLE) /* 487 */ \ + OP(GenMailboxCHROMIUM) /* 488 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 489 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 490 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 491 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 492 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 493 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 494 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 495 */ \ + OP(IsValuebufferCHROMIUM) /* 496 */ \ + OP(BindValuebufferCHROMIUM) /* 497 */ \ + OP(SubscribeValueCHROMIUM) /* 498 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 499 */ \ + OP(UniformValuebufferCHROMIUM) /* 500 */ \ + OP(BindTexImage2DCHROMIUM) /* 501 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 502 */ \ + OP(TraceBeginCHROMIUM) /* 503 */ \ + OP(TraceEndCHROMIUM) /* 504 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 505 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 506 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 507 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 508 */ \ + OP(DiscardFramebufferEXTImmediate) /* 509 */ \ + OP(LoseContextCHROMIUM) /* 510 */ \ + OP(InsertSyncPointCHROMIUM) /* 511 */ \ + OP(WaitSyncPointCHROMIUM) /* 512 */ \ + OP(DrawBuffersEXTImmediate) /* 513 */ \ + OP(DiscardBackbufferCHROMIUM) /* 514 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 515 */ \ + OP(SwapInterval) /* 516 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 517 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 518 */ \ + OP(BlendBarrierKHR) /* 519 */ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index 02e4440..a2f4ca7 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h @@ -14,6 +14,7 @@ static std::string GetStringAttachment(uint32_t value); static std::string GetStringBackbufferAttachment(uint32_t value); static std::string GetStringBlitFilter(uint32_t value); +static std::string GetStringBufferMode(uint32_t value); static std::string GetStringBufferParameter(uint32_t value); static std::string GetStringBufferTarget(uint32_t value); static std::string GetStringBufferUsage(uint32_t value); diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 393ee43..db3a6c4 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -4475,6 +4475,15 @@ std::string GLES2Util::GetStringBlitFilter(uint32_t value) { arraysize(string_table), value); } +std::string GLES2Util::GetStringBufferMode(uint32_t value) { + static const EnumToString string_table[] = { + {GL_INTERLEAVED_ATTRIBS, "GL_INTERLEAVED_ATTRIBS"}, + {GL_SEPARATE_ATTRIBS, "GL_SEPARATE_ATTRIBS"}, + }; + return GLES2Util::GetQualifiedEnumString(string_table, + arraysize(string_table), value); +} + std::string GLES2Util::GetStringBufferParameter(uint32_t value) { static const EnumToString string_table[] = { {GL_BUFFER_SIZE, "GL_BUFFER_SIZE"}, {GL_BUFFER_USAGE, "GL_BUFFER_USAGE"}, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 645522a..f37c61a 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1178,6 +1178,11 @@ class GLES2DecoderImpl : public GLES2Decoder, void DoShaderSource( GLuint client_id, GLsizei count, const char** data, const GLint* length); + // Wrapper for glTransformFeedbackVaryings. + void DoTransformFeedbackVaryings( + GLuint client_program_id, GLsizei count, const char* const* varyings, + GLenum buffer_mode); + // Clear any textures used by the current program. bool ClearUnclearedTextures(); @@ -7057,6 +7062,18 @@ void GLES2DecoderImpl::DoShaderSource( shader->set_source(str); } +void GLES2DecoderImpl::DoTransformFeedbackVaryings( + GLuint client_program_id, GLsizei count, const char* const* varyings, + GLenum buffer_mode) { + Program* program = GetProgramInfoNotShader( + client_program_id, "glTransformFeedbackVaryings"); + if (!program) { + return; + } + glTransformFeedbackVaryings( + program->service_id(), count, varyings, buffer_mode); +} + void GLES2DecoderImpl::DoCompileShader(GLuint client_id) { TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader"); Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader"); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 86a9c52..720d54e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2806,6 +2806,64 @@ error::Error GLES2DecoderImpl::HandleTexStorage3D(uint32_t immediate_data_size, return error::kNoError; } +error::Error GLES2DecoderImpl::HandleTransformFeedbackVaryingsBucket( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::TransformFeedbackVaryingsBucket& c = + *static_cast<const gles2::cmds::TransformFeedbackVaryingsBucket*>( + cmd_data); + (void)c; + GLuint program = static_cast<GLuint>(c.program); + + const size_t kMinBucketSize = sizeof(GLint); + // Each string has at least |length| in the header and a NUL character. + const size_t kMinStringSize = sizeof(GLint) + 1; + Bucket* bucket = GetBucket(c.varyings_bucket_id); + if (!bucket) { + return error::kInvalidArguments; + } + const size_t bucket_size = bucket->size(); + if (bucket_size < kMinBucketSize) { + return error::kInvalidArguments; + } + const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size); + const GLint* header = reinterpret_cast<const GLint*>(bucket_data); + GLsizei count = static_cast<GLsizei>(header[0]); + if (count < 0) { + return error::kInvalidArguments; + } + const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize; + if (max_count < static_cast<size_t>(count)) { + return error::kInvalidArguments; + } + const GLint* length = header + 1; + scoped_ptr<const char* []> strs; + if (count > 0) + strs.reset(new const char* [count]); + const char** varyings = strs.get(); + base::CheckedNumeric<size_t> total_size = sizeof(GLint); + total_size *= count + 1; // Header size. + if (!total_size.IsValid()) + return error::kInvalidArguments; + for (GLsizei ii = 0; ii < count; ++ii) { + varyings[ii] = bucket_data + total_size.ValueOrDefault(0); + total_size += length[ii]; + total_size += 1; // NUL char at the end of each char array. + if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size || + varyings[ii][length[ii]] != 0) { + return error::kInvalidArguments; + } + } + if (total_size.ValueOrDefault(0) != bucket_size) { + return error::kInvalidArguments; + } + GLenum buffermode = static_cast<GLenum>(c.buffermode); + DoTransformFeedbackVaryings(program, count, varyings, buffermode); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleUniform1f(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::Uniform1f& c = diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 50db95c..2947723 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -580,20 +580,15 @@ TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidHeader) { const char kValidStrEnd = 0; const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource)); const GLsizei kTests[] = { - kCount, 0, std::numeric_limits<GLsizei>::max(), -1, kCount, + kCount + 1, 0, std::numeric_limits<GLsizei>::max(), -1, }; decoder_->set_unsafe_es3_apis_enabled(true); for (size_t ii = 0; ii < arraysize(kTests); ++ii) { SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd); cmds::ShaderSourceBucket cmd; cmd.Init(client_shader_id_, kBucketId); - if (kTests[ii] == kCount) { - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } else { - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - } + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); } - EXPECT_EQ(GL_NO_ERROR, GetGLError()); } TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidStringEnding) { @@ -606,7 +601,6 @@ TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidStringEnding) { cmd.Init(client_shader_id_, kBucketId); decoder_->set_unsafe_es3_apis_enabled(true); EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); } TEST_P(GLES2DecoderTest2, StencilFuncValidArgs) { @@ -874,6 +868,69 @@ TEST_P(GLES2DecoderTest2, TexStorage3DValidArgs) { // TODO(gman): TexSubImage3D +TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketValidArgs) { + EXPECT_CALL(*gl_, TransformFeedbackVaryings(kServiceProgramId, 1, _, + GL_INTERLEAVED_ATTRIBS)); + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kValidStrEnd = 0; + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); + cmds::TransformFeedbackVaryingsBucket cmd; + cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketInvalidArgs) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kValidStrEnd = 0; + decoder_->set_unsafe_es3_apis_enabled(true); + cmds::TransformFeedbackVaryingsBucket cmd; + // Test no bucket. + cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + // Test invalid client. + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); + cmd.Init(kInvalidClientId, kBucketId, GL_INTERLEAVED_ATTRIBS); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketInvalidHeader) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kValidStrEnd = 0; + const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource)); + const GLsizei kTests[] = { + kCount + 1, 0, std::numeric_limits<GLsizei>::max(), -1, + }; + decoder_->set_unsafe_es3_apis_enabled(true); + for (size_t ii = 0; ii < arraysize(kTests); ++ii) { + SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd); + cmds::TransformFeedbackVaryingsBucket cmd; + cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + } +} + +TEST_P(GLES2DecoderTest2, TransformFeedbackVaryingsBucketInvalidStringEnding) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kInvalidStrEnd = '*'; + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd); + cmds::TransformFeedbackVaryingsBucket cmd; + cmd.Init(client_program_id_, kBucketId, GL_INTERLEAVED_ATTRIBS); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); +} + TEST_P(GLES2DecoderTest2, Uniform1fValidArgs) { EXPECT_CALL(*gl_, Uniform1fv(1, 1, _)); SpecializedSetup<cmds::Uniform1f, 0>(true); @@ -1469,21 +1526,4 @@ TEST_P(GLES2DecoderTest2, VertexAttribI4uiValidArgs) { decoder_->set_unsafe_es3_apis_enabled(false); EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); } - -TEST_P(GLES2DecoderTest2, VertexAttribI4uivImmediateValidArgs) { - cmds::VertexAttribI4uivImmediate& cmd = - *GetImmediateAs<cmds::VertexAttribI4uivImmediate>(); - SpecializedSetup<cmds::VertexAttribI4uivImmediate, 0>(true); - GLuint temp[4] = { - 0, - }; - cmd.Init(1, &temp[0]); - EXPECT_CALL(*gl_, VertexAttribI4uiv(1, reinterpret_cast<GLuint*>( - ImmediateDataAddress(&cmd)))); - decoder_->set_unsafe_es3_apis_enabled(true); - EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - decoder_->set_unsafe_es3_apis_enabled(false); - EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); -} #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index be13c7c..2eb4e58 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -12,6 +12,22 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ +TEST_P(GLES2DecoderTest3, VertexAttribI4uivImmediateValidArgs) { + cmds::VertexAttribI4uivImmediate& cmd = + *GetImmediateAs<cmds::VertexAttribI4uivImmediate>(); + SpecializedSetup<cmds::VertexAttribI4uivImmediate, 0>(true); + GLuint temp[4] = { + 0, + }; + cmd.Init(1, &temp[0]); + EXPECT_CALL(*gl_, VertexAttribI4uiv(1, reinterpret_cast<GLuint*>( + ImmediateDataAddress(&cmd)))); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); +} // TODO(gman): VertexAttribIPointer // TODO(gman): VertexAttribPointer diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index e163642..6c9d377 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -14,6 +14,7 @@ ValueValidator<GLenum> attachment; ValueValidator<GLenum> backbuffer_attachment; ValueValidator<GLenum> blit_filter; +ValueValidator<GLenum> buffer_mode; ValueValidator<GLenum> buffer_parameter; ValueValidator<GLenum> buffer_target; ValueValidator<GLenum> buffer_usage; diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index febce20..1f1211b 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -28,6 +28,11 @@ static const GLenum valid_blit_filter_table[] = { GL_LINEAR, }; +static const GLenum valid_buffer_mode_table[] = { + GL_INTERLEAVED_ATTRIBS, + GL_SEPARATE_ATTRIBS, +}; + static const GLenum valid_buffer_parameter_table[] = { GL_BUFFER_SIZE, GL_BUFFER_USAGE, @@ -585,6 +590,7 @@ Validators::Validators() backbuffer_attachment(valid_backbuffer_attachment_table, arraysize(valid_backbuffer_attachment_table)), blit_filter(valid_blit_filter_table, arraysize(valid_blit_filter_table)), + buffer_mode(valid_buffer_mode_table, arraysize(valid_buffer_mode_table)), buffer_parameter(valid_buffer_parameter_table, arraysize(valid_buffer_parameter_table)), buffer_target(valid_buffer_target_table, |