| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 6 | 6 |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 // Check that certain assumptions the code makes are true. There are places in | 28 // Check that certain assumptions the code makes are true. There are places in |
| 29 // the code where shared memory is passed direclty to GL. Example, glUniformiv, | 29 // the code where shared memory is passed direclty to GL. Example, glUniformiv, |
| 30 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe | 30 // glShaderSource. The command buffer code assumes GLint and GLsizei (and maybe |
| 31 // a few others) are 32bits. If they are not 32bits the code will have to change | 31 // a few others) are 32bits. If they are not 32bits the code will have to change |
| 32 // to call those GL functions with service side memory and then copy the results | 32 // to call those GL functions with service side memory and then copy the results |
| 33 // to shared memory, converting the sizes. | 33 // to shared memory, converting the sizes. |
| 34 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT | 34 COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT |
| 35 GLint_not_same_size_as_uint32); | 35 GLint_not_same_size_as_uint32); |
| 36 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT | 36 COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT |
| 37 GLint_not_same_size_as_uint32); | 37 GLint_not_same_size_as_uint32); |
| 38 COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT |
| 39 GLfloat_not_same_size_as_float); |
| 38 | 40 |
| 39 namespace { | 41 namespace { |
| 40 | 42 |
| 41 size_t GetGLTypeSize(GLenum type) { | 43 size_t GetGLTypeSize(GLenum type) { |
| 42 switch (type) { | 44 switch (type) { |
| 43 case GL_BYTE: | 45 case GL_BYTE: |
| 44 return sizeof(GLbyte); // NOLINT | 46 return sizeof(GLbyte); // NOLINT |
| 45 case GL_UNSIGNED_BYTE: | 47 case GL_UNSIGNED_BYTE: |
| 46 return sizeof(GLubyte); // NOLINT | 48 return sizeof(GLubyte); // NOLINT |
| 47 case GL_SHORT: | 49 case GL_SHORT: |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 // | 304 // |
| 303 // NOTE: To support shared resources an instance of this class will | 305 // NOTE: To support shared resources an instance of this class will |
| 304 // need to be shared by multiple GLES2Decoders. | 306 // need to be shared by multiple GLES2Decoders. |
| 305 class ProgramManager { | 307 class ProgramManager { |
| 306 public: | 308 public: |
| 307 // This is used to track which attributes a particular program needs | 309 // This is used to track which attributes a particular program needs |
| 308 // so we can verify at glDrawXXX time that every attribute is either disabled | 310 // so we can verify at glDrawXXX time that every attribute is either disabled |
| 309 // or if enabled that it points to a valid source. | 311 // or if enabled that it points to a valid source. |
| 310 class ProgramInfo { | 312 class ProgramInfo { |
| 311 public: | 313 public: |
| 314 struct UniformInfo { |
| 315 GLsizei GetSizeInBytes() const; |
| 316 |
| 317 GLsizei size; |
| 318 GLenum type; |
| 319 GLint location; |
| 320 }; |
| 321 |
| 322 typedef std::vector<UniformInfo> UniformInfoVector; |
| 312 typedef std::vector<GLuint> AttribLocationVector; | 323 typedef std::vector<GLuint> AttribLocationVector; |
| 313 | 324 |
| 314 ProgramInfo() { | 325 ProgramInfo() { |
| 315 } | 326 } |
| 316 | 327 |
| 317 void SetNumAttributes(int num_attribs) { | 328 void SetNumAttributes(int num_attribs) { |
| 318 attrib_locations_.resize(num_attribs); | 329 attrib_locations_.resize(num_attribs); |
| 319 } | 330 } |
| 320 | 331 |
| 321 void SetAttributeLocation(GLuint index, int location) { | 332 void SetAttributeLocation(GLuint index, int location) { |
| 322 DCHECK(index < attrib_locations_.size()); | 333 DCHECK(index < attrib_locations_.size()); |
| 323 attrib_locations_[index] = location; | 334 attrib_locations_[index] = location; |
| 324 } | 335 } |
| 325 | 336 |
| 326 const AttribLocationVector& GetAttribLocations() const { | 337 const AttribLocationVector& GetAttribLocations() const { |
| 327 return attrib_locations_; | 338 return attrib_locations_; |
| 328 } | 339 } |
| 340 |
| 341 void SetNumUniforms(int num_uniforms) { |
| 342 uniform_infos_.resize(num_uniforms); |
| 343 } |
| 344 |
| 345 void SetUniformInfo( |
| 346 GLint index, GLsizei size, GLenum type, GLint location) { |
| 347 UniformInfo& info = uniform_infos_[index]; |
| 348 info.size = size; |
| 349 info.type = type; |
| 350 info.location = location; |
| 351 } |
| 352 |
| 353 const UniformInfo* GetUniformInfoByLocation(GLint location) { |
| 354 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { |
| 355 if (uniform_infos_[ii].location == location) { |
| 356 return &uniform_infos_[ii]; |
| 357 } |
| 358 } |
| 359 return NULL; |
| 360 } |
| 361 |
| 362 |
| 329 private: | 363 private: |
| 330 AttribLocationVector attrib_locations_; | 364 AttribLocationVector attrib_locations_; |
| 365 |
| 366 // Uniform info by info. |
| 367 UniformInfoVector uniform_infos_; |
| 331 }; | 368 }; |
| 332 | 369 |
| 333 ProgramInfo* GetProgramInfo(GLuint program); | 370 ProgramInfo* GetProgramInfo(GLuint program); |
| 334 | 371 |
| 335 // Updates the program info for the given program. | 372 // Updates the program info for the given program. |
| 336 void UpdateProgramInfo(GLuint program); | 373 void UpdateProgramInfo(GLuint program); |
| 337 | 374 |
| 338 // Deletes the program info for the given program. | 375 // Deletes the program info for the given program. |
| 339 void RemoveProgramInfo(GLuint program); | 376 void RemoveProgramInfo(GLuint program); |
| 340 | 377 |
| 341 private: | 378 private: |
| 342 // Info for each "successfully linked" program by service side program Id. | 379 // Info for each "successfully linked" program by service side program Id. |
| 343 // TODO(gman): Choose a faster container. | 380 // TODO(gman): Choose a faster container. |
| 344 typedef std::map<GLuint, ProgramInfo> ProgramInfoMap; | 381 typedef std::map<GLuint, ProgramInfo> ProgramInfoMap; |
| 345 ProgramInfoMap program_infos_; | 382 ProgramInfoMap program_infos_; |
| 346 }; | 383 }; |
| 347 | 384 |
| 385 GLsizei ProgramManager::ProgramInfo::UniformInfo::GetSizeInBytes() const { |
| 386 return GLES2Util::GetGLDataTypeSize(type) * size; |
| 387 } |
| 388 |
| 348 ProgramManager::ProgramInfo* ProgramManager::GetProgramInfo(GLuint program) { | 389 ProgramManager::ProgramInfo* ProgramManager::GetProgramInfo(GLuint program) { |
| 349 ProgramInfoMap::iterator it = program_infos_.find(program); | 390 ProgramInfoMap::iterator it = program_infos_.find(program); |
| 350 return it != program_infos_.end() ? &it->second : NULL; | 391 return it != program_infos_.end() ? &it->second : NULL; |
| 351 } | 392 } |
| 352 | 393 |
| 353 void ProgramManager::UpdateProgramInfo(GLuint program) { | 394 void ProgramManager::UpdateProgramInfo(GLuint program) { |
| 354 ProgramInfo* info = GetProgramInfo(program); | 395 ProgramInfo* info = GetProgramInfo(program); |
| 355 if (!info) { | 396 if (!info) { |
| 356 std::pair<ProgramInfoMap::iterator, bool> result = | 397 std::pair<ProgramInfoMap::iterator, bool> result = |
| 357 program_infos_.insert(std::make_pair(program, ProgramInfo())); | 398 program_infos_.insert(std::make_pair(program, ProgramInfo())); |
| 358 DCHECK(result.second); | 399 DCHECK(result.second); |
| 359 info = &result.first->second; | 400 info = &result.first->second; |
| 360 } | 401 } |
| 361 GLint num_attribs = 0; | 402 GLint num_attribs = 0; |
| 362 GLint max_len = 0; | 403 GLint max_len = 0; |
| 363 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &num_attribs); | 404 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &num_attribs); |
| 364 info->SetNumAttributes(num_attribs); | 405 info->SetNumAttributes(num_attribs); |
| 365 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); | 406 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); |
| 366 // TODO(gman): Should we check for error? | 407 // TODO(gman): Should we check for error? |
| 367 scoped_array<char> name_buffer(new char[max_len + 1]); | 408 scoped_array<char> name_buffer(new char[max_len]); |
| 368 for (GLint ii = 0; ii < num_attribs; ++ii) { | 409 for (GLint ii = 0; ii < num_attribs; ++ii) { |
| 369 GLsizei length; | 410 GLsizei length; |
| 370 GLsizei size; | 411 GLsizei size; |
| 371 GLenum type; | 412 GLenum type; |
| 372 glGetActiveAttrib( | 413 glGetActiveAttrib( |
| 373 program, ii, max_len + 1, &length, &size, &type, name_buffer.get()); | 414 program, ii, max_len, &length, &size, &type, name_buffer.get()); |
| 374 // TODO(gman): Should we check for error? | 415 // TODO(gman): Should we check for error? |
| 375 GLint location = glGetAttribLocation(program, name_buffer.get()); | 416 GLint location = glGetAttribLocation(program, name_buffer.get()); |
| 376 info->SetAttributeLocation(ii, location); | 417 info->SetAttributeLocation(ii, location); |
| 377 } | 418 } |
| 419 GLint num_uniforms; |
| 420 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &num_uniforms); |
| 421 info->SetNumUniforms(num_uniforms); |
| 422 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); |
| 423 name_buffer.reset(new char[max_len]); |
| 424 for (GLint ii = 0; ii < num_uniforms; ++ii) { |
| 425 GLsizei length; |
| 426 GLsizei size; |
| 427 GLenum type; |
| 428 glGetActiveUniform( |
| 429 program, ii, max_len, &length, &size, &type, name_buffer.get()); |
| 430 // TODO(gman): Should we check for error? |
| 431 GLint location = glGetUniformLocation(program, name_buffer.get()); |
| 432 info->SetUniformInfo(ii, size, type, location); |
| 433 } |
| 378 } | 434 } |
| 379 | 435 |
| 380 void ProgramManager::RemoveProgramInfo(GLuint program) { | 436 void ProgramManager::RemoveProgramInfo(GLuint program) { |
| 381 ProgramInfoMap::iterator it = program_infos_.find(program); | 437 ProgramInfoMap::iterator it = program_infos_.find(program); |
| 382 if (it != program_infos_.end()) { | 438 if (it != program_infos_.end()) { |
| 383 program_infos_.erase(it); | 439 program_infos_.erase(it); |
| 384 } | 440 } |
| 385 } | 441 } |
| 386 | 442 |
| 387 // This class implements GLES2Decoder so we don't have to expose all the GLES2 | 443 // This class implements GLES2Decoder so we don't have to expose all the GLES2 |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 // Checks if the current program and vertex attributes are valid for drawing. | 662 // Checks if the current program and vertex attributes are valid for drawing. |
| 607 bool IsDrawValid(GLuint max_vertex_accessed); | 663 bool IsDrawValid(GLuint max_vertex_accessed); |
| 608 | 664 |
| 609 // Gets the buffer id for a given target. | 665 // Gets the buffer id for a given target. |
| 610 GLuint GetBufferForTarget(GLenum target) { | 666 GLuint GetBufferForTarget(GLenum target) { |
| 611 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); | 667 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); |
| 612 return target == GL_ARRAY_BUFFER ? bound_array_buffer_ : | 668 return target == GL_ARRAY_BUFFER ? bound_array_buffer_ : |
| 613 bound_element_array_buffer_; | 669 bound_element_array_buffer_; |
| 614 } | 670 } |
| 615 | 671 |
| 672 // Validates the program and location for a glGetUniform call and returns |
| 673 // a SizeResult setup to receive the result. Returns true if glGetUniform |
| 674 // should be called. |
| 675 bool GetUniformSetup( |
| 676 GLuint program, GLint location, |
| 677 uint32 shm_id, uint32 shm_offset, |
| 678 error::Error* error, GLuint* service_id, SizedResult** result); |
| 679 |
| 616 // Generate a member function prototype for each command in an automated and | 680 // Generate a member function prototype for each command in an automated and |
| 617 // typesafe way. | 681 // typesafe way. |
| 618 #define GLES2_CMD_OP(name) \ | 682 #define GLES2_CMD_OP(name) \ |
| 619 Error Handle ## name( \ | 683 Error Handle ## name( \ |
| 620 uint32 immediate_data_size, \ | 684 uint32 immediate_data_size, \ |
| 621 const gles2::name& args); \ | 685 const gles2::name& args); \ |
| 622 | 686 |
| 623 GLES2_COMMAND_LIST(GLES2_CMD_OP) | 687 GLES2_COMMAND_LIST(GLES2_CMD_OP) |
| 624 | 688 |
| 625 #undef GLES2_CMD_OP | 689 #undef GLES2_CMD_OP |
| (...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 } | 1920 } |
| 1857 if (index >= max_vertex_attribs_) { | 1921 if (index >= max_vertex_attribs_) { |
| 1858 SetGLError(GL_INVALID_VALUE); | 1922 SetGLError(GL_INVALID_VALUE); |
| 1859 return error::kNoError; | 1923 return error::kNoError; |
| 1860 } | 1924 } |
| 1861 result->size = sizeof(GLuint); | 1925 result->size = sizeof(GLuint); |
| 1862 *result->GetDataAs<GLuint*>() = vertex_attrib_infos_[index].offset(); | 1926 *result->GetDataAs<GLuint*>() = vertex_attrib_infos_[index].offset(); |
| 1863 return error::kNoError; | 1927 return error::kNoError; |
| 1864 } | 1928 } |
| 1865 | 1929 |
| 1930 bool GLES2DecoderImpl::GetUniformSetup( |
| 1931 GLuint program, GLint location, |
| 1932 uint32 shm_id, uint32 shm_offset, |
| 1933 error::Error* error, GLuint* service_id, SizedResult** result) { |
| 1934 *error = error::kNoError; |
| 1935 // Make sure we have enough room for the result on failure. |
| 1936 *result = GetSharedMemoryAs<SizedResult*>( |
| 1937 shm_id, shm_offset, SizedResult::GetSize(0)); |
| 1938 if (!*result) { |
| 1939 *error = error::kOutOfBounds; |
| 1940 return false; |
| 1941 } |
| 1942 // Set the result size to 0 so the client does not have to check for success. |
| 1943 (*result)->size = 0; |
| 1944 if (!id_manager_->GetServiceId(program, service_id)) { |
| 1945 SetGLError(GL_INVALID_VALUE); |
| 1946 return error::kNoError; |
| 1947 } |
| 1948 ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id); |
| 1949 if (!info) { |
| 1950 // Program was not linked successfully. (ie, glLinkProgram) |
| 1951 SetGLError(GL_INVALID_OPERATION); |
| 1952 return false; |
| 1953 } |
| 1954 const ProgramManager::ProgramInfo::UniformInfo* uniform_info = |
| 1955 info->GetUniformInfoByLocation(location); |
| 1956 if (!uniform_info) { |
| 1957 // No such location. |
| 1958 SetGLError(GL_INVALID_OPERATION); |
| 1959 return false; |
| 1960 } |
| 1961 GLsizei size = uniform_info->GetSizeInBytes(); |
| 1962 if (size == 0) { |
| 1963 SetGLError(GL_INVALID_OPERATION); |
| 1964 return false; |
| 1965 } |
| 1966 *result = GetSharedMemoryAs<SizedResult*>( |
| 1967 shm_id, shm_offset, SizedResult::GetSize(size)); |
| 1968 if (!*result) { |
| 1969 *error = error::kOutOfBounds; |
| 1970 return false; |
| 1971 } |
| 1972 (*result)->size = size; |
| 1973 return true; |
| 1974 } |
| 1975 |
| 1866 error::Error GLES2DecoderImpl::HandleGetUniformiv( | 1976 error::Error GLES2DecoderImpl::HandleGetUniformiv( |
| 1867 uint32 immediate_data_size, const gles2::GetUniformiv& c) { | 1977 uint32 immediate_data_size, const gles2::GetUniformiv& c) { |
| 1868 // TODO(gman): Implement. | 1978 GLuint program = c.program; |
| 1869 NOTREACHED(); | 1979 GLint location = c.location; |
| 1870 return error::kNoError; | 1980 GLuint service_id; |
| 1981 Error error; |
| 1982 SizedResult* result; |
| 1983 if (GetUniformSetup( |
| 1984 program, location, c.params_shm_id, c.params_shm_offset, |
| 1985 &error, &service_id, &result)) { |
| 1986 glGetUniformiv(service_id, location, result->GetDataAs<GLint*>()); |
| 1987 } |
| 1988 return error; |
| 1871 } | 1989 } |
| 1872 | 1990 |
| 1873 error::Error GLES2DecoderImpl::HandleGetUniformfv( | 1991 error::Error GLES2DecoderImpl::HandleGetUniformfv( |
| 1874 uint32 immediate_data_size, const gles2::GetUniformfv& c) { | 1992 uint32 immediate_data_size, const gles2::GetUniformfv& c) { |
| 1875 // TODO(gman): Implement. | 1993 GLuint program = c.program; |
| 1876 NOTREACHED(); | 1994 GLint location = c.location; |
| 1877 return error::kNoError; | 1995 GLuint service_id; |
| 1996 Error error; |
| 1997 SizedResult* result; |
| 1998 if (GetUniformSetup( |
| 1999 program, location, c.params_shm_id, c.params_shm_offset, |
| 2000 &error, &service_id, &result)) { |
| 2001 glGetUniformfv(service_id, location, result->GetDataAs<GLfloat*>()); |
| 2002 } |
| 2003 return error; |
| 1878 } | 2004 } |
| 1879 | 2005 |
| 1880 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat( | 2006 error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat( |
| 1881 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) { | 2007 uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) { |
| 1882 // TODO(gman): Implement. | 2008 // TODO(gman): Implement. |
| 1883 NOTREACHED(); | 2009 NOTREACHED(); |
| 1884 return error::kNoError; | 2010 return error::kNoError; |
| 1885 } | 2011 } |
| 1886 | 2012 |
| 1887 error::Error GLES2DecoderImpl::HandleGetAttachedShaders( | 2013 error::Error GLES2DecoderImpl::HandleGetAttachedShaders( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1905 return error::kNoError; | 2031 return error::kNoError; |
| 1906 } | 2032 } |
| 1907 | 2033 |
| 1908 // Include the auto-generated part of this file. We split this because it means | 2034 // Include the auto-generated part of this file. We split this because it means |
| 1909 // we can easily edit the non-auto generated parts right here in this file | 2035 // we can easily edit the non-auto generated parts right here in this file |
| 1910 // instead of having to edit some template or the code generator. | 2036 // instead of having to edit some template or the code generator. |
| 1911 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 2037 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
| 1912 | 2038 |
| 1913 } // namespace gles2 | 2039 } // namespace gles2 |
| 1914 } // namespace gpu | 2040 } // namespace gpu |
| OLD | NEW |