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 |