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 <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <list> | 10 #include <list> |
(...skipping 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 bool client_visible) { | 1156 bool client_visible) { |
1157 return vertex_array_manager()->CreateVertexAttribManager( | 1157 return vertex_array_manager()->CreateVertexAttribManager( |
1158 client_id, service_id, group_->max_vertex_attribs(), client_visible); | 1158 client_id, service_id, group_->max_vertex_attribs(), client_visible); |
1159 } | 1159 } |
1160 | 1160 |
1161 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name); | 1161 void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name); |
1162 void DoBindUniformLocationCHROMIUM( | 1162 void DoBindUniformLocationCHROMIUM( |
1163 GLuint client_id, GLint location, const char* name); | 1163 GLuint client_id, GLint location, const char* name); |
1164 | 1164 |
1165 error::Error GetAttribLocationHelper( | 1165 error::Error GetAttribLocationHelper( |
1166 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, | 1166 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
1167 const std::string& name_str); | 1167 const std::string& name_str); |
1168 | 1168 |
1169 error::Error GetUniformLocationHelper( | 1169 error::Error GetUniformLocationHelper( |
1170 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, | 1170 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
1171 const std::string& name_str); | 1171 const std::string& name_str); |
1172 | 1172 |
1173 error::Error GetFragDataLocationHelper( | 1173 error::Error GetFragDataLocationHelper( |
1174 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, | 1174 GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
1175 const std::string& name_str); | 1175 const std::string& name_str); |
1176 | 1176 |
1177 // Wrapper for glShaderSource. | 1177 // Wrapper for glShaderSource. |
1178 void DoShaderSource( | 1178 void DoShaderSource( |
1179 GLuint client_id, GLsizei count, const char** data, const GLint* length); | 1179 GLuint client_id, GLsizei count, const char** data, const GLint* length); |
1180 | 1180 |
1181 // Wrapper for glTransformFeedbackVaryings. | 1181 // Wrapper for glTransformFeedbackVaryings. |
1182 void DoTransformFeedbackVaryings( | 1182 void DoTransformFeedbackVaryings( |
1183 GLuint client_program_id, GLsizei count, const char* const* varyings, | 1183 GLuint client_program_id, GLsizei count, const char* const* varyings, |
1184 GLenum buffer_mode); | 1184 GLenum buffer_mode); |
1185 | 1185 |
(...skipping 1649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2835 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs); | 2835 DoGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.max_vertex_attribs); |
2836 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, | 2836 DoGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, |
2837 &caps.max_vertex_texture_image_units); | 2837 &caps.max_vertex_texture_image_units); |
2838 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, | 2838 DoGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, |
2839 &caps.max_vertex_uniform_vectors); | 2839 &caps.max_vertex_uniform_vectors); |
2840 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, | 2840 DoGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, |
2841 &caps.num_compressed_texture_formats); | 2841 &caps.num_compressed_texture_formats); |
2842 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats); | 2842 DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats); |
2843 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, | 2843 DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, |
2844 &caps.bind_generates_resource_chromium); | 2844 &caps.bind_generates_resource_chromium); |
| 2845 if (unsafe_es3_apis_enabled()) { |
| 2846 DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, |
| 2847 &caps.max_transform_feedback_separate_attribs); |
| 2848 DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, |
| 2849 &caps.max_uniform_buffer_bindings); |
| 2850 DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, |
| 2851 &caps.uniform_buffer_offset_alignment); |
| 2852 } |
2845 | 2853 |
2846 caps.egl_image_external = | 2854 caps.egl_image_external = |
2847 feature_info_->feature_flags().oes_egl_image_external; | 2855 feature_info_->feature_flags().oes_egl_image_external; |
2848 caps.texture_format_bgra8888 = | 2856 caps.texture_format_bgra8888 = |
2849 feature_info_->feature_flags().ext_texture_format_bgra8888; | 2857 feature_info_->feature_flags().ext_texture_format_bgra8888; |
2850 caps.texture_format_etc1 = | 2858 caps.texture_format_etc1 = |
2851 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture; | 2859 feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture; |
2852 caps.texture_format_etc1_npot = | 2860 caps.texture_format_etc1_npot = |
2853 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only; | 2861 caps.texture_format_etc1 && !workarounds().etc1_power_of_two_only; |
2854 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle; | 2862 caps.texture_rectangle = feature_info_->feature_flags().arb_texture_rectangle; |
(...skipping 4189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7044 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer"); | 7052 "GetMaxValueInBufferCHROMIUM", "range out of bounds for buffer"); |
7045 } | 7053 } |
7046 } | 7054 } |
7047 return max_vertex_accessed; | 7055 return max_vertex_accessed; |
7048 } | 7056 } |
7049 | 7057 |
7050 void GLES2DecoderImpl::DoShaderSource( | 7058 void GLES2DecoderImpl::DoShaderSource( |
7051 GLuint client_id, GLsizei count, const char** data, const GLint* length) { | 7059 GLuint client_id, GLsizei count, const char** data, const GLint* length) { |
7052 std::string str; | 7060 std::string str; |
7053 for (GLsizei ii = 0; ii < count; ++ii) { | 7061 for (GLsizei ii = 0; ii < count; ++ii) { |
7054 str.append(data[ii]); | 7062 if (length && length[ii] > 0) |
| 7063 str.append(data[ii], length[ii]); |
| 7064 else |
| 7065 str.append(data[ii]); |
7055 } | 7066 } |
7056 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource"); | 7067 Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource"); |
7057 if (!shader) { | 7068 if (!shader) { |
7058 return; | 7069 return; |
7059 } | 7070 } |
7060 // Note: We don't actually call glShaderSource here. We wait until | 7071 // Note: We don't actually call glShaderSource here. We wait until |
7061 // the call to glCompileShader. | 7072 // we actually compile the shader. |
7062 shader->set_source(str); | 7073 shader->set_source(str); |
7063 } | 7074 } |
7064 | 7075 |
7065 void GLES2DecoderImpl::DoTransformFeedbackVaryings( | 7076 void GLES2DecoderImpl::DoTransformFeedbackVaryings( |
7066 GLuint client_program_id, GLsizei count, const char* const* varyings, | 7077 GLuint client_program_id, GLsizei count, const char* const* varyings, |
7067 GLenum buffer_mode) { | 7078 GLenum buffer_mode) { |
7068 Program* program = GetProgramInfoNotShader( | 7079 Program* program = GetProgramInfoNotShader( |
7069 client_program_id, "glTransformFeedbackVaryings"); | 7080 client_program_id, "glTransformFeedbackVaryings"); |
7070 if (!program) { | 7081 if (!program) { |
7071 return; | 7082 return; |
7072 } | 7083 } |
7073 glTransformFeedbackVaryings( | 7084 glTransformFeedbackVaryings( |
7074 program->service_id(), count, varyings, buffer_mode); | 7085 program->service_id(), count, varyings, buffer_mode); |
7075 } | 7086 } |
7076 | 7087 |
7077 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) { | 7088 void GLES2DecoderImpl::DoCompileShader(GLuint client_id) { |
7078 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader"); | 7089 TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCompileShader"); |
7079 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader"); | 7090 Shader* shader = GetShaderInfoNotProgram(client_id, "glCompileShader"); |
7080 if (!shader) { | 7091 if (!shader) { |
7081 return; | 7092 return; |
7082 } | 7093 } |
7083 ShaderTranslator* translator = NULL; | 7094 ShaderTranslator* translator = NULL; |
7084 if (use_shader_translator_) { | 7095 if (use_shader_translator_) { |
7085 translator = shader->shader_type() == GL_VERTEX_SHADER ? | 7096 translator = shader->shader_type() == GL_VERTEX_SHADER ? |
7086 vertex_translator_.get() : fragment_translator_.get(); | 7097 vertex_translator_.get() : fragment_translator_.get(); |
7087 } | 7098 } |
7088 | 7099 |
| 7100 shader->RequestCompile(); |
| 7101 |
| 7102 // TODO(dyen): Currently we compile immediately when glCompileShader is |
| 7103 // requested. Eventually this should be deffered to the linker stage. |
7089 shader->DoCompile( | 7104 shader->DoCompile( |
7090 translator, | 7105 translator, |
7091 feature_info_->feature_flags().angle_translated_shader_source ? | 7106 feature_info_->feature_flags().angle_translated_shader_source ? |
7092 Shader::kANGLE : Shader::kGL); | 7107 Shader::kANGLE : Shader::kGL); |
7093 | 7108 |
7094 // CompileShader can be very slow. Exit command processing to allow for | 7109 // CompileShader can be very slow. Exit command processing to allow for |
7095 // context preemption and GPU watchdog checks. | 7110 // context preemption and GPU watchdog checks. |
7096 ExitCommandProcessingEarly(); | 7111 ExitCommandProcessingEarly(); |
7097 } | 7112 } |
7098 | 7113 |
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8179 return error::kInvalidArguments; | 8194 return error::kInvalidArguments; |
8180 } | 8195 } |
8181 std::string name_str; | 8196 std::string name_str; |
8182 if (!bucket->GetAsString(&name_str)) { | 8197 if (!bucket->GetAsString(&name_str)) { |
8183 return error::kInvalidArguments; | 8198 return error::kInvalidArguments; |
8184 } | 8199 } |
8185 return GetFragDataLocationHelper( | 8200 return GetFragDataLocationHelper( |
8186 c.program, c.location_shm_id, c.location_shm_offset, name_str); | 8201 c.program, c.location_shm_id, c.location_shm_offset, name_str); |
8187 } | 8202 } |
8188 | 8203 |
| 8204 error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex( |
| 8205 uint32 immediate_data_size, const void* cmd_data) { |
| 8206 if (!unsafe_es3_apis_enabled()) |
| 8207 return error::kUnknownCommand; |
| 8208 const gles2::cmds::GetUniformBlockIndex& c = |
| 8209 *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data); |
| 8210 Bucket* bucket = GetBucket(c.name_bucket_id); |
| 8211 if (!bucket) { |
| 8212 return error::kInvalidArguments; |
| 8213 } |
| 8214 std::string name_str; |
| 8215 if (!bucket->GetAsString(&name_str)) { |
| 8216 return error::kInvalidArguments; |
| 8217 } |
| 8218 GLuint* index = GetSharedMemoryAs<GLuint*>( |
| 8219 c.index_shm_id, c.index_shm_offset, sizeof(GLuint)); |
| 8220 if (!index) { |
| 8221 return error::kOutOfBounds; |
| 8222 } |
| 8223 // Require the client to init this in case the context is lost and we are no |
| 8224 // longer executing commands. |
| 8225 if (*index != GL_INVALID_INDEX) { |
| 8226 return error::kGenericError; |
| 8227 } |
| 8228 Program* program = GetProgramInfoNotShader( |
| 8229 c.program, "glGetUniformBlockIndex"); |
| 8230 if (!program) { |
| 8231 return error::kNoError; |
| 8232 } |
| 8233 *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str()); |
| 8234 return error::kNoError; |
| 8235 } |
| 8236 |
8189 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, | 8237 error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, |
8190 const void* cmd_data) { | 8238 const void* cmd_data) { |
8191 const gles2::cmds::GetString& c = | 8239 const gles2::cmds::GetString& c = |
8192 *static_cast<const gles2::cmds::GetString*>(cmd_data); | 8240 *static_cast<const gles2::cmds::GetString*>(cmd_data); |
8193 GLenum name = static_cast<GLenum>(c.name); | 8241 GLenum name = static_cast<GLenum>(c.name); |
8194 if (!validators_->string_type.IsValid(name)) { | 8242 if (!validators_->string_type.IsValid(name)) { |
8195 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name"); | 8243 LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name"); |
8196 return error::kNoError; | 8244 return error::kNoError; |
8197 } | 8245 } |
8198 const char* str = reinterpret_cast<const char*>(glGetString(name)); | 8246 const char* str = reinterpret_cast<const char*>(glGetString(name)); |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9675 return error::kNoError; | 9723 return error::kNoError; |
9676 } | 9724 } |
9677 result->success = 1; // true. | 9725 result->success = 1; // true. |
9678 result->size = uniform_info->size; | 9726 result->size = uniform_info->size; |
9679 result->type = uniform_info->type; | 9727 result->type = uniform_info->type; |
9680 Bucket* bucket = CreateBucket(name_bucket_id); | 9728 Bucket* bucket = CreateBucket(name_bucket_id); |
9681 bucket->SetFromString(uniform_info->name.c_str()); | 9729 bucket->SetFromString(uniform_info->name.c_str()); |
9682 return error::kNoError; | 9730 return error::kNoError; |
9683 } | 9731 } |
9684 | 9732 |
| 9733 error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName( |
| 9734 uint32 immediate_data_size, const void* cmd_data) { |
| 9735 if (!unsafe_es3_apis_enabled()) |
| 9736 return error::kUnknownCommand; |
| 9737 const gles2::cmds::GetActiveUniformBlockName& c = |
| 9738 *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data); |
| 9739 GLuint program_id = c.program; |
| 9740 GLuint index = c.index; |
| 9741 uint32 name_bucket_id = c.name_bucket_id; |
| 9742 typedef cmds::GetActiveUniformBlockName::Result Result; |
| 9743 Result* result = GetSharedMemoryAs<Result*>( |
| 9744 c.result_shm_id, c.result_shm_offset, sizeof(*result)); |
| 9745 if (!result) { |
| 9746 return error::kOutOfBounds; |
| 9747 } |
| 9748 // Check that the client initialized the result. |
| 9749 if (*result != 0) { |
| 9750 return error::kInvalidArguments; |
| 9751 } |
| 9752 Program* program = GetProgramInfoNotShader( |
| 9753 program_id, "glGetActiveUniformBlockName"); |
| 9754 if (!program) { |
| 9755 return error::kNoError; |
| 9756 } |
| 9757 GLuint service_id = program->service_id(); |
| 9758 GLint link_status = GL_FALSE; |
| 9759 glGetProgramiv(service_id, GL_LINK_STATUS, &link_status); |
| 9760 if (link_status != GL_TRUE) { |
| 9761 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, |
| 9762 "glGetActiveActiveUniformBlockName", "program not linked"); |
| 9763 return error::kNoError; |
| 9764 } |
| 9765 GLint max_length = 0; |
| 9766 glGetProgramiv( |
| 9767 service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length); |
| 9768 // Increase one so &buffer[0] is always valid. |
| 9769 GLsizei buf_size = static_cast<GLsizei>(max_length) + 1; |
| 9770 std::vector<char> buffer(buf_size); |
| 9771 GLsizei length = 0; |
| 9772 glGetActiveUniformBlockName( |
| 9773 service_id, index, buf_size, &length, &buffer[0]); |
| 9774 if (length == 0) { |
| 9775 *result = 0; |
| 9776 return error::kNoError; |
| 9777 } |
| 9778 *result = 1; |
| 9779 Bucket* bucket = CreateBucket(name_bucket_id); |
| 9780 DCHECK_GT(buf_size, length); |
| 9781 DCHECK_EQ(0, buffer[length]); |
| 9782 bucket->SetFromString(&buffer[0]); |
| 9783 return error::kNoError; |
| 9784 } |
| 9785 |
9685 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size, | 9786 error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size, |
9686 const void* cmd_data) { | 9787 const void* cmd_data) { |
9687 const gles2::cmds::GetActiveAttrib& c = | 9788 const gles2::cmds::GetActiveAttrib& c = |
9688 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data); | 9789 *static_cast<const gles2::cmds::GetActiveAttrib*>(cmd_data); |
9689 GLuint program_id = c.program; | 9790 GLuint program_id = c.program; |
9690 GLuint index = c.index; | 9791 GLuint index = c.index; |
9691 uint32 name_bucket_id = c.name_bucket_id; | 9792 uint32 name_bucket_id = c.name_bucket_id; |
9692 typedef cmds::GetActiveAttrib::Result Result; | 9793 typedef cmds::GetActiveAttrib::Result Result; |
9693 Result* result = GetSharedMemoryAs<Result*>( | 9794 Result* result = GetSharedMemoryAs<Result*>( |
9694 c.result_shm_id, c.result_shm_offset, sizeof(*result)); | 9795 c.result_shm_id, c.result_shm_offset, sizeof(*result)); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10009 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail. | 10110 bucket->SetSize(sizeof(ProgramInfoHeader)); // in case we fail. |
10010 Program* program = NULL; | 10111 Program* program = NULL; |
10011 program = GetProgram(program_id); | 10112 program = GetProgram(program_id); |
10012 if (!program || !program->IsValid()) { | 10113 if (!program || !program->IsValid()) { |
10013 return error::kNoError; | 10114 return error::kNoError; |
10014 } | 10115 } |
10015 program->GetProgramInfo(program_manager(), bucket); | 10116 program->GetProgramInfo(program_manager(), bucket); |
10016 return error::kNoError; | 10117 return error::kNoError; |
10017 } | 10118 } |
10018 | 10119 |
| 10120 error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM( |
| 10121 uint32 immediate_data_size, const void* cmd_data) { |
| 10122 if (!unsafe_es3_apis_enabled()) |
| 10123 return error::kUnknownCommand; |
| 10124 const gles2::cmds::GetUniformBlocksCHROMIUM& c = |
| 10125 *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data); |
| 10126 GLuint program_id = static_cast<GLuint>(c.program); |
| 10127 uint32 bucket_id = c.bucket_id; |
| 10128 Bucket* bucket = CreateBucket(bucket_id); |
| 10129 bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail. |
| 10130 Program* program = NULL; |
| 10131 program = GetProgram(program_id); |
| 10132 if (!program || !program->IsValid()) { |
| 10133 return error::kNoError; |
| 10134 } |
| 10135 program->GetUniformBlocks(bucket); |
| 10136 return error::kNoError; |
| 10137 } |
| 10138 |
10019 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() { | 10139 error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() { |
10020 switch (reset_status_) { | 10140 switch (reset_status_) { |
10021 case GL_NO_ERROR: | 10141 case GL_NO_ERROR: |
10022 // TODO(kbr): improve the precision of the error code in this case. | 10142 // TODO(kbr): improve the precision of the error code in this case. |
10023 // Consider delegating to context for error code if MakeCurrent fails. | 10143 // Consider delegating to context for error code if MakeCurrent fails. |
10024 return error::kUnknown; | 10144 return error::kUnknown; |
10025 case GL_GUILTY_CONTEXT_RESET_ARB: | 10145 case GL_GUILTY_CONTEXT_RESET_ARB: |
10026 return error::kGuilty; | 10146 return error::kGuilty; |
10027 case GL_INNOCENT_CONTEXT_RESET_ARB: | 10147 case GL_INNOCENT_CONTEXT_RESET_ARB: |
10028 return error::kInnocent; | 10148 return error::kInnocent; |
(...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11668 } | 11788 } |
11669 } | 11789 } |
11670 | 11790 |
11671 // Include the auto-generated part of this file. We split this because it means | 11791 // Include the auto-generated part of this file. We split this because it means |
11672 // we can easily edit the non-auto generated parts right here in this file | 11792 // we can easily edit the non-auto generated parts right here in this file |
11673 // instead of having to edit some template or the code generator. | 11793 // instead of having to edit some template or the code generator. |
11674 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 11794 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
11675 | 11795 |
11676 } // namespace gles2 | 11796 } // namespace gles2 |
11677 } // namespace gpu | 11797 } // namespace gpu |
OLD | NEW |