diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 02:46:30 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 02:46:30 +0000 |
commit | 07f54fcc277a2d8fc3e6cecc5df5ea5c3d5ed080 (patch) | |
tree | 5495bf94c1fbeb71d321d0933b36910311fd1d93 /gpu | |
parent | bd04c9889d9607a69cf696fc5136dab6d6c83dec (diff) | |
download | chromium_src-07f54fcc277a2d8fc3e6cecc5df5ea5c3d5ed080.zip chromium_src-07f54fcc277a2d8fc3e6cecc5df5ea5c3d5ed080.tar.gz chromium_src-07f54fcc277a2d8fc3e6cecc5df5ea5c3d5ed080.tar.bz2 |
Add Immediate command data size validation.
Adds checks that Immediate commands all
check the sizeo of the data they are going
to access is valid.
Also adds Vertex Attribute validation for
glDrawXXX. In order to accomplish this
it must track buffers and their sizes,
the settings set with glVertexAttribPointer,
program info at glLinkProgram time and which
program as active via glUseProgram
Given all that info it can validate that is
is okay to call glDrawArray or glDrawElements.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/501097
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35135 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 179 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 648 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h | 610 |
3 files changed, 895 insertions, 542 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index b5bed72..d7878de 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -663,10 +663,13 @@ _FUNCTION_INFO = { 'DeleteShader': {'type': 'Custom', 'DecoderFunc': 'DoDeleteShader'}, 'DeleteTextures': {'type': 'DELn'}, 'DepthRangef': {'DecoderFunc': 'glDepthRange'}, + 'DisableVertexAttribArray': {'DecoderFunc': 'DoDisableVertexAttribArray'}, + 'DrawArrays': { 'DecoderFunc': 'DoDrawArrays'}, 'DrawElements': { 'type': 'Manual', 'cmd_args': 'GLenum mode, GLsizei count, GLenum type, GLuint index_offset', }, + 'EnableVertexAttribArray': {'DecoderFunc': 'DoEnableVertexAttribArray'}, 'FramebufferRenderbuffer': {'DecoderFunc': 'glFramebufferRenderbufferEXT'}, 'FramebufferTexture2D': {'DecoderFunc': 'glFramebufferTexture2DEXT'}, 'GenerateMipmap': {'DecoderFunc': 'glGenerateMipmapEXT'}, @@ -724,6 +727,7 @@ _FUNCTION_INFO = { 'IsRenderbuffer': {'type': 'Is', 'DecoderFunc': 'glIsRenderbufferEXT'}, 'IsShader': {'type': 'Is'}, 'IsTexture': {'type': 'Is'}, + 'LinkProgram': {'DecoderFunc': 'DoLinkProgram'}, 'PixelStorei': {'type': 'Manual'}, 'RenderbufferStorage': {'DecoderFunc': 'glRenderbufferStorageEXT'}, 'ReadPixels': {'type': 'Custom', 'immediate': False}, @@ -751,6 +755,7 @@ _FUNCTION_INFO = { 'UniformMatrix2fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 4}, 'UniformMatrix3fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 9}, 'UniformMatrix4fv': {'type': 'PUTn', 'data_type': 'GLfloat', 'count': 16}, + 'UseProgram': {'DecoderFunc': 'DoUseProgram'}, 'VertexAttrib1fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 1}, 'VertexAttrib2fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 2}, 'VertexAttrib3fv': {'type': 'PUT', 'data_type': 'GLfloat', 'count': 3}, @@ -941,6 +946,10 @@ class TypeHandler(object): file.Write("}\n") file.Write("\n") + def WriteGetDataSizeCode(self, func, file): + """Writes the code to set data_size used in validation""" + pass + def WriteImmediateCmdSizeTest(self, func, file): """Writes a size test for an immediate version of a command.""" file.Write(" // TODO(gman): Compute correct size.\n") @@ -948,8 +957,6 @@ class TypeHandler(object): def WriteImmediateHandlerImplementation (self, func, file): """Writes the handler impl for the immediate version of a command.""" - file.Write(" // Immediate version.\n") - func.WriteHandlerValidation(file) file.Write(" %s(%s);\n" % (func.GetGLFunctionName(), func.MakeOriginalArgString(""))) @@ -959,8 +966,13 @@ class TypeHandler(object): "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name) file.Write( " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) - for arg in func.GetOriginalArgs(): - arg.WriteGetCode(file) + if len(func.GetOriginalArgs()) > 0: + last_arg = func.GetLastOriginalArg() + all_but_last_arg = func.GetOriginalArgs()[:-1] + for arg in all_but_last_arg: + arg.WriteGetCode(file) + self.WriteGetDataSizeCode(func, file) + last_arg.WriteGetCode(file) func.WriteHandlerValidation(file) func.WriteHandlerImplementation(file) file.Write(" return parse_error::kParseNoError;\n") @@ -973,8 +985,12 @@ class TypeHandler(object): "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name) file.Write( " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) - for arg in func.GetOriginalArgs(): + last_arg = func.GetLastOriginalArg() + all_but_last_arg = func.GetOriginalArgs()[:-1] + for arg in all_but_last_arg: arg.WriteGetCode(file) + self.WriteGetDataSizeCode(func, file) + last_arg.WriteGetCode(file) func.WriteHandlerValidation(file) func.WriteHandlerImplementation(file) file.Write(" return parse_error::kParseNoError;\n") @@ -1199,46 +1215,34 @@ class ManualHandler(CustomHandler): CustomHandler.WriteImmediateCmdGetTotalSize(self, func, file) -class DataHandler(CustomHandler): +class DataHandler(TypeHandler): """Handler for glBufferData, glBufferSubData, glTexImage2D, glTexSubImage2D, glCompressedTexImage2D, glCompressedTexImageSub2D.""" def __init__(self): - CustomHandler.__init__(self) + TypeHandler.__init__(self) - def WriteServiceImplementation(self, func, file): + def WriteGetDataSizeCode(self, func, file): """Overrriden from TypeHandler.""" - file.Write( - "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name) - file.Write( - " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) - for arg in func.GetCmdArgs(): - arg.WriteGetCode(file) - # TODO(gman): Move this data to _FUNCTION_INFO? - if func.name == 'BufferData': + name = func.name + if name.endswith("Immediate"): + name = name[0:-9] + if name == 'BufferData': file.Write(" uint32 data_size = size;\n") - elif func.name == 'BufferSubData': + elif name == 'BufferSubData': file.Write(" uint32 data_size = size;\n") - elif func.name == 'CompressedTexImage2D': + elif name == 'CompressedTexImage2D': file.Write(" uint32 data_size = imageSize;\n") - elif func.name == 'CompressedTexSubImage2D': + elif name == 'CompressedTexSubImage2D': file.Write(" uint32 data_size = imageSize;\n") - elif func.name == 'TexImage2D': - file.Write(" uint32 pixels_size = GLES2Util::ComputeImageDataSize(\n") + elif name == 'TexImage2D': + file.Write(" uint32 data_size = GLES2Util::ComputeImageDataSize(\n") file.Write(" width, height, format, type, unpack_alignment_);\n") - elif func.name == 'TexSubImage2D': - file.Write(" uint32 pixels_size = GLES2Util::ComputeImageDataSize(\n") + elif name == 'TexSubImage2D': + file.Write(" uint32 data_size = GLES2Util::ComputeImageDataSize(\n") file.Write(" width, height, format, type, unpack_alignment_);\n") else: - file.Write(" uint32 data_size = 0; // TODO(gman): get correct size!\n") - - for arg in func.GetOriginalArgs(): - arg.WriteGetAddress(file) - func.WriteHandlerValidation(file) - func.WriteHandlerImplementation(file) - file.Write(" return parse_error::kParseNoError;\n") - file.Write("}\n") - file.Write("\n") + file.Write("// uint32 data_size = 0; // TODO(gman): get correct size!\n") def WriteImmediateCmdGetTotalSize(self, func, file): """Overrriden from TypeHandler.""" @@ -1277,6 +1281,29 @@ class DataHandler(CustomHandler): " uint32 total_size = 0; // TODO(gman): get correct size\n") file.Write(" EXPECT_EQ(sizeof(cmd), total_size);\n") + def WriteImmediateCmdInit(self, func, file): + """Overrriden from TypeHandler.""" + file.Write(" void Init(%s) {\n" % func.MakeTypedCmdArgString("_")) + self.WriteImmediateCmdGetTotalSize(func, file) + file.Write(" SetHeader(total_size);\n") + args = func.GetCmdArgs() + for arg in args: + file.Write(" %s = _%s;\n" % (arg.name, arg.name)) + file.Write(" }\n") + file.Write("\n") + + def WriteImmediateCmdSet(self, func, file): + """Overrriden from TypeHandler.""" + copy_args = func.MakeCmdArgString("_", False) + file.Write(" void* Set(void* cmd%s) {\n" % + func.MakeTypedCmdArgString("_", True)) + self.WriteImmediateCmdGetTotalSize(func, file) + file.Write(" static_cast<ValueType*>(cmd)->Init(%s);\n" % copy_args) + file.Write(" return NextImmediateCmdAddressTotalSize<ValueType>(" + "cmd, total_size);\n") + file.Write(" }\n") + file.Write("\n") + def WriteImmediateFormatTest(self, func, file): """Overrriden from TypeHandler.""" # TODO(gman): Remove this exception. @@ -1298,15 +1325,17 @@ class GENnHandler(TypeHandler): """Overrriden from TypeHandler.""" pass + def WriteGetDataSizeCode(self, func, file): + """Overrriden from TypeHandler.""" + file.Write(" uint32 data_size = n * sizeof(GLuint);\n") + def WriteHandlerImplementation (self, func, file): """Overrriden from TypeHandler.""" - func.WriteHandlerValidation(file) file.Write(" GenGLObjects<GL%sHelper>(n, %s);\n" % (func.name, func.GetLastOriginalArg().name)) def WriteImmediateHandlerImplementation(self, func, file): """Overrriden from TypeHandler.""" - func.WriteHandlerValidation(file) file.Write(" GenGLObjects<GL%sHelper>(n, %s);\n" % (func.original_name, func.GetLastOriginalArg().name)) @@ -1435,7 +1464,6 @@ class CreateHandler(TypeHandler): def WriteHandlerImplementation (self, func, file): """Overrriden from TypeHandler.""" file.Write(" uint32 client_id = c.client_id;\n") - func.WriteHandlerValidation(file) file.Write(" %sHelper(%s);\n" % (func.name, func.MakeCmdArgString(""))) @@ -1463,15 +1491,17 @@ class DELnHandler(TypeHandler): def __init__(self): TypeHandler.__init__(self) + def WriteGetDataSizeCode(self, func, file): + """Overrriden from TypeHandler.""" + file.Write(" uint32 data_size = n * sizeof(GLuint);\n") + def WriteHandlerImplementation (self, func, file): """Overrriden from TypeHandler.""" - func.WriteHandlerValidation(file) file.Write(" DeleteGLObjects<GL%sHelper>(n, %s);\n" % (func.name, func.GetLastOriginalArg().name)) def WriteImmediateHandlerImplementation (self, func, file): """Overrriden from TypeHandler.""" - func.WriteHandlerValidation(file) file.Write(" DeleteGLObjects<GL%sHelper>(n, %s);\n" % (func.original_name, func.GetLastOriginalArg().name)) @@ -1650,13 +1680,11 @@ class PUTHandler(TypeHandler): def __init__(self): TypeHandler.__init__(self) - def WriteImmediateValidationCode(self, func, file): + def WriteGetDataSizeCode(self, func, file): """Overrriden from TypeHandler.""" - file.Write(" if (!CheckImmediateDataSize<%s>(" - "immediate_data_size, 1, sizeof(%s), %d)) {\n" % - (func.name, func.info.data_type, func.info.count)) - file.Write(" return parse_error::kParseOutOfBounds;\n") - file.Write(" }\n") + file.Write(" uint32 data_size = ComputeImmediateDataSize(" + "immediate_data_size, 1, sizeof(%s), %d);\n" % + (func.info.data_type, func.info.count)) def WriteGLES2ImplementationHeader(self, func, file): """Overrriden from TypeHandler.""" @@ -1783,13 +1811,11 @@ class PUTnHandler(TypeHandler): def __init__(self): TypeHandler.__init__(self) - def WriteImmediateValidationCode(self, func, file): + def WriteGetDataSizeCode(self, func, file): """Overrriden from TypeHandler.""" - file.Write(" if (!CheckImmediateDataSize<%s>(" - "immediate_data_size, count, sizeof(%s), %d)) {\n" % - (func.name, func.info.data_type, func.info.count)) - file.Write(" return parse_error::kParseOutOfBounds;\n") - file.Write(" }\n") + file.Write(" uint32 data_size = ComputeImmediateDataSize(" + "immediate_data_size, 1, sizeof(%s), %d);\n" % + (func.info.data_type, func.info.count)) def WriteGLES2ImplementationHeader(self, func, file): """Overrriden from TypeHandler.""" @@ -1960,9 +1986,8 @@ class GLcharHandler(TypeHandler): file.Write(" uint32 name_size = c.data_size;\n") file.Write( - " const char* name = GetImmediateDataAs<const char*>(c);\n") - file.Write(" // TODO(gman): Make sure validate checks\n") - file.Write(" // immediate_data_size covers data_size.\n") + " const char* name = GetImmediateDataAs<const char*>(\n") + file.Write(" c, name_size, immediate_data_size);\n") func.WriteHandlerValidation(file) arg_string = ", ".join(["%s" % arg.name for arg in all_but_last_arg]) file.Write(" String name_str(name, name_size);\n") @@ -2129,9 +2154,8 @@ class GetGLcharHandler(GLcharHandler): file.Write(" uint32 name_size = c.data_size;\n") file.Write( - " const char* name = GetImmediateDataAs<const char*>(c);\n") - file.Write(" // TODO(gman): Make sure validate checks\n") - file.Write(" // immediate_data_size covers data_size.\n") + " const char* name = GetImmediateDataAs<const char*>(\n") + file.Write(" c, name_size, immediate_data_size);\n") file.Write(" GLint* location = GetSharedMemoryAs<GLint*>(\n") file.Write( " c.location_shm_id, c.location_shm_offset, sizeof(*location));\n") @@ -2316,6 +2340,44 @@ class STRnHandler(TypeHandler): file.Write("// TODO(gman): Implement this\n") TypeHandler.WriteGLES2ImplementationHeader(self, func, file) + def WriteServiceImplementation(self, func, file): + """Overrriden from TypeHandler.""" + file.Write( + "parse_error::ParseError GLES2DecoderImpl::Handle%s(\n" % func.name) + file.Write( + " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) + args = func.GetOriginalArgs() + all_but_last_2_args = args[:-2] + for arg in all_but_last_2_args: + arg.WriteGetCode(file) + self.WriteGetDataSizeCode(func, file) + size_arg = args[-2] + file.Write(" uint32 size_shm_id = c.%s_shm_id;\n" % size_arg.name) + file.Write(" uint32 size_shm_offset = c.%s_shm_offset;\n" % size_arg.name) + file.Write(" GLsizei* length = NULL;\n") + file.Write(" if (size_shm_id != 0 || size_shm_offset != 0) {\n" + " length = GetSharedMemoryAs<GLsizei*>(\n" + " size_shm_id, size_shm_offset, sizeof(*length));\n" + " if (!length) {\n" + " return parse_error::kParseOutOfBounds;\n" + " }\n" + " }\n") + dest_arg = args[-1] + bufsize_arg = args[-3] + file.Write( + " %s %s = GetSharedMemoryAs<%s>(\n" % + (dest_arg.type, dest_arg.name, dest_arg.type)) + file.Write( + " c.%s_shm_id, c.%s_shm_offset, %s);\n" % + (dest_arg.name, dest_arg.name, bufsize_arg.name)) + for arg in all_but_last_2_args + [dest_arg]: + arg.WriteValidationCode(file) + func.WriteValidationCode(file) + func.WriteHandlerImplementation(file) + file.Write(" return parse_error::kParseNoError;\n") + file.Write("}\n") + file.Write("\n") + class FunctionInfo(object): """Holds info about a function.""" @@ -2427,8 +2489,9 @@ class ImmediatePointerArgument(Argument): def WriteGetCode(self, file): """Overridden from Argument.""" file.Write( - " %s %s = GetImmediateDataAs<%s>(c);\n" % - (self.type, self.name, self.type)) + " %s %s = GetImmediateDataAs<%s>(\n" % + (self.type, self.name, self.type)) + file.Write(" c, data_size, immediate_data_size);\n") def WriteValidationCode(self, file): """Overridden from Argument.""" @@ -2462,7 +2525,7 @@ class PointerArgument(Argument): " %s %s = GetSharedMemoryAs<%s>(\n" % (self.type, self.name, self.type)) file.Write( - " c.%s_shm_id, c.%s_shm_offset, 0 /* TODO(gman): size */);\n" % + " c.%s_shm_id, c.%s_shm_offset, data_size);\n" % (self.name, self.name)) def WriteGetAddress(self, file): diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 63e6799..f13944f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -18,28 +18,60 @@ namespace gpu { namespace gles2 { +// Check that certain assumptions the code makes are true. There are places in +// the code where shared memory is passed direclty to GL. Example, glUniformiv, +// glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe +// a few others) are 32bits. If they are not 32bits the code will have to change +// to call those GL functions with service side memory and then copy the results +// to shared memory, converting the sizes. +COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT + GLint_not_same_size_as_uint32); +COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT + GLint_not_same_size_as_uint32); + namespace { +size_t GetGLTypeSize(GLenum type) { + switch (type) { + case GL_BYTE: + return sizeof(GLbyte); // NOLINT + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); // NOLINT + case GL_SHORT: + return sizeof(GLshort); // NOLINT + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); // NOLINT + case GL_FLOAT: + return sizeof(GLfloat); // NOLINT + default: + return 0; + } +} + // Returns the address of the first byte after a struct. template <typename T> const void* AddressAfterStruct(const T& pod) { return reinterpret_cast<const uint8*>(&pod) + sizeof(pod); } -// Returns the address of the frst byte after the struct. +// Returns the address of the frst byte after the struct or NULL if size > +// immediate_data_size. template <typename RETURN_TYPE, typename COMMAND_TYPE> -RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) { - return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))); +RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod, + uint32 size, + uint32 immediate_data_size) { + return (size <= immediate_data_size) ? + static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))) : + NULL; } -// Checks if there is enough immediate data. -template<typename T> -bool CheckImmediateDataSize( +// Computes the data size for certain gl commands like glUniform. +uint32 ComputeImmediateDataSize( uint32 immediate_data_size, GLuint count, size_t size, unsigned int elements_per_unit) { - return immediate_data_size == count * size * elements_per_unit; + return count * size * elements_per_unit; } // A struct to hold info about each command. @@ -59,39 +91,6 @@ const CommandInfo g_command_info[] = { #undef GLES2_CMD_OP }; -// These commands convert from c calls to local os calls. -void GLGenBuffersHelper(GLsizei n, GLuint* ids) { - glGenBuffersARB(n, ids); -} - -void GLGenFramebuffersHelper(GLsizei n, GLuint* ids) { - glGenFramebuffersEXT(n, ids); -} - -void GLGenRenderbuffersHelper(GLsizei n, GLuint* ids) { - glGenRenderbuffersEXT(n, ids); -} - -void GLGenTexturesHelper(GLsizei n, GLuint* ids) { - glGenTextures(n, ids); -} - -void GLDeleteBuffersHelper(GLsizei n, GLuint* ids) { - glDeleteBuffersARB(n, ids); -} - -void GLDeleteFramebuffersHelper(GLsizei n, GLuint* ids) { - glDeleteFramebuffersEXT(n, ids); -} - -void GLDeleteRenderbuffersHelper(GLsizei n, GLuint* ids) { - glDeleteRenderbuffersEXT(n, ids); -} - -void GLDeleteTexturesHelper(GLsizei n, GLuint* ids) { - glDeleteTextures(n, ids); -} - namespace GLErrorBit { enum GLErrorBit { kNoError = 0, @@ -221,6 +220,131 @@ bool IdMap::GetClientId(GLuint service_id, GLuint* client_id) { // cmd stuff to outside this class. class GLES2DecoderImpl : public GLES2Decoder { public: + // Info about Vertex Attributes. This is used to track what the user currently + // has bound on each Vertex Attribute so that checking can be done at + // glDrawXXX time. + class VertexAttribInfo { + public: + VertexAttribInfo() + : enabled_(false), + size_(0), + type_(0), + offset_(0), + real_stride_(0), + buffer_(0), + buffer_size_(0), + num_elements_(0) { + } + // Returns true if this VertexAttrib can access index. + bool CanAccess(GLuint index); + + void set_enabled(bool enabled) { + enabled_ = enabled; + } + + GLuint buffer() const { + return buffer_; + } + + void Clear() { + buffer_ = 0; + SetBufferSize(0); + } + + void SetBufferSize(GLsizeiptr buffer_size) { + buffer_size_ = buffer_size; + if (offset_ > buffer_size || real_stride_ == 0) { + num_elements_ = 0; + } else { + uint32 size = buffer_size - offset_; + num_elements_ = size / real_stride_ + + (size % real_stride_ >= GetGLTypeSize(type_) ? 1 : 0); + } + } + + void SetInfo( + GLuint buffer, + GLsizeiptr buffer_size, + GLint size, + GLenum type, + GLsizei real_stride, + GLsizei offset) { + DCHECK(real_stride > 0); + buffer_ = buffer; + size_ = size; + type_ = type; + real_stride_ = real_stride; + offset_ = offset; + SetBufferSize(buffer_size); + } + + private: + // Whether or not this attribute is enabled. + bool enabled_; + + // number of components (1, 2, 3, 4) + GLint size_; + + // GL_BYTE, GL_FLOAT, etc. See glVertexAttribPointer. + GLenum type_; + + // The offset into the buffer. + GLsizei offset_; + + // The stride that will be used to access the buffer. This is the actual + // stide, NOT the GL bogus stride. In other words there is never a stride + // of 0. + GLsizei real_stride_; + + // The service side name of the buffer bound to this attribute. 0 = invalid + GLuint buffer_; + + // The size of the buffer. + GLsizeiptr buffer_size_; + + // The number of elements that can be accessed. + GLuint num_elements_; + }; + + // Info about Buffers currently in the system. + struct BufferInfo { + BufferInfo() + : size(0) { + } + + explicit BufferInfo(GLsizeiptr _size) + : size(_size) { + } + + GLsizeiptr size; + }; + + // This is used to track which attributes a particular program needs + // so we can verify at glDrawXXX time that every attribute is either disabled + // or if enabled that it points to a valid source. + class ProgramInfo { + public: + typedef std::vector<GLuint> AttribLocationVector; + + ProgramInfo() { + } + + void SetNumAttributes(int num_attribs) { + attrib_locations_.resize(num_attribs); + } + + void SetAttributeLocation(GLuint index, int location) { + DCHECK(index < attrib_locations_.size()); + attrib_locations_[index] = location; + } + + const AttribLocationVector& GetAttribLocations() const { + return attrib_locations_; + } + private: + AttribLocationVector attrib_locations_; + }; + GLES2DecoderImpl(); // Overridden from AsyncAPIInterface. @@ -237,41 +361,59 @@ class GLES2DecoderImpl : public GLES2Decoder { // Overridden from GLES2Decoder. virtual void Destroy(); + // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used + // on glDeleteBuffers so we can make sure the user does not try to render + // with deleted buffers. + void RemoveBufferInfo(GLuint buffer_id); + private: bool InitPlatformSpecific(); bool InitGlew(); // Template to help call glGenXXX functions. - template <void gl_gen_function(GLsizei, GLuint*)> + template <void gl_gen_function(GLES2DecoderImpl*, GLsizei, GLuint*)> bool GenGLObjects(GLsizei n, const GLuint* client_ids) { // TODO(gman): Verify client ids are unused. scoped_array<GLuint>temp(new GLuint[n]); - gl_gen_function(n, temp.get()); + gl_gen_function(this, n, temp.get()); // TODO(gman): check for success before copying results. - for (GLsizei ii = 0; ii < n; ++ii) { - if (!id_map_.AddMapping(client_ids[ii], temp[ii])) { - // TODO(gman): fail. - } - } - return true; + return RegisterObjects(n, client_ids, temp.get()); } // Template to help call glDeleteXXX functions. - template <void gl_delete_function(GLsizei, GLuint*)> + template <void gl_delete_function(GLES2DecoderImpl*, GLsizei, GLuint*)> bool DeleteGLObjects(GLsizei n, const GLuint* client_ids) { scoped_array<GLuint>temp(new GLuint[n]); - // TODO(gman): check for success before copying results. - for (GLsizei ii = 0; ii < n; ++ii) { - if (id_map_.GetServiceId(client_ids[ii], &temp[ii])) { - id_map_.RemoveMapping(client_ids[ii], temp[ii]); - } else { - temp[ii] = 0; - } - } - gl_delete_function(n, temp.get()); + UnregisterObjects(n, client_ids, temp.get()); + gl_delete_function(this, n, temp.get()); return true; } + // Register client ids with generated service ids. + bool RegisterObjects( + GLsizei n, const GLuint* client_ids, const GLuint* service_ids); + + // Unregisters client ids with service ids. + void UnregisterObjects( + GLsizei n, const GLuint* client_ids, GLuint* service_ids); + + // Gets the program info for the given program. Returns NULL if none exists. + // Programs that have no had glLinkProgram succesfully called on them will + // not exist. + ProgramInfo* GetProgramInfo(GLuint program); + + // Updates the program info for the given program. + void UpdateProgramInfo(GLuint program); + + // Deletes the program info for the given program. + void RemoveProgramInfo(GLuint program); + + // Gets the buffer info for the given buffer. + const BufferInfo* GetBufferInfo(GLuint buffer); + + // Sets the info for a buffer. + void SetBufferInfo(GLuint buffer, GLsizeiptr size); + // Wrapper for glCreateProgram void CreateProgramHelper(GLuint client_id); @@ -281,15 +423,46 @@ class GLES2DecoderImpl : public GLES2Decoder { // Wrapper for glBindBuffer since we need to track the current targets. void DoBindBuffer(GLenum target, GLuint buffer); + // Wrapper for glDrawArrays. + void DoDrawArrays(GLenum mode, GLint first, GLsizei count); + + // Wrapper for glDisableVertexAttribArray. + void DoDisableVertexAttribArray(GLuint index); + + // Wrapper for glEnableVertexAttribArray. + void DoEnableVertexAttribArray(GLuint index); + + // Wrapper for glLinkProgram + void DoLinkProgram(GLuint program); + // Swaps the buffers (copies/renders to the current window). void DoSwapBuffers(); + // Wrapper for glUseProgram + void DoUseProgram(GLuint program); + // Gets the GLError through our wrapper. GLenum GetGLError(); // Sets our wrapper for the GLError. void SetGLError(GLenum error); + // Copies the real GL errors to the wrapper. This is so we can + // make sure there are no native GL errors before calling some GL function + // so that on return we know any error generated was for that specific + // command. + void CopyRealGLErrorsToWrapper(); + + // Checks if the current program and vertex attributes are valid for drawing. + bool IsDrawValid(GLuint max_vertex_accessed); + + // Gets the buffer id for a given target. + GLuint GetBufferForTarget(GLenum target) { + DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); + return target == GL_ARRAY_BUFFER ? bound_array_buffer_ : + bound_element_array_buffer_; + } + // Generate a member function prototype for each command in an automated and // typesafe way. #define GLES2_CMD_OP(name) \ @@ -324,6 +497,26 @@ class GLES2DecoderImpl : public GLES2Decoder { // to call glDrawElements. GLuint bound_element_array_buffer_; + // The maximum vertex attributes. + GLuint max_vertex_attribs_; + + // Info for each vertex attribute saved so we can check at glDrawXXX time + // if it is safe to draw. + scoped_array<VertexAttribInfo> vertex_attrib_infos_; + + // Info for each buffer in the system. + // TODO(gman): Choose a faster container. + typedef std::map<GLuint, BufferInfo> BufferInfoMap; + BufferInfoMap buffer_infos_; + + // Info for each "successfully linked" program by service side program Id. + // TODO(gman): Choose a faster container. + typedef std::map<GLuint, ProgramInfo> ProgramInfoMap; + ProgramInfoMap program_infos_; + + // The program in current use through glUseProgram. + ProgramInfo* current_program_info_; + #if defined(OS_WIN) HDC device_context_; HGLRC gl_context_; @@ -346,6 +539,8 @@ GLES2DecoderImpl::GLES2DecoderImpl() unpack_alignment_(4), bound_array_buffer_(0), bound_element_array_buffer_(0), + max_vertex_attribs_(0), + current_program_info_(NULL), #ifdef OS_WIN device_context_(NULL), gl_context_(NULL), @@ -360,6 +555,17 @@ bool GLES2DecoderImpl::Initialize() { return false; CHECK_GL_ERROR(); + // Lookup GL things we need to know. + GLint value; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value); + max_vertex_attribs_ = value; + + DCHECK_GE(max_vertex_attribs_, 8u); + + vertex_attrib_infos_.reset(new VertexAttribInfo[max_vertex_attribs_]); + memset(vertex_attrib_infos_.get(), 0, + sizeof(vertex_attrib_infos_[0]) * max_vertex_attribs_); + //glBindFramebuffer(0, 0); return true; } @@ -533,9 +739,84 @@ bool GetWindowsPixelFormat(HWND window, return true; } +// These commands convert from c calls to local os calls. +void GLGenBuffersHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glGenBuffersARB(n, ids); +} + +void GLGenFramebuffersHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glGenFramebuffersEXT(n, ids); +} + +void GLGenRenderbuffersHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glGenRenderbuffersEXT(n, ids); +} + +void GLGenTexturesHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glGenTextures(n, ids); +} + +void GLDeleteBuffersHelper( + GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) { + glDeleteBuffersARB(n, ids); + for (GLsizei ii = 0; ii < n; ++ii) { + decoder->RemoveBufferInfo(ids[ii]); + } +} + +void GLDeleteFramebuffersHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glDeleteFramebuffersEXT(n, ids); +} + +void GLDeleteRenderbuffersHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glDeleteRenderbuffersEXT(n, ids); +} + +void GLDeleteTexturesHelper( + GLES2DecoderImpl*, GLsizei n, GLuint* ids) { + glDeleteTextures(n, ids); +} + } // anonymous namespace #endif +bool GLES2DecoderImpl::RegisterObjects( + GLsizei n, const GLuint* client_ids, const GLuint* service_ids) { + for (GLsizei ii = 0; ii < n; ++ii) { + if (!id_map_.AddMapping(client_ids[ii], service_ids[ii])) { + // TODO(gman): fail. + } + } + return true; +} + +void GLES2DecoderImpl::UnregisterObjects( + GLsizei n, const GLuint* client_ids, GLuint* service_ids) { + // TODO(gman): check for success before copying results. + for (GLsizei ii = 0; ii < n; ++ii) { + if (id_map_.GetServiceId(client_ids[ii], &service_ids[ii])) { + id_map_.RemoveMapping(client_ids[ii], service_ids[ii]); + } else { + service_ids[ii] = 0; + } + } +} + +void GLES2DecoderImpl::RemoveBufferInfo(GLuint buffer_id) { + for (GLuint ii = 0; ii < max_vertex_attribs_; ++ii) { + if (vertex_attrib_infos_[ii].buffer() == buffer_id) { + vertex_attrib_infos_[ii].Clear(); + } + } + buffer_infos_.erase(buffer_id); +} + bool GLES2DecoderImpl::InitPlatformSpecific() { #if defined(OS_WIN) device_context_ = ::GetDC(hwnd()); @@ -678,8 +959,10 @@ parse_error::ParseError GLES2DecoderImpl::DoCommand( #undef GLES2_CMD_OP } if (debug()) { - if (glGetError() != 0) { + GLenum error; + while ((error = glGetError()) != GL_NO_ERROR) { // TODO(gman): Change output to something useful for NaCl. + SetGLError(error); printf("GL ERROR b4: %s\n", GetCommandName(command)); } } @@ -723,6 +1006,24 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint buffer) { glBindBuffer(target, buffer); } +void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { + if (index < max_vertex_attribs_) { + vertex_attrib_infos_[index].set_enabled(false); + glEnableVertexAttribArray(index); + } else { + SetGLError(GL_INVALID_VALUE); + } +} + +void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) { + if (index < max_vertex_attribs_) { + vertex_attrib_infos_[index].set_enabled(true); + glEnableVertexAttribArray(index); + } else { + SetGLError(GL_INVALID_VALUE); + } +} + parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader( uint32 immediate_data_size, const gles2::DeleteShader& c) { GLuint shader = c.shader; @@ -731,7 +1032,7 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteShader( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - glDeleteProgram(service_id); + glDeleteShader(service_id); id_map_.RemoveMapping(shader, service_id); return parse_error::kParseNoError; } @@ -744,11 +1045,31 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteProgram( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } + RemoveProgramInfo(program); glDeleteProgram(service_id); id_map_.RemoveMapping(program, service_id); return parse_error::kParseNoError; } +void GLES2DecoderImpl::DoDrawArrays( + GLenum mode, GLint first, GLsizei count) { + if (IsDrawValid(first + count - 1)) { + glDrawArrays(mode, first, count); + } +} + +void GLES2DecoderImpl::DoLinkProgram(GLuint program) { + CopyRealGLErrorsToWrapper(); + glLinkProgram(program); + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + RemoveProgramInfo(program); + SetGLError(error); + } else { + UpdateProgramInfo(program); + } +}; + // NOTE: If you need to know the results of SwapBuffers (like losing // the context) then add a new command. Do NOT make SwapBuffers synchronous. void GLES2DecoderImpl::DoSwapBuffers() { @@ -762,6 +1083,17 @@ void GLES2DecoderImpl::DoSwapBuffers() { #endif } +void GLES2DecoderImpl::DoUseProgram(GLuint program) { + ProgramInfo* info = GetProgramInfo(program); + if (!info) { + // Program was not linked successfully. (ie, glLinkProgram) + SetGLError(GL_INVALID_OPERATION); + } else { + current_program_info_ = info; + glUseProgram(program); + } +} + GLenum GLES2DecoderImpl::GetGLError() { // Check the GL error first, then our wrapped error. GLenum error = glGetError(); @@ -786,6 +1118,97 @@ void GLES2DecoderImpl::SetGLError(GLenum error) { error_bits_ |= GLErrorToErrorBit(error); } +void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() { + GLenum error; + while ((error = glGetError()) != GL_NO_ERROR) { + SetGLError(error); + } +} + +const GLES2DecoderImpl::BufferInfo* GLES2DecoderImpl::GetBufferInfo( + GLuint buffer) { + BufferInfoMap::iterator it = buffer_infos_.find(buffer); + return it != buffer_infos_.end() ? &it->second : NULL; +} + +void GLES2DecoderImpl::SetBufferInfo(GLuint buffer, GLsizeiptr size) { + buffer_infos_[buffer] = BufferInfo(size); + + // Also go through VertexAttribInfo and update any info that references + // the same buffer. + for (GLuint ii = 0; ii < max_vertex_attribs_; ++ii) { + if (vertex_attrib_infos_[ii].buffer() == buffer) { + vertex_attrib_infos_[ii].SetBufferSize(size); + } + } +} + +GLES2DecoderImpl::ProgramInfo* GLES2DecoderImpl::GetProgramInfo( + GLuint program) { + ProgramInfoMap::iterator it = program_infos_.find(program); + return it != program_infos_.end() ? &it->second : NULL; +} + +void GLES2DecoderImpl::UpdateProgramInfo(GLuint program) { + ProgramInfo* info = GetProgramInfo(program); + if (!info) { + std::pair<ProgramInfoMap::iterator, bool> result = + program_infos_.insert(std::make_pair(program, ProgramInfo())); + DCHECK(result.second); + info = &result.first->second; + } + GLint num_attribs = 0; + GLint max_len = 0; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &num_attribs); + info->SetNumAttributes(num_attribs); + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); + // TODO(gman): Should we check for error? + scoped_array<char> name_buffer(new char[max_len + 1]); + for (GLint ii = 0; ii < num_attribs; ++ii) { + GLsizei length; + GLsizei size; + GLenum type; + glGetActiveAttrib( + program, ii, max_len + 1, &length, &size, &type, name_buffer.get()); + // TODO(gman): Should we check for error? + GLint location = glGetAttribLocation(program, name_buffer.get()); + info->SetAttributeLocation(ii, num_attribs); + } +} + +void GLES2DecoderImpl::RemoveProgramInfo(GLuint program) { + ProgramInfoMap::iterator it = program_infos_.find(program); + if (it != program_infos_.end()) { + if (current_program_info_ == &it->second) { + current_program_info_ = NULL; + } + program_infos_.erase(it); + } +} + +bool GLES2DecoderImpl::VertexAttribInfo::CanAccess(GLuint index) { + return !enabled_ || (buffer_ != 0 && index < num_elements_); +} + +bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) { + if (current_program_info_) { + // Validate that all attribs current program needs are setup correctly. + const ProgramInfo::AttribLocationVector& locations = + current_program_info_->GetAttribLocations(); + for (size_t ii = 0; ii < locations.size(); ++ii) { + GLuint location = locations[ii]; + DCHECK_LT(location, max_vertex_attribs_); + if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) { + SetGLError(GL_INVALID_OPERATION); + } + } + return true; + } + // We do not set a GL error here because the GL spec says no error if the + // program is invalid. + return false; +}; + parse_error::ParseError GLES2DecoderImpl::HandleDrawElements( uint32 immediate_data_size, const gles2::DrawElements& c) { if (bound_element_array_buffer_ != 0) { @@ -797,9 +1220,15 @@ parse_error::ParseError GLES2DecoderImpl::HandleDrawElements( SetGLError(GL_INVALID_VALUE); } else { const GLvoid* indices = reinterpret_cast<const GLvoid*>(c.index_offset); - // TODO(gman): Validate indices - // TOOD(gman): Validate all attribs current program needs are setup. - glDrawElements(mode, count, type, indices); + // TODO(gman): Validate indices. Get maximum index. + // + // This value should be computed by walking the index buffer from 0 to + // count and finding the maximum vertex accessed. + // For now we'll special case 0 to not check. + GLuint max_vertex_accessed = 0; + if (IsDrawValid(max_vertex_accessed)) { + glDrawElements(mode, count, type, indices); + } } } else { SetGLError(GL_INVALID_VALUE); @@ -865,8 +1294,8 @@ parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate( } GLsizei count = c.count; uint32 data_size = c.data_size; - // TODO(gman): need to check that data_size is in range for arg_count. - const char** data = GetImmediateDataAs<const char**>(c); + const char** data = GetImmediateDataAs<const char**>( + c, data_size, immediate_data_size); if (!data) { return parse_error::kParseOutOfBounds; } @@ -876,21 +1305,35 @@ parse_error::ParseError GLES2DecoderImpl::HandleShaderSourceImmediate( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttribPointer( uint32 immediate_data_size, const gles2::VertexAttribPointer& c) { - // TODO(gman): Is this a valid check or does this check have to come - // at glDrawElements time. if (bound_array_buffer_ != 0) { GLuint indx = c.indx; GLint size = c.size; GLenum type = c.type; GLboolean normalized = c.normalized; GLsizei stride = c.stride; - GLuint offset = c.offset; - const void* ptr = reinterpret_cast<const void*>(c.offset); + GLsizei offset = c.offset; + const void* ptr = reinterpret_cast<const void*>(offset); if (!ValidateGLenumVertexAttribType(type) || - !ValidateGLenumVertexAttribSize(size)) { + !ValidateGLenumVertexAttribSize(size) || + indx >= max_vertex_attribs_ || + stride < 0) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } + const BufferInfo* buffer_info = GetBufferInfo(bound_array_buffer_); + GLsizei component_size = GetGLTypeSize(type); + GLsizei real_stride = stride != 0 ? stride : component_size * size; + if (offset % component_size > 0) { + SetGLError(GL_INVALID_VALUE); + return parse_error::kParseNoError; + } + vertex_attrib_infos_[indx].SetInfo( + bound_array_buffer_, + buffer_info ? buffer_info->size : 0, + size, + type, + real_stride, + offset); glVertexAttribPointer(indx, size, type, normalized, stride, ptr); } else { SetGLError(GL_INVALID_VALUE); @@ -975,9 +1418,8 @@ parse_error::ParseError GLES2DecoderImpl::HandleGetAttribLocationImmediate( return parse_error::kParseNoError; } uint32 name_size = c.data_size; - const char* name = GetImmediateDataAs<const char*>(c); - // TODO(gman): Make sure validate checks arg_count - // covers data_size. + const char* name = GetImmediateDataAs<const char*>( + c, name_size, immediate_data_size); GLint* location = GetSharedMemoryAs<GLint*>( c.location_shm_id, c.location_shm_offset, sizeof(GLint)); if (!location || !name) { @@ -1016,9 +1458,8 @@ parse_error::ParseError GLES2DecoderImpl::HandleGetUniformLocationImmediate( return parse_error::kParseNoError; } uint32 name_size = c.data_size; - const char* name = GetImmediateDataAs<const char*>(c); - // TODO(gman): Make sure validate checks arg_count - // covers data_size. + const char* name = GetImmediateDataAs<const char*>( + c, name_size, immediate_data_size); GLint* location = GetSharedMemoryAs<GLint*>( c.location_shm_id, c.location_shm_offset, sizeof(GLint)); if (!location || !name) { @@ -1043,13 +1484,26 @@ parse_error::ParseError GLES2DecoderImpl::HandleBufferData( return parse_error::kParseOutOfBounds; } } - // TODO(gman): Validate case where data is NULL. if (!ValidateGLenumBufferTarget(target) || !ValidateGLenumBufferUsage(usage)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } + // Clear the buffer to 0 if no initial data was passed in. + scoped_array<int8> zero; + if (!data) { + zero.reset(new int8[size]); + memset(zero.get(), 0, size); + data = zero.get(); + } + CopyRealGLErrorsToWrapper(); glBufferData(target, size, data, usage); + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + SetGLError(error); + } else { + SetBufferInfo(GetBufferForTarget(target), size); + } return parse_error::kParseNoError; } @@ -1057,15 +1511,25 @@ parse_error::ParseError GLES2DecoderImpl::HandleBufferDataImmediate( uint32 immediate_data_size, const gles2::BufferDataImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLsizeiptr size = static_cast<GLsizeiptr>(c.size); - const void* data = GetImmediateDataAs<const void*>(c); + const void* data = GetImmediateDataAs<const void*>( + c, size, immediate_data_size); + if (!data) { + return parse_error::kParseOutOfBounds; + } GLenum usage = static_cast<GLenum>(c.usage); if (!ValidateGLenumBufferTarget(target) || !ValidateGLenumBufferUsage(usage)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - // TODO(gman): Handle case where data is NULL. + CopyRealGLErrorsToWrapper(); glBufferData(target, size, data, usage); + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + SetGLError(error); + } else { + SetBufferInfo(GetBufferForTarget(target), size); + } return parse_error::kParseNoError; } @@ -1093,7 +1557,12 @@ parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2D( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - // TODO(gman): Validate case where data is NULL. + scoped_array<int8> zero; + if (!data) { + zero.reset(new int8[image_size]); + memset(zero.get(), 0, image_size); + data = zero.get(); + } glCompressedTexImage2D( target, level, internal_format, width, height, border, image_size, data); return parse_error::kParseNoError; @@ -1108,9 +1577,8 @@ parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexImage2DImmediate( GLsizei height = static_cast<GLsizei>(c.height); GLint border = static_cast<GLint>(c.border); GLsizei image_size = static_cast<GLsizei>(c.imageSize); - const void* data = GetImmediateDataAs<const void*>(c); - // Immediate version. - // TODO(gman): Handle case where data is NULL. + const void* data = GetImmediateDataAs<const void*>( + c, image_size, immediate_data_size); if (!data) { return parse_error::kParseOutOfBounds; } @@ -1153,7 +1621,12 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexImage2D( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - // TODO(gman): Validate case where data is NULL. + scoped_array<int8> zero; + if (!pixels) { + zero.reset(new int8[pixels_size]); + memset(zero.get(), 0, pixels_size); + pixels = zero.get(); + } glTexImage2D( target, level, internal_format, width, height, border, format, type, pixels); @@ -1170,9 +1643,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexImage2DImmediate( GLint border = static_cast<GLint>(c.border); GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); - const void* pixels = GetImmediateDataAs<const void*>(c); - // Immediate version. - // TODO(gman): Handle case where data is NULL. + uint32 size = GLES2Util::ComputeImageDataSize( + width, height, format, type, unpack_alignment_); + const void* pixels = GetImmediateDataAs<const void*>( + c, size, immediate_data_size); if (!pixels) { return parse_error::kParseOutOfBounds; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 957ccad..24e7340 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -53,9 +53,8 @@ parse_error::ParseError GLES2DecoderImpl::HandleBindAttribLocationImmediate( } GLuint index = static_cast<GLuint>(c.index); uint32 name_size = c.data_size; - const char* name = GetImmediateDataAs<const char*>(c); - // TODO(gman): Make sure validate checks - // immediate_data_size covers data_size. + const char* name = GetImmediateDataAs<const char*>( + c, name_size, immediate_data_size); if (name == NULL) { return parse_error::kParseOutOfBounds; } @@ -212,11 +211,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleBufferSubData( GLenum target = static_cast<GLenum>(c.target); GLintptr offset = static_cast<GLintptr>(c.offset); GLsizeiptr size = static_cast<GLsizeiptr>(c.size); - uint32 data_shm_id = static_cast<uint32>(c.data_shm_id); - uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset); uint32 data_size = size; const void* data = GetSharedMemoryAs<const void*>( - data_shm_id, data_shm_offset, data_size); + c.data_shm_id, c.data_shm_offset, data_size); if (!ValidateGLenumBufferTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -233,15 +230,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleBufferSubDataImmediate( GLenum target = static_cast<GLenum>(c.target); GLintptr offset = static_cast<GLintptr>(c.offset); GLsizeiptr size = static_cast<GLsizeiptr>(c.size); - const void* data = GetImmediateDataAs<const void*>(c); - if (!ValidateGLenumBufferTarget(target)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (data == NULL) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. + uint32 data_size = size; + const void* data = GetImmediateDataAs<const void*>( + c, data_size, immediate_data_size); if (!ValidateGLenumBufferTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -326,11 +317,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexSubImage2D( GLsizei height = static_cast<GLsizei>(c.height); GLenum format = static_cast<GLenum>(c.format); GLsizei imageSize = static_cast<GLsizei>(c.imageSize); - uint32 data_shm_id = static_cast<uint32>(c.data_shm_id); - uint32 data_shm_offset = static_cast<uint32>(c.data_shm_offset); uint32 data_size = imageSize; const void* data = GetSharedMemoryAs<const void*>( - data_shm_id, data_shm_offset, data_size); + c.data_shm_id, c.data_shm_offset, data_size); if (!ValidateGLenumTextureTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -355,15 +344,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleCompressedTexSubImage2DImmediate GLsizei height = static_cast<GLsizei>(c.height); GLenum format = static_cast<GLenum>(c.format); GLsizei imageSize = static_cast<GLsizei>(c.imageSize); - const void* data = GetImmediateDataAs<const void*>(c); - if (!ValidateGLenumTextureTarget(target)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (data == NULL) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. + uint32 data_size = imageSize; + const void* data = GetImmediateDataAs<const void*>( + c, data_size, immediate_data_size); if (!ValidateGLenumTextureTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -427,10 +410,6 @@ parse_error::ParseError GLES2DecoderImpl::HandleCreateShader( return parse_error::kParseNoError; } uint32 client_id = c.client_id; - if (!ValidateGLenumShaderType(type)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } CreateShaderHelper(type, client_id); return parse_error::kParseNoError; } @@ -449,11 +428,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleCullFace( parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffers( uint32 immediate_data_size, const gles2::DeleteBuffers& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); const GLuint* buffers = GetSharedMemoryAs<const GLuint*>( - c.buffers_shm_id, c.buffers_shm_offset, 0 /* TODO(gman): size */); - if (buffers == NULL) { - return parse_error::kParseOutOfBounds; - } + c.buffers_shm_id, c.buffers_shm_offset, data_size); if (buffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -464,10 +441,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffers( parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffersImmediate( uint32 immediate_data_size, const gles2::DeleteBuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - const GLuint* buffers = GetImmediateDataAs<const GLuint*>(c); - if (buffers == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + const GLuint* buffers = GetImmediateDataAs<const GLuint*>( + c, data_size, immediate_data_size); if (buffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -478,12 +454,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteBuffersImmediate( parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffers( uint32 immediate_data_size, const gles2::DeleteFramebuffers& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); const GLuint* framebuffers = GetSharedMemoryAs<const GLuint*>( - c.framebuffers_shm_id, c.framebuffers_shm_offset, 0 /* TODO( - gman): size */); - if (framebuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + c.framebuffers_shm_id, c.framebuffers_shm_offset, data_size); if (framebuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -494,10 +467,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffers( parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffersImmediate( uint32 immediate_data_size, const gles2::DeleteFramebuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - const GLuint* framebuffers = GetImmediateDataAs<const GLuint*>(c); - if (framebuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + const GLuint* framebuffers = GetImmediateDataAs<const GLuint*>( + c, data_size, immediate_data_size); if (framebuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -508,12 +480,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteFramebuffersImmediate( parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffers( uint32 immediate_data_size, const gles2::DeleteRenderbuffers& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); const GLuint* renderbuffers = GetSharedMemoryAs<const GLuint*>( - c.renderbuffers_shm_id, c.renderbuffers_shm_offset, 0 /* TODO( - gman): size */); - if (renderbuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + c.renderbuffers_shm_id, c.renderbuffers_shm_offset, data_size); if (renderbuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -524,10 +493,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffers( parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffersImmediate( uint32 immediate_data_size, const gles2::DeleteRenderbuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - const GLuint* renderbuffers = GetImmediateDataAs<const GLuint*>(c); - if (renderbuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + const GLuint* renderbuffers = GetImmediateDataAs<const GLuint*>( + c, data_size, immediate_data_size); if (renderbuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -538,11 +506,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteRenderbuffersImmediate( parse_error::ParseError GLES2DecoderImpl::HandleDeleteTextures( uint32 immediate_data_size, const gles2::DeleteTextures& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); const GLuint* textures = GetSharedMemoryAs<const GLuint*>( - c.textures_shm_id, c.textures_shm_offset, 0 /* TODO(gman): size */); - if (textures == NULL) { - return parse_error::kParseOutOfBounds; - } + c.textures_shm_id, c.textures_shm_offset, data_size); if (textures == NULL) { return parse_error::kParseOutOfBounds; } @@ -553,10 +519,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleDeleteTextures( parse_error::ParseError GLES2DecoderImpl::HandleDeleteTexturesImmediate( uint32 immediate_data_size, const gles2::DeleteTexturesImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - const GLuint* textures = GetImmediateDataAs<const GLuint*>(c); - if (textures == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + const GLuint* textures = GetImmediateDataAs<const GLuint*>( + c, data_size, immediate_data_size); if (textures == NULL) { return parse_error::kParseOutOfBounds; } @@ -620,7 +585,7 @@ parse_error::ParseError GLES2DecoderImpl::HandleDisable( parse_error::ParseError GLES2DecoderImpl::HandleDisableVertexAttribArray( uint32 immediate_data_size, const gles2::DisableVertexAttribArray& c) { GLuint index = static_cast<GLuint>(c.index); - glDisableVertexAttribArray(index); + DoDisableVertexAttribArray(index); return parse_error::kParseNoError; } @@ -633,7 +598,7 @@ parse_error::ParseError GLES2DecoderImpl::HandleDrawArrays( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - glDrawArrays(mode, first, count); + DoDrawArrays(mode, first, count); return parse_error::kParseNoError; } @@ -651,7 +616,7 @@ parse_error::ParseError GLES2DecoderImpl::HandleEnable( parse_error::ParseError GLES2DecoderImpl::HandleEnableVertexAttribArray( uint32 immediate_data_size, const gles2::EnableVertexAttribArray& c) { GLuint index = static_cast<GLuint>(c.index); - glEnableVertexAttribArray(index); + DoEnableVertexAttribArray(index); return parse_error::kParseNoError; } @@ -735,11 +700,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleFrontFace( parse_error::ParseError GLES2DecoderImpl::HandleGenBuffers( uint32 immediate_data_size, const gles2::GenBuffers& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); GLuint* buffers = GetSharedMemoryAs<GLuint*>( - c.buffers_shm_id, c.buffers_shm_offset, 0 /* TODO(gman): size */); - if (buffers == NULL) { - return parse_error::kParseOutOfBounds; - } + c.buffers_shm_id, c.buffers_shm_offset, data_size); if (buffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -750,10 +713,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenBuffers( parse_error::ParseError GLES2DecoderImpl::HandleGenBuffersImmediate( uint32 immediate_data_size, const gles2::GenBuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - GLuint* buffers = GetImmediateDataAs<GLuint*>(c); - if (buffers == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + GLuint* buffers = GetImmediateDataAs<GLuint*>( + c, data_size, immediate_data_size); if (buffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -775,12 +737,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenerateMipmap( parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffers( uint32 immediate_data_size, const gles2::GenFramebuffers& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); GLuint* framebuffers = GetSharedMemoryAs<GLuint*>( - c.framebuffers_shm_id, c.framebuffers_shm_offset, 0 /* TODO( - gman): size */); - if (framebuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + c.framebuffers_shm_id, c.framebuffers_shm_offset, data_size); if (framebuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -791,10 +750,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffers( parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffersImmediate( uint32 immediate_data_size, const gles2::GenFramebuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - GLuint* framebuffers = GetImmediateDataAs<GLuint*>(c); - if (framebuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + GLuint* framebuffers = GetImmediateDataAs<GLuint*>( + c, data_size, immediate_data_size); if (framebuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -805,12 +763,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenFramebuffersImmediate( parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffers( uint32 immediate_data_size, const gles2::GenRenderbuffers& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); GLuint* renderbuffers = GetSharedMemoryAs<GLuint*>( - c.renderbuffers_shm_id, c.renderbuffers_shm_offset, 0 /* TODO( - gman): size */); - if (renderbuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + c.renderbuffers_shm_id, c.renderbuffers_shm_offset, data_size); if (renderbuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -821,10 +776,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffers( parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffersImmediate( uint32 immediate_data_size, const gles2::GenRenderbuffersImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - GLuint* renderbuffers = GetImmediateDataAs<GLuint*>(c); - if (renderbuffers == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + GLuint* renderbuffers = GetImmediateDataAs<GLuint*>( + c, data_size, immediate_data_size); if (renderbuffers == NULL) { return parse_error::kParseOutOfBounds; } @@ -835,11 +789,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenRenderbuffersImmediate( parse_error::ParseError GLES2DecoderImpl::HandleGenTextures( uint32 immediate_data_size, const gles2::GenTextures& c) { GLsizei n = static_cast<GLsizei>(c.n); + uint32 data_size = n * sizeof(GLuint); GLuint* textures = GetSharedMemoryAs<GLuint*>( - c.textures_shm_id, c.textures_shm_offset, 0 /* TODO(gman): size */); - if (textures == NULL) { - return parse_error::kParseOutOfBounds; - } + c.textures_shm_id, c.textures_shm_offset, data_size); if (textures == NULL) { return parse_error::kParseOutOfBounds; } @@ -850,10 +802,9 @@ parse_error::ParseError GLES2DecoderImpl::HandleGenTextures( parse_error::ParseError GLES2DecoderImpl::HandleGenTexturesImmediate( uint32 immediate_data_size, const gles2::GenTexturesImmediate& c) { GLsizei n = static_cast<GLsizei>(c.n); - GLuint* textures = GetImmediateDataAs<GLuint*>(c); - if (textures == NULL) { - return parse_error::kParseOutOfBounds; - } + uint32 data_size = n * sizeof(GLuint); + GLuint* textures = GetImmediateDataAs<GLuint*>( + c, data_size, immediate_data_size); if (textures == NULL) { return parse_error::kParseOutOfBounds; } @@ -1001,13 +952,18 @@ parse_error::ParseError GLES2DecoderImpl::HandleGetProgramInfoLog( return parse_error::kParseNoError; } GLsizei bufsize = static_cast<GLsizei>(c.bufsize); - GLsizei* length = GetSharedMemoryAs<GLsizei*>( - c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */); - char* infolog = GetSharedMemoryAs<char*>( - c.infolog_shm_id, c.infolog_shm_offset, 0 /* TODO(gman): size */); - if (length == NULL) { - return parse_error::kParseOutOfBounds; + uint32 size_shm_id = c.length_shm_id; + uint32 size_shm_offset = c.length_shm_offset; + GLsizei* length = NULL; + if (size_shm_id != 0 || size_shm_offset != 0) { + length = GetSharedMemoryAs<GLsizei*>( + size_shm_id, size_shm_offset, sizeof(*length)); + if (!length) { + return parse_error::kParseOutOfBounds; + } } + char* infolog = GetSharedMemoryAs<char*>( + c.infolog_shm_id, c.infolog_shm_offset, bufsize); if (infolog == NULL) { return parse_error::kParseOutOfBounds; } @@ -1071,13 +1027,18 @@ parse_error::ParseError GLES2DecoderImpl::HandleGetShaderInfoLog( return parse_error::kParseNoError; } GLsizei bufsize = static_cast<GLsizei>(c.bufsize); - GLsizei* length = GetSharedMemoryAs<GLsizei*>( - c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */); - char* infolog = GetSharedMemoryAs<char*>( - c.infolog_shm_id, c.infolog_shm_offset, 0 /* TODO(gman): size */); - if (length == NULL) { - return parse_error::kParseOutOfBounds; + uint32 size_shm_id = c.length_shm_id; + uint32 size_shm_offset = c.length_shm_offset; + GLsizei* length = NULL; + if (size_shm_id != 0 || size_shm_offset != 0) { + length = GetSharedMemoryAs<GLsizei*>( + size_shm_id, size_shm_offset, sizeof(*length)); + if (!length) { + return parse_error::kParseOutOfBounds; + } } + char* infolog = GetSharedMemoryAs<char*>( + c.infolog_shm_id, c.infolog_shm_offset, bufsize); if (infolog == NULL) { return parse_error::kParseOutOfBounds; } @@ -1093,13 +1054,18 @@ parse_error::ParseError GLES2DecoderImpl::HandleGetShaderSource( return parse_error::kParseNoError; } GLsizei bufsize = static_cast<GLsizei>(c.bufsize); - GLsizei* length = GetSharedMemoryAs<GLsizei*>( - c.length_shm_id, c.length_shm_offset, 0 /* TODO(gman): size */); - char* source = GetSharedMemoryAs<char*>( - c.source_shm_id, c.source_shm_offset, 0 /* TODO(gman): size */); - if (length == NULL) { - return parse_error::kParseOutOfBounds; + uint32 size_shm_id = c.length_shm_id; + uint32 size_shm_offset = c.length_shm_offset; + GLsizei* length = NULL; + if (size_shm_id != 0 || size_shm_offset != 0) { + length = GetSharedMemoryAs<GLsizei*>( + size_shm_id, size_shm_offset, sizeof(*length)); + if (!length) { + return parse_error::kParseOutOfBounds; + } } + char* source = GetSharedMemoryAs<char*>( + c.source_shm_id, c.source_shm_offset, bufsize); if (source == NULL) { return parse_error::kParseOutOfBounds; } @@ -1327,7 +1293,7 @@ parse_error::ParseError GLES2DecoderImpl::HandleLinkProgram( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - glLinkProgram(program); + DoLinkProgram(program); return parse_error::kParseNoError; } @@ -1493,8 +1459,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfv( uint32 immediate_data_size, const gles2::TexParameterfv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 1); const GLfloat* params = GetSharedMemoryAs<const GLfloat*>( - c.params_shm_id, c.params_shm_offset, 0 /* TODO(gman): size */); + c.params_shm_id, c.params_shm_offset, data_size); if (!ValidateGLenumTextureBindTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -1514,7 +1482,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfvImmediate( uint32 immediate_data_size, const gles2::TexParameterfvImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); - const GLfloat* params = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 1); + const GLfloat* params = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (!ValidateGLenumTextureBindTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -1526,26 +1497,6 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexParameterfvImmediate( if (params == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<TexParameterfvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 1)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (!ValidateGLenumTextureBindTarget(target)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (!ValidateGLenumTextureParameter(pname)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (params == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<TexParameterfvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 1)) { - return parse_error::kParseOutOfBounds; - } glTexParameterfv(target, pname, params); return parse_error::kParseNoError; } @@ -1571,8 +1522,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexParameteriv( uint32 immediate_data_size, const gles2::TexParameteriv& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 1); const GLint* params = GetSharedMemoryAs<const GLint*>( - c.params_shm_id, c.params_shm_offset, 0 /* TODO(gman): size */); + c.params_shm_id, c.params_shm_offset, data_size); if (!ValidateGLenumTextureBindTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -1592,23 +1545,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexParameterivImmediate( uint32 immediate_data_size, const gles2::TexParameterivImmediate& c) { GLenum target = static_cast<GLenum>(c.target); GLenum pname = static_cast<GLenum>(c.pname); - const GLint* params = GetImmediateDataAs<const GLint*>(c); - if (!ValidateGLenumTextureBindTarget(target)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (!ValidateGLenumTextureParameter(pname)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (params == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<TexParameterivImmediate>( - immediate_data_size, 1, sizeof(GLint), 1)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 1); + const GLint* params = GetImmediateDataAs<const GLint*>( + c, data_size, immediate_data_size); if (!ValidateGLenumTextureBindTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -1620,10 +1560,6 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexParameterivImmediate( if (params == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<TexParameterivImmediate>( - immediate_data_size, 1, sizeof(GLint), 1)) { - return parse_error::kParseOutOfBounds; - } glTexParameteriv(target, pname, params); return parse_error::kParseNoError; } @@ -1638,12 +1574,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexSubImage2D( GLsizei height = static_cast<GLsizei>(c.height); GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); - uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id); - uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset); - uint32 pixels_size = GLES2Util::ComputeImageDataSize( + uint32 data_size = GLES2Util::ComputeImageDataSize( width, height, format, type, unpack_alignment_); const void* pixels = GetSharedMemoryAs<const void*>( - pixels_shm_id, pixels_shm_offset, pixels_size); + c.pixels_shm_id, c.pixels_shm_offset, data_size); if (!ValidateGLenumTextureTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -1674,23 +1608,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleTexSubImage2DImmediate( GLsizei height = static_cast<GLsizei>(c.height); GLenum format = static_cast<GLenum>(c.format); GLenum type = static_cast<GLenum>(c.type); - const void* pixels = GetImmediateDataAs<const void*>(c); - if (!ValidateGLenumTextureTarget(target)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (!ValidateGLenumTextureFormat(format)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (!ValidateGLenumPixelType(type)) { - SetGLError(GL_INVALID_VALUE); - return parse_error::kParseNoError; - } - if (pixels == NULL) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. + uint32 data_size = GLES2Util::ComputeImageDataSize( + width, height, format, type, unpack_alignment_); + const void* pixels = GetImmediateDataAs<const void*>( + c, data_size, immediate_data_size); if (!ValidateGLenumTextureTarget(target)) { SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; @@ -1723,8 +1644,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform1fv( uint32 immediate_data_size, const gles2::Uniform1fv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 1); const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -1736,22 +1659,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform1fvImmediate( uint32 immediate_data_size, const gles2::Uniform1fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 1); + const GLfloat* v = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform1fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 1)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform1fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 1)) { - return parse_error::kParseOutOfBounds; - } glUniform1fv(location, count, v); return parse_error::kParseNoError; } @@ -1768,8 +1682,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform1iv( uint32 immediate_data_size, const gles2::Uniform1iv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 1); const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -1781,22 +1697,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform1ivImmediate( uint32 immediate_data_size, const gles2::Uniform1ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLint* v = GetImmediateDataAs<const GLint*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 1); + const GLint* v = GetImmediateDataAs<const GLint*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform1ivImmediate>( - immediate_data_size, count, sizeof(GLint), 1)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform1ivImmediate>( - immediate_data_size, count, sizeof(GLint), 1)) { - return parse_error::kParseOutOfBounds; - } glUniform1iv(location, count, v); return parse_error::kParseNoError; } @@ -1814,8 +1721,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform2fv( uint32 immediate_data_size, const gles2::Uniform2fv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 2); const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -1827,22 +1736,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform2fvImmediate( uint32 immediate_data_size, const gles2::Uniform2fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 2); + const GLfloat* v = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform2fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 2)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform2fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 2)) { - return parse_error::kParseOutOfBounds; - } glUniform2fv(location, count, v); return parse_error::kParseNoError; } @@ -1860,8 +1760,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform2iv( uint32 immediate_data_size, const gles2::Uniform2iv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 2); const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -1873,22 +1775,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform2ivImmediate( uint32 immediate_data_size, const gles2::Uniform2ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLint* v = GetImmediateDataAs<const GLint*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 2); + const GLint* v = GetImmediateDataAs<const GLint*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform2ivImmediate>( - immediate_data_size, count, sizeof(GLint), 2)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform2ivImmediate>( - immediate_data_size, count, sizeof(GLint), 2)) { - return parse_error::kParseOutOfBounds; - } glUniform2iv(location, count, v); return parse_error::kParseNoError; } @@ -1907,8 +1800,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform3fv( uint32 immediate_data_size, const gles2::Uniform3fv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 3); const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -1920,22 +1815,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform3fvImmediate( uint32 immediate_data_size, const gles2::Uniform3fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 3); + const GLfloat* v = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform3fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 3)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform3fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 3)) { - return parse_error::kParseOutOfBounds; - } glUniform3fv(location, count, v); return parse_error::kParseNoError; } @@ -1954,8 +1840,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform3iv( uint32 immediate_data_size, const gles2::Uniform3iv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 3); const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -1967,22 +1855,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform3ivImmediate( uint32 immediate_data_size, const gles2::Uniform3ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLint* v = GetImmediateDataAs<const GLint*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 3); + const GLint* v = GetImmediateDataAs<const GLint*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform3ivImmediate>( - immediate_data_size, count, sizeof(GLint), 3)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform3ivImmediate>( - immediate_data_size, count, sizeof(GLint), 3)) { - return parse_error::kParseOutOfBounds; - } glUniform3iv(location, count, v); return parse_error::kParseNoError; } @@ -2002,8 +1881,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform4fv( uint32 immediate_data_size, const gles2::Uniform4fv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 4); const GLfloat* v = GetSharedMemoryAs<const GLfloat*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -2015,22 +1896,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform4fvImmediate( uint32 immediate_data_size, const gles2::Uniform4fvImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLfloat* v = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 4); + const GLfloat* v = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform4fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 4)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform4fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 4)) { - return parse_error::kParseOutOfBounds; - } glUniform4fv(location, count, v); return parse_error::kParseNoError; } @@ -2050,8 +1922,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform4iv( uint32 immediate_data_size, const gles2::Uniform4iv& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 4); const GLint* v = GetSharedMemoryAs<const GLint*>( - c.v_shm_id, c.v_shm_offset, 0 /* TODO(gman): size */); + c.v_shm_id, c.v_shm_offset, data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } @@ -2063,22 +1937,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniform4ivImmediate( uint32 immediate_data_size, const gles2::Uniform4ivImmediate& c) { GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); - const GLint* v = GetImmediateDataAs<const GLint*>(c); - if (v == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<Uniform4ivImmediate>( - immediate_data_size, count, sizeof(GLint), 4)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLint), 4); + const GLint* v = GetImmediateDataAs<const GLint*>( + c, data_size, immediate_data_size); if (v == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<Uniform4ivImmediate>( - immediate_data_size, count, sizeof(GLint), 4)) { - return parse_error::kParseOutOfBounds; - } glUniform4iv(location, count, v); return parse_error::kParseNoError; } @@ -2088,8 +1953,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix2fv( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 4); const GLfloat* value = GetSharedMemoryAs<const GLfloat*>( - c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */); + c.value_shm_id, c.value_shm_offset, data_size); if (value == NULL) { return parse_error::kParseOutOfBounds; } @@ -2102,22 +1969,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix2fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 4); + const GLfloat* value = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (value == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<UniformMatrix2fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 4)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (value == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<UniformMatrix2fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 4)) { - return parse_error::kParseOutOfBounds; - } glUniformMatrix2fv(location, count, transpose, value); return parse_error::kParseNoError; } @@ -2127,8 +1985,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix3fv( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 9); const GLfloat* value = GetSharedMemoryAs<const GLfloat*>( - c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */); + c.value_shm_id, c.value_shm_offset, data_size); if (value == NULL) { return parse_error::kParseOutOfBounds; } @@ -2141,22 +2001,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix3fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 9); + const GLfloat* value = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (value == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<UniformMatrix3fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 9)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (value == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<UniformMatrix3fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 9)) { - return parse_error::kParseOutOfBounds; - } glUniformMatrix3fv(location, count, transpose, value); return parse_error::kParseNoError; } @@ -2166,8 +2017,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix4fv( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 16); const GLfloat* value = GetSharedMemoryAs<const GLfloat*>( - c.value_shm_id, c.value_shm_offset, 0 /* TODO(gman): size */); + c.value_shm_id, c.value_shm_offset, data_size); if (value == NULL) { return parse_error::kParseOutOfBounds; } @@ -2180,22 +2033,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleUniformMatrix4fvImmediate( GLint location = static_cast<GLint>(c.location); GLsizei count = static_cast<GLsizei>(c.count); GLboolean transpose = static_cast<GLboolean>(c.transpose); - const GLfloat* value = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 16); + const GLfloat* value = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (value == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<UniformMatrix4fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 16)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (value == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<UniformMatrix4fvImmediate>( - immediate_data_size, count, sizeof(GLfloat), 16)) { - return parse_error::kParseOutOfBounds; - } glUniformMatrix4fv(location, count, transpose, value); return parse_error::kParseNoError; } @@ -2207,7 +2051,7 @@ parse_error::ParseError GLES2DecoderImpl::HandleUseProgram( SetGLError(GL_INVALID_VALUE); return parse_error::kParseNoError; } - glUseProgram(program); + DoUseProgram(program); return parse_error::kParseNoError; } @@ -2233,8 +2077,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1f( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fv( uint32 immediate_data_size, const gles2::VertexAttrib1fv& c) { GLuint indx = static_cast<GLuint>(c.indx); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 1); const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */); + c.values_shm_id, c.values_shm_offset, data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } @@ -2245,22 +2091,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fv( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib1fvImmediate( uint32 immediate_data_size, const gles2::VertexAttrib1fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 1); + const GLfloat* values = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<VertexAttrib1fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 1)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (values == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<VertexAttrib1fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 1)) { - return parse_error::kParseOutOfBounds; - } glVertexAttrib1fv(indx, values); return parse_error::kParseNoError; } @@ -2277,8 +2114,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2f( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fv( uint32 immediate_data_size, const gles2::VertexAttrib2fv& c) { GLuint indx = static_cast<GLuint>(c.indx); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 2); const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */); + c.values_shm_id, c.values_shm_offset, data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } @@ -2289,22 +2128,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fv( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib2fvImmediate( uint32 immediate_data_size, const gles2::VertexAttrib2fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 2); + const GLfloat* values = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<VertexAttrib2fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 2)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (values == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<VertexAttrib2fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 2)) { - return parse_error::kParseOutOfBounds; - } glVertexAttrib2fv(indx, values); return parse_error::kParseNoError; } @@ -2322,8 +2152,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3f( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fv( uint32 immediate_data_size, const gles2::VertexAttrib3fv& c) { GLuint indx = static_cast<GLuint>(c.indx); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 3); const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */); + c.values_shm_id, c.values_shm_offset, data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } @@ -2334,22 +2166,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fv( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib3fvImmediate( uint32 immediate_data_size, const gles2::VertexAttrib3fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 3); + const GLfloat* values = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<VertexAttrib3fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 3)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (values == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<VertexAttrib3fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 3)) { - return parse_error::kParseOutOfBounds; - } glVertexAttrib3fv(indx, values); return parse_error::kParseNoError; } @@ -2368,8 +2191,10 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4f( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fv( uint32 immediate_data_size, const gles2::VertexAttrib4fv& c) { GLuint indx = static_cast<GLuint>(c.indx); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 4); const GLfloat* values = GetSharedMemoryAs<const GLfloat*>( - c.values_shm_id, c.values_shm_offset, 0 /* TODO(gman): size */); + c.values_shm_id, c.values_shm_offset, data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } @@ -2380,22 +2205,13 @@ parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fv( parse_error::ParseError GLES2DecoderImpl::HandleVertexAttrib4fvImmediate( uint32 immediate_data_size, const gles2::VertexAttrib4fvImmediate& c) { GLuint indx = static_cast<GLuint>(c.indx); - const GLfloat* values = GetImmediateDataAs<const GLfloat*>(c); + uint32 data_size = + ComputeImmediateDataSize(immediate_data_size, 1, sizeof(GLfloat), 4); + const GLfloat* values = GetImmediateDataAs<const GLfloat*>( + c, data_size, immediate_data_size); if (values == NULL) { return parse_error::kParseOutOfBounds; } - if (!CheckImmediateDataSize<VertexAttrib4fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 4)) { - return parse_error::kParseOutOfBounds; - } - // Immediate version. - if (values == NULL) { - return parse_error::kParseOutOfBounds; - } - if (!CheckImmediateDataSize<VertexAttrib4fvImmediate>( - immediate_data_size, 1, sizeof(GLfloat), 4)) { - return parse_error::kParseOutOfBounds; - } glVertexAttrib4fv(indx, values); return parse_error::kParseNoError; } |