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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 depth(_depth) {} | 159 depth(_depth) {} |
160 | 160 |
161 int xoffset; | 161 int xoffset; |
162 int yoffset; | 162 int yoffset; |
163 int zoffset; | 163 int zoffset; |
164 int width; | 164 int width; |
165 int height; | 165 int height; |
166 int depth; | 166 int depth; |
167 }; | 167 }; |
168 | 168 |
169 // Check if all |ref| bits are set in |bits|. | |
170 bool AllBitsSet(GLbitfield bits, GLbitfield ref) { | |
171 DCHECK_NE(0u, ref); | |
172 return ((bits & ref) == ref); | |
173 } | |
174 | |
175 // Check if any of |ref| bits are set in |bits|. | |
176 bool AnyBitsSet(GLbitfield bits, GLbitfield ref) { | |
177 DCHECK_NE(0u, ref); | |
178 return ((bits & ref) != 0); | |
179 } | |
180 | |
169 } // namespace | 181 } // namespace |
170 | 182 |
171 class GLES2DecoderImpl; | 183 class GLES2DecoderImpl; |
172 | 184 |
173 // Local versions of the SET_GL_ERROR macros | 185 // Local versions of the SET_GL_ERROR macros |
174 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \ | 186 #define LOCAL_SET_GL_ERROR(error, function_name, msg) \ |
175 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg) | 187 ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg) |
176 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \ | 188 #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \ |
177 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \ | 189 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), \ |
178 function_name, value, label) | 190 function_name, value, label) |
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1027 void DoLoseContextCHROMIUM(GLenum current, GLenum other); | 1039 void DoLoseContextCHROMIUM(GLenum current, GLenum other); |
1028 | 1040 |
1029 void DoFlushDriverCachesCHROMIUM(void); | 1041 void DoFlushDriverCachesCHROMIUM(void); |
1030 | 1042 |
1031 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, | 1043 void DoMatrixLoadfCHROMIUM(GLenum matrix_mode, |
1032 const volatile GLfloat* matrix); | 1044 const volatile GLfloat* matrix); |
1033 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode); | 1045 void DoMatrixLoadIdentityCHROMIUM(GLenum matrix_mode); |
1034 void DoScheduleCALayerInUseQueryCHROMIUM(GLsizei count, | 1046 void DoScheduleCALayerInUseQueryCHROMIUM(GLsizei count, |
1035 const volatile GLuint* textures); | 1047 const volatile GLuint* textures); |
1036 | 1048 |
1049 void DoFlushMappedBufferRange( | |
1050 GLenum target, GLintptr offset, GLsizeiptr size); | |
1051 | |
1037 // Creates a Program for the given program. | 1052 // Creates a Program for the given program. |
1038 Program* CreateProgram(GLuint client_id, GLuint service_id) { | 1053 Program* CreateProgram(GLuint client_id, GLuint service_id) { |
1039 return program_manager()->CreateProgram(client_id, service_id); | 1054 return program_manager()->CreateProgram(client_id, service_id); |
1040 } | 1055 } |
1041 | 1056 |
1042 // Gets the program info for the given program. Returns NULL if none exists. | 1057 // Gets the program info for the given program. Returns NULL if none exists. |
1043 Program* GetProgram(GLuint client_id) { | 1058 Program* GetProgram(GLuint client_id) { |
1044 return program_manager()->GetProgram(client_id); | 1059 return program_manager()->GetProgram(client_id); |
1045 } | 1060 } |
1046 | 1061 |
(...skipping 15777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16824 typedef cmds::MapBufferRange::Result Result; | 16839 typedef cmds::MapBufferRange::Result Result; |
16825 Result* result = GetSharedMemoryAs<Result*>( | 16840 Result* result = GetSharedMemoryAs<Result*>( |
16826 c.result_shm_id, c.result_shm_offset, sizeof(*result)); | 16841 c.result_shm_id, c.result_shm_offset, sizeof(*result)); |
16827 if (!result) { | 16842 if (!result) { |
16828 return error::kOutOfBounds; | 16843 return error::kOutOfBounds; |
16829 } | 16844 } |
16830 if (*result != 0) { | 16845 if (*result != 0) { |
16831 *result = 0; | 16846 *result = 0; |
16832 return error::kInvalidArguments; | 16847 return error::kInvalidArguments; |
16833 } | 16848 } |
16834 int8_t* mem = | |
16835 GetSharedMemoryAs<int8_t*>(data_shm_id, data_shm_offset, size); | |
16836 if (!mem) { | |
16837 return error::kOutOfBounds; | |
16838 } | |
16839 | |
16840 if (!validators_->buffer_target.IsValid(target)) { | 16849 if (!validators_->buffer_target.IsValid(target)) { |
16841 LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); | 16850 LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
16842 return error::kNoError; | 16851 return error::kNoError; |
16843 } | 16852 } |
16844 | |
16845 GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT; | |
16846 if ((access & mask) == mask) { | |
16847 // TODO(zmo): To be on the safe side, always map | |
16848 // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT. | |
16849 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT); | |
16850 access = (access | GL_MAP_INVALIDATE_RANGE_BIT); | |
16851 } | |
16852 // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of | |
16853 // undefined behaviors. | |
16854 mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT; | |
16855 if ((access & mask) == mask) { | |
16856 LOCAL_SET_GL_ERROR( | |
16857 GL_INVALID_OPERATION, func_name, "incompatible access bits"); | |
16858 return error::kNoError; | |
16859 } | |
16860 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT); | |
16861 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT && | |
16862 (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) { | |
16863 access = (access | GL_MAP_READ_BIT); | |
16864 } | |
16865 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); | 16853 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); |
16866 if (!buffer) { | 16854 if (!buffer) { |
16867 LOCAL_SET_GL_ERROR( | 16855 LOCAL_SET_GL_ERROR( |
16868 GL_INVALID_OPERATION, func_name, "no buffer bound to target"); | 16856 GL_INVALID_OPERATION, func_name, "no buffer bound to target"); |
16869 return error::kNoError; | 16857 return error::kNoError; |
16870 } | 16858 } |
16871 if (buffer->GetMappedRange()) { | 16859 if (buffer->GetMappedRange()) { |
16872 LOCAL_SET_GL_ERROR( | 16860 LOCAL_SET_GL_ERROR( |
16873 GL_INVALID_OPERATION, func_name, "buffer is already mapped"); | 16861 GL_INVALID_OPERATION, func_name, "buffer is already mapped"); |
16862 return error::kNoError; | |
16863 } | |
16864 if (size == 0) { | |
vmiura
2016/10/04 22:18:52
I think size == 0 should not generate a GL error.
Zhenyao Mo
2016/10/04 22:30:27
This is explicitly required by the spec, ES 3.04,
| |
16865 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "size is zero"); | |
16866 return error::kNoError; | |
16874 } | 16867 } |
16875 if (!buffer->CheckRange(offset, size)) { | 16868 if (!buffer->CheckRange(offset, size)) { |
16876 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "invalid range"); | 16869 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "invalid range"); |
16877 return error::kNoError; | 16870 return error::kNoError; |
16878 } | 16871 } |
16872 int8_t* mem = | |
16873 GetSharedMemoryAs<int8_t*>(data_shm_id, data_shm_offset, size); | |
16874 if (!mem) { | |
16875 return error::kOutOfBounds; | |
16876 } | |
16877 if (!AnyBitsSet(access, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) { | |
16878 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, | |
16879 "neither MAP_READ_BIT nore MAP_WRITE_BIT is set"); | |
16880 return error::kNoError; | |
16881 } | |
vmiura
2016/10/04 22:18:52
Could you add check for "GL_INVALID_VALUE is gener
Zhenyao Mo
2016/10/04 22:30:27
Done.
| |
16882 if (AllBitsSet(access, GL_MAP_READ_BIT) && | |
16883 AnyBitsSet(access, (GL_MAP_INVALIDATE_RANGE_BIT | | |
16884 GL_MAP_INVALIDATE_BUFFER_BIT | | |
16885 GL_MAP_UNSYNCHRONIZED_BIT))) { | |
16886 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, | |
16887 "Incompatible access bits with MAP_READ_BIT"); | |
16888 return error::kNoError; | |
16889 } | |
16890 if (AllBitsSet(access, GL_MAP_FLUSH_EXPLICIT_BIT) && | |
16891 !AllBitsSet(access, GL_MAP_WRITE_BIT)) { | |
16892 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, | |
16893 "MAP_FLUSH_EXPLICIT_BIT set without MAP_WRITE_BIT"); | |
16894 return error::kNoError; | |
16895 } | |
16896 if (AllBitsSet(access, GL_MAP_INVALIDATE_BUFFER_BIT)) { | |
16897 // To be on the safe side, always map GL_MAP_INVALIDATE_BUFFER_BIT to | |
16898 // GL_MAP_INVALIDATE_RANGE_BIT. | |
16899 access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT); | |
16900 access = (access | GL_MAP_INVALIDATE_RANGE_BIT); | |
16901 } | |
16902 // Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of undefined | |
16903 // behaviors. | |
16904 access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT); | |
16905 if (AllBitsSet(access, GL_MAP_WRITE_BIT) && | |
16906 !AllBitsSet(access, GL_MAP_INVALIDATE_RANGE_BIT)) { | |
16907 access = (access | GL_MAP_READ_BIT); | |
16908 } | |
16879 void* ptr = glMapBufferRange(target, offset, size, access); | 16909 void* ptr = glMapBufferRange(target, offset, size, access); |
16880 if (ptr == nullptr) { | 16910 if (ptr == nullptr) { |
16881 return error::kNoError; | 16911 return error::kNoError; |
16882 } | 16912 } |
16883 buffer->SetMappedRange(offset, size, access, ptr, | 16913 buffer->SetMappedRange(offset, size, access, ptr, |
16884 GetSharedMemoryBuffer(data_shm_id), | 16914 GetSharedMemoryBuffer(data_shm_id), |
16885 static_cast<unsigned int>(data_shm_offset)); | 16915 static_cast<unsigned int>(data_shm_offset)); |
16886 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) { | 16916 if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) { |
16887 memcpy(mem, ptr, size); | 16917 memcpy(mem, ptr, size); |
16888 } | 16918 } |
16889 *result = 1; | 16919 *result = 1; |
16890 return error::kNoError; | 16920 return error::kNoError; |
16891 } | 16921 } |
16892 | 16922 |
16893 error::Error GLES2DecoderImpl::HandleUnmapBuffer( | 16923 error::Error GLES2DecoderImpl::HandleUnmapBuffer( |
16894 uint32_t immediate_data_size, | 16924 uint32_t immediate_data_size, const volatile void* cmd_data) { |
16895 const volatile void* cmd_data) { | |
16896 if (!unsafe_es3_apis_enabled()) { | 16925 if (!unsafe_es3_apis_enabled()) { |
16897 return error::kUnknownCommand; | 16926 return error::kUnknownCommand; |
16898 } | 16927 } |
16928 const char* func_name = "glUnmapBuffer"; | |
16929 | |
16899 const volatile gles2::cmds::UnmapBuffer& c = | 16930 const volatile gles2::cmds::UnmapBuffer& c = |
16900 *static_cast<const volatile gles2::cmds::UnmapBuffer*>(cmd_data); | 16931 *static_cast<const volatile gles2::cmds::UnmapBuffer*>(cmd_data); |
16901 GLenum target = static_cast<GLenum>(c.target); | 16932 GLenum target = static_cast<GLenum>(c.target); |
16902 | 16933 |
16903 if (!validators_->buffer_target.IsValid(target)) { | 16934 if (!validators_->buffer_target.IsValid(target)) { |
16904 LOCAL_SET_GL_ERROR_INVALID_ENUM("glMapBufferRange", target, "target"); | 16935 LOCAL_SET_GL_ERROR_INVALID_ENUM(func_name, target, "target"); |
16905 return error::kNoError; | 16936 return error::kNoError; |
16906 } | 16937 } |
16907 | 16938 |
16908 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); | 16939 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); |
16909 if (!buffer) { | 16940 if (!buffer) { |
16910 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound"); | 16941 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "no buffer bound"); |
16911 return error::kNoError; | 16942 return error::kNoError; |
16912 } | 16943 } |
16913 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange(); | 16944 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange(); |
16914 if (!mapped_range) { | 16945 if (!mapped_range) { |
16915 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", | 16946 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "buffer is unmapped"); |
16916 "buffer is unmapped"); | |
16917 return error::kNoError; | 16947 return error::kNoError; |
16918 } | 16948 } |
16919 if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 || | 16949 if (!AllBitsSet(mapped_range->access, GL_MAP_WRITE_BIT) || |
16920 (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) == | 16950 AllBitsSet(mapped_range->access, GL_MAP_FLUSH_EXPLICIT_BIT)) { |
16921 GL_MAP_FLUSH_EXPLICIT_BIT) { | |
16922 // If we don't need to write back, or explict flush is required, no copying | 16951 // If we don't need to write back, or explict flush is required, no copying |
16923 // back is needed. | 16952 // back is needed. |
16924 } else { | 16953 } else { |
16925 void* mem = mapped_range->GetShmPointer(); | 16954 void* mem = mapped_range->GetShmPointer(); |
16926 if (!mem) { | 16955 DCHECK(mem); |
16927 return error::kOutOfBounds; | |
16928 } | |
16929 DCHECK(mapped_range->pointer); | 16956 DCHECK(mapped_range->pointer); |
16930 memcpy(mapped_range->pointer, mem, mapped_range->size); | 16957 memcpy(mapped_range->pointer, mem, mapped_range->size); |
16931 if (buffer->shadowed()) { | 16958 if (buffer->shadowed()) { |
16932 bool success = buffer->SetRange( | 16959 bool success = buffer->SetRange( |
16933 mapped_range->offset, mapped_range->size, mem); | 16960 mapped_range->offset, mapped_range->size, mem); |
16934 DCHECK(success); | 16961 DCHECK(success); |
16935 } | 16962 } |
16936 } | 16963 } |
16937 buffer->RemoveMappedRange(); | 16964 buffer->RemoveMappedRange(); |
16938 GLboolean rt = glUnmapBuffer(target); | 16965 GLboolean rt = glUnmapBuffer(target); |
16939 if (rt == GL_FALSE) { | 16966 if (rt == GL_FALSE) { |
16940 // At this point, we have already done the necessary validation, so | 16967 // At this point, we have already done the necessary validation, so |
16941 // GL_FALSE indicates data corruption. | 16968 // GL_FALSE indicates data corruption. |
16942 // TODO(zmo): We could redo the map / copy data / unmap to recover, but | 16969 // TODO(zmo): We could redo the map / copy data / unmap to recover, but |
16943 // the second unmap could still return GL_FALSE. For now, we simply lose | 16970 // the second unmap could still return GL_FALSE. For now, we simply lose |
16944 // the contexts in the share group. | 16971 // the contexts in the share group. |
16945 LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE"; | 16972 LOG(ERROR) << func_name << " unexpectedly returned GL_FALSE"; |
16946 // Need to lose current context before broadcasting! | 16973 // Need to lose current context before broadcasting! |
16947 MarkContextLost(error::kGuilty); | 16974 MarkContextLost(error::kGuilty); |
16948 group_->LoseContexts(error::kInnocent); | 16975 group_->LoseContexts(error::kInnocent); |
16949 return error::kLostContext; | 16976 return error::kLostContext; |
16950 } | 16977 } |
16951 return error::kNoError; | 16978 return error::kNoError; |
16952 } | 16979 } |
16953 | 16980 |
16981 void GLES2DecoderImpl::DoFlushMappedBufferRange( | |
16982 GLenum target, GLintptr offset, GLsizeiptr size) { | |
16983 const char* func_name = "glFlushMappedBufferRange"; | |
16984 // |size| is validated in HandleFlushMappedBufferRange(). | |
16985 if (offset < 0) { | |
16986 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "offset < 0"); | |
16987 return; | |
16988 } | |
16989 Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); | |
16990 if (!buffer) { | |
16991 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "no buffer bound"); | |
16992 return; | |
16993 } | |
16994 const Buffer::MappedRange* mapped_range = buffer->GetMappedRange(); | |
16995 if (!mapped_range) { | |
16996 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "buffer is unmapped"); | |
16997 return; | |
16998 } | |
16999 if (!AllBitsSet(mapped_range->access, GL_MAP_FLUSH_EXPLICIT_BIT)) { | |
17000 LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, | |
17001 "buffer is mapped without MAP_FLUSH_EXPLICIT_BIT flag"); | |
17002 return; | |
17003 } | |
17004 base::CheckedNumeric<int32_t> range_size = size; | |
17005 range_size += offset; | |
17006 if (!range_size.IsValid() || | |
17007 range_size.ValueOrDefault(0) > mapped_range->size) { | |
17008 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, | |
17009 "offset + size out of bounds"); | |
17010 return; | |
17011 } | |
17012 char* client_data = reinterpret_cast<char*>(mapped_range->GetShmPointer()); | |
17013 DCHECK(client_data); | |
17014 char* gpu_data = reinterpret_cast<char*>(mapped_range->pointer); | |
17015 DCHECK(gpu_data); | |
17016 memcpy(gpu_data + offset, client_data + offset, size); | |
17017 if (buffer->shadowed()) { | |
17018 bool success = buffer->SetRange( | |
17019 mapped_range->offset + offset, size, client_data + offset); | |
17020 DCHECK(success); | |
17021 } | |
17022 glFlushMappedBufferRange(target, offset, size); | |
17023 } | |
17024 | |
16954 // Note that GL_LOST_CONTEXT is specific to GLES. | 17025 // Note that GL_LOST_CONTEXT is specific to GLES. |
16955 // For desktop GL we have to query the reset status proactively. | 17026 // For desktop GL we have to query the reset status proactively. |
16956 void GLES2DecoderImpl::OnContextLostError() { | 17027 void GLES2DecoderImpl::OnContextLostError() { |
16957 if (!WasContextLost()) { | 17028 if (!WasContextLost()) { |
16958 // Need to lose current context before broadcasting! | 17029 // Need to lose current context before broadcasting! |
16959 CheckResetStatus(); | 17030 CheckResetStatus(); |
16960 group_->LoseContexts(error::kUnknown); | 17031 group_->LoseContexts(error::kUnknown); |
16961 reset_by_robustness_extension_ = true; | 17032 reset_by_robustness_extension_ = true; |
16962 } | 17033 } |
16963 } | 17034 } |
(...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18144 } | 18215 } |
18145 | 18216 |
18146 // Include the auto-generated part of this file. We split this because it means | 18217 // Include the auto-generated part of this file. We split this because it means |
18147 // we can easily edit the non-auto generated parts right here in this file | 18218 // we can easily edit the non-auto generated parts right here in this file |
18148 // instead of having to edit some template or the code generator. | 18219 // instead of having to edit some template or the code generator. |
18149 #include "base/macros.h" | 18220 #include "base/macros.h" |
18150 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 18221 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
18151 | 18222 |
18152 } // namespace gles2 | 18223 } // namespace gles2 |
18153 } // namespace gpu | 18224 } // namespace gpu |
OLD | NEW |