OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <limits.h> | 7 #include <limits.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
(...skipping 1356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1367 | 1367 |
1368 // Checks if a draw buffer's format and its corresponding fragment shader | 1368 // Checks if a draw buffer's format and its corresponding fragment shader |
1369 // output's type are compatible, i.e., a signed integer typed variable is | 1369 // output's type are compatible, i.e., a signed integer typed variable is |
1370 // incompatible with a float or unsigned integer buffer. | 1370 // incompatible with a float or unsigned integer buffer. |
1371 // If incompaticle, generates an INVALID_OPERATION to avoid undefined buffer | 1371 // If incompaticle, generates an INVALID_OPERATION to avoid undefined buffer |
1372 // contents and return false. | 1372 // contents and return false. |
1373 // Otherwise, filter out the draw buffers that are not written to but are not | 1373 // Otherwise, filter out the draw buffers that are not written to but are not |
1374 // NONE through DrawBuffers, to be on the safe side. Return true. | 1374 // NONE through DrawBuffers, to be on the safe side. Return true. |
1375 bool ValidateAndAdjustDrawBuffers(const char* function_name); | 1375 bool ValidateAndAdjustDrawBuffers(const char* function_name); |
1376 | 1376 |
| 1377 // Checks if all active uniform blocks in the current program are backed by |
| 1378 // a buffer of sufficient size. |
| 1379 // If not, generates an INVALID_OPERATION to avoid undefined behavior in |
| 1380 // shader execution and return false. |
| 1381 bool ValidateUniformBlockBackings(const char* function_name); |
| 1382 |
1377 // Checks if |api_type| is valid for the given uniform | 1383 // Checks if |api_type| is valid for the given uniform |
1378 // If the api type is not valid generates the appropriate GL | 1384 // If the api type is not valid generates the appropriate GL |
1379 // error. Returns true if |api_type| is valid for the uniform | 1385 // error. Returns true if |api_type| is valid for the uniform |
1380 bool CheckUniformForApiType(const Program::UniformInfo* info, | 1386 bool CheckUniformForApiType(const Program::UniformInfo* info, |
1381 const char* function_name, | 1387 const char* function_name, |
1382 Program::UniformApiType api_type); | 1388 Program::UniformApiType api_type); |
1383 | 1389 |
1384 // Gets the type of a uniform for a location in the current program. Sets GL | 1390 // Gets the type of a uniform for a location in the current program. Sets GL |
1385 // errors if the current program is not valid. Returns true if the current | 1391 // errors if the current program is not valid. Returns true if the current |
1386 // program is valid and the location exists. Adjusts count so it | 1392 // program is valid and the location exists. Adjusts count so it |
(...skipping 6675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8062 state_.current_program->fragment_output_written_mask(); | 8068 state_.current_program->fragment_output_written_mask(); |
8063 if (!framebuffer->ValidateAndAdjustDrawBuffers( | 8069 if (!framebuffer->ValidateAndAdjustDrawBuffers( |
8064 fragment_output_type_mask, fragment_output_written_mask)) { | 8070 fragment_output_type_mask, fragment_output_written_mask)) { |
8065 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, | 8071 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, |
8066 "buffer format and fragment output variable type incompatible"); | 8072 "buffer format and fragment output variable type incompatible"); |
8067 return false; | 8073 return false; |
8068 } | 8074 } |
8069 return true; | 8075 return true; |
8070 } | 8076 } |
8071 | 8077 |
| 8078 bool GLES2DecoderImpl::ValidateUniformBlockBackings(const char* func_name) { |
| 8079 switch (feature_info_->context_type()) { |
| 8080 case CONTEXT_TYPE_OPENGLES2: |
| 8081 case CONTEXT_TYPE_WEBGL1: |
| 8082 // Uniform blocks do not exist in ES2 contexts. |
| 8083 return true; |
| 8084 default: |
| 8085 break; |
| 8086 } |
| 8087 DCHECK(state_.current_program.get()); |
| 8088 for (auto info : state_.current_program->uniform_block_size_info()) { |
| 8089 uint32_t buffer_size = static_cast<uint32_t>( |
| 8090 state_.indexed_uniform_buffer_bindings->GetEffectiveBufferSize( |
| 8091 info.binding)); |
| 8092 if (info.data_size > buffer_size) { |
| 8093 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, |
| 8094 "uniform blocks are not backed by a buffer with sufficient data"); |
| 8095 return false; |
| 8096 } |
| 8097 } |
| 8098 return true; |
| 8099 } |
| 8100 |
8072 bool GLES2DecoderImpl::CheckUniformForApiType( | 8101 bool GLES2DecoderImpl::CheckUniformForApiType( |
8073 const Program::UniformInfo* info, | 8102 const Program::UniformInfo* info, |
8074 const char* function_name, | 8103 const char* function_name, |
8075 Program::UniformApiType api_type) { | 8104 Program::UniformApiType api_type) { |
8076 DCHECK(info); | 8105 DCHECK(info); |
8077 if ((api_type & info->accepts_api_type) == 0) { | 8106 if ((api_type & info->accepts_api_type) == 0) { |
8078 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, | 8107 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, |
8079 "wrong uniform function for type"); | 8108 "wrong uniform function for type"); |
8080 return false; | 8109 return false; |
8081 } | 8110 } |
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9092 } | 9121 } |
9093 bool simulated_fixed_attribs = false; | 9122 bool simulated_fixed_attribs = false; |
9094 if (SimulateFixedAttribs( | 9123 if (SimulateFixedAttribs( |
9095 function_name, max_vertex_accessed, &simulated_fixed_attribs, | 9124 function_name, max_vertex_accessed, &simulated_fixed_attribs, |
9096 primcount)) { | 9125 primcount)) { |
9097 bool textures_set = !PrepareTexturesForRender(); | 9126 bool textures_set = !PrepareTexturesForRender(); |
9098 ApplyDirtyState(); | 9127 ApplyDirtyState(); |
9099 if (!ValidateAndAdjustDrawBuffers(function_name)) { | 9128 if (!ValidateAndAdjustDrawBuffers(function_name)) { |
9100 return error::kNoError; | 9129 return error::kNoError; |
9101 } | 9130 } |
| 9131 if (!ValidateUniformBlockBackings(function_name)) { |
| 9132 return error::kNoError; |
| 9133 } |
9102 if (!instanced) { | 9134 if (!instanced) { |
9103 glDrawArrays(mode, first, count); | 9135 glDrawArrays(mode, first, count); |
9104 } else { | 9136 } else { |
9105 glDrawArraysInstancedANGLE(mode, first, count, primcount); | 9137 glDrawArraysInstancedANGLE(mode, first, count, primcount); |
9106 } | 9138 } |
9107 if (textures_set) { | 9139 if (textures_set) { |
9108 RestoreStateForTextures(); | 9140 RestoreStateForTextures(); |
9109 } | 9141 } |
9110 if (simulated_fixed_attribs) { | 9142 if (simulated_fixed_attribs) { |
9111 RestoreStateForSimulatedFixedAttribs(); | 9143 RestoreStateForSimulatedFixedAttribs(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9236 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset); | 9268 const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset); |
9237 bool used_client_side_array = false; | 9269 bool used_client_side_array = false; |
9238 if (element_array_buffer->IsClientSideArray()) { | 9270 if (element_array_buffer->IsClientSideArray()) { |
9239 used_client_side_array = true; | 9271 used_client_side_array = true; |
9240 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); | 9272 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
9241 indices = element_array_buffer->GetRange(offset, 0); | 9273 indices = element_array_buffer->GetRange(offset, 0); |
9242 } | 9274 } |
9243 if (!ValidateAndAdjustDrawBuffers(function_name)) { | 9275 if (!ValidateAndAdjustDrawBuffers(function_name)) { |
9244 return error::kNoError; | 9276 return error::kNoError; |
9245 } | 9277 } |
| 9278 if (!ValidateUniformBlockBackings(function_name)) { |
| 9279 return error::kNoError; |
| 9280 } |
9246 if (state_.enable_flags.primitive_restart_fixed_index && | 9281 if (state_.enable_flags.primitive_restart_fixed_index && |
9247 feature_info_->feature_flags(). | 9282 feature_info_->feature_flags(). |
9248 emulate_primitive_restart_fixed_index) { | 9283 emulate_primitive_restart_fixed_index) { |
9249 glEnable(GL_PRIMITIVE_RESTART); | 9284 glEnable(GL_PRIMITIVE_RESTART); |
9250 buffer_manager()->SetPrimitiveRestartFixedIndexIfNecessary(type); | 9285 buffer_manager()->SetPrimitiveRestartFixedIndexIfNecessary(type); |
9251 } | 9286 } |
9252 if (!instanced) { | 9287 if (!instanced) { |
9253 glDrawElements(mode, count, type, indices); | 9288 glDrawElements(mode, count, type, indices); |
9254 } else { | 9289 } else { |
9255 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount); | 9290 glDrawElementsInstancedANGLE(mode, count, type, indices, primcount); |
(...skipping 6649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15905 ? state_.projection_matrix | 15940 ? state_.projection_matrix |
15906 : state_.modelview_matrix; | 15941 : state_.modelview_matrix; |
15907 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix)); | 15942 memcpy(target_matrix, kIdentityMatrix, sizeof(kIdentityMatrix)); |
15908 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV | 15943 // The matrix_mode is either GL_PATH_MODELVIEW_NV or GL_PATH_PROJECTION_NV |
15909 // since the values of the _NV and _CHROMIUM tokens match. | 15944 // since the values of the _NV and _CHROMIUM tokens match. |
15910 glMatrixLoadIdentityEXT(matrix_mode); | 15945 glMatrixLoadIdentityEXT(matrix_mode); |
15911 } | 15946 } |
15912 | 15947 |
15913 error::Error GLES2DecoderImpl::HandleUniformBlockBinding( | 15948 error::Error GLES2DecoderImpl::HandleUniformBlockBinding( |
15914 uint32_t immediate_data_size, const void* cmd_data) { | 15949 uint32_t immediate_data_size, const void* cmd_data) { |
| 15950 const char* func_name = "glUniformBlockBinding"; |
15915 if (!unsafe_es3_apis_enabled()) | 15951 if (!unsafe_es3_apis_enabled()) |
15916 return error::kUnknownCommand; | 15952 return error::kUnknownCommand; |
15917 const gles2::cmds::UniformBlockBinding& c = | 15953 const gles2::cmds::UniformBlockBinding& c = |
15918 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data); | 15954 *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data); |
15919 GLuint client_id = c.program; | 15955 GLuint client_id = c.program; |
15920 GLuint index = static_cast<GLuint>(c.index); | 15956 GLuint index = static_cast<GLuint>(c.index); |
15921 GLuint binding = static_cast<GLuint>(c.binding); | 15957 GLuint binding = static_cast<GLuint>(c.binding); |
15922 Program* program = GetProgramInfoNotShader( | 15958 Program* program = GetProgramInfoNotShader(client_id, func_name); |
15923 client_id, "glUniformBlockBinding"); | |
15924 if (!program) { | 15959 if (!program) { |
15925 return error::kNoError; | 15960 return error::kNoError; |
15926 } | 15961 } |
| 15962 if (index >= program->uniform_block_size_info().size()) { |
| 15963 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, |
| 15964 "uniformBlockIndex is not an active uniform block index"); |
| 15965 return error::kNoError; |
| 15966 } |
| 15967 if (binding >= group_->max_uniform_buffer_bindings()) { |
| 15968 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, |
| 15969 "uniformBlockBinding >= MAX_UNIFORM_BUFFER_BINDINGS"); |
| 15970 return error::kNoError; |
| 15971 } |
15927 GLuint service_id = program->service_id(); | 15972 GLuint service_id = program->service_id(); |
15928 glUniformBlockBinding(service_id, index, binding); | 15973 glUniformBlockBinding(service_id, index, binding); |
| 15974 program->SetUniformBlockBinding(index, binding); |
15929 return error::kNoError; | 15975 return error::kNoError; |
15930 } | 15976 } |
15931 | 15977 |
15932 error::Error GLES2DecoderImpl::HandleClientWaitSync( | 15978 error::Error GLES2DecoderImpl::HandleClientWaitSync( |
15933 uint32_t immediate_data_size, const void* cmd_data) { | 15979 uint32_t immediate_data_size, const void* cmd_data) { |
15934 const char* function_name = "glClientWaitSync"; | 15980 const char* function_name = "glClientWaitSync"; |
15935 if (!unsafe_es3_apis_enabled()) | 15981 if (!unsafe_es3_apis_enabled()) |
15936 return error::kUnknownCommand; | 15982 return error::kUnknownCommand; |
15937 const gles2::cmds::ClientWaitSync& c = | 15983 const gles2::cmds::ClientWaitSync& c = |
15938 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data); | 15984 *static_cast<const gles2::cmds::ClientWaitSync*>(cmd_data); |
(...skipping 1466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17405 } | 17451 } |
17406 | 17452 |
17407 // Include the auto-generated part of this file. We split this because it means | 17453 // Include the auto-generated part of this file. We split this because it means |
17408 // we can easily edit the non-auto generated parts right here in this file | 17454 // we can easily edit the non-auto generated parts right here in this file |
17409 // instead of having to edit some template or the code generator. | 17455 // instead of having to edit some template or the code generator. |
17410 #include "base/macros.h" | 17456 #include "base/macros.h" |
17411 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 17457 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
17412 | 17458 |
17413 } // namespace gles2 | 17459 } // namespace gles2 |
17414 } // namespace gpu | 17460 } // namespace gpu |
OLD | NEW |