summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorzmo <zmo@chromium.org>2015-01-29 12:17:39 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-29 20:18:42 +0000
commit38923567f136fb3dda353b84700cd47ac0077fbd (patch)
tree3984643b5eba34d765b6fd1364cf22919d6e5bbe /gpu
parent836b0aaeae4a2984c9f0c10c69fbe9627b15a542 (diff)
downloadchromium_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')
-rw-r--r--gpu/GLES2/gl2chromium_autogen.h1
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py111
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h11
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h10
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h5
-rw-r--r--gpu/command_buffer/client/gles2_implementation_impl_autogen.h94
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest_autogen.h52
-rw-r--r--gpu/command_buffer/client/gles2_interface_autogen.h4
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_autogen.h4
-rw-r--r--gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h6
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_autogen.h4
-rw-r--r--gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h9
-rw-r--r--gpu/command_buffer/cmd_buffer_functions.txt1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h47
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h15
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h229
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_autogen.h1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h9
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc17
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h58
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h90
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h16
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_autogen.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h6
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,