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 <cmath> | 10 #include <cmath> |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 } | 183 } |
184 | 184 |
185 struct Vec4f { | 185 struct Vec4f { |
186 explicit Vec4f(const Vec4& data) { | 186 explicit Vec4f(const Vec4& data) { |
187 data.GetValues(v); | 187 data.GetValues(v); |
188 } | 188 } |
189 | 189 |
190 GLfloat v[4]; | 190 GLfloat v[4]; |
191 }; | 191 }; |
192 | 192 |
193 // Returns the union of |rect1| and |rect2| if one of the rectangles is empty, | |
194 // contains the other rectangle or shares an edge with the other rectangle. | |
195 bool CombineAdjacentRects(const gfx::Rect& rect1, | |
196 const gfx::Rect& rect2, | |
197 gfx::Rect* result) { | |
198 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|. | |
199 if (rect1.IsEmpty() || rect2.Contains(rect1)) { | |
200 *result = rect2; | |
201 return true; | |
202 } | |
203 | |
204 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|. | |
205 if (rect2.IsEmpty() || rect1.Contains(rect2)) { | |
206 *result = rect1; | |
207 return true; | |
208 } | |
209 | |
210 // Return the union of |rect1| and |rect2| if they share an edge. | |
211 if (rect1.SharesEdgeWith(rect2)) { | |
212 *result = gfx::UnionRects(rect1, rect2); | |
213 return true; | |
214 } | |
215 | |
216 // Return false if it's not possible to combine |rect1| and |rect2|. | |
217 return false; | |
218 } | |
219 | |
220 GLenum ExtractFormatFromStorageFormat(GLenum internalformat) { | 193 GLenum ExtractFormatFromStorageFormat(GLenum internalformat) { |
221 switch (internalformat) { | 194 switch (internalformat) { |
222 case GL_R8: | 195 case GL_R8: |
223 case GL_R8_SNORM: | 196 case GL_R8_SNORM: |
224 case GL_R16F: | 197 case GL_R16F: |
225 case GL_R32F: | 198 case GL_R32F: |
226 return GL_RED; | 199 return GL_RED; |
227 case GL_R8UI: | 200 case GL_R8UI: |
228 case GL_R8I: | 201 case GL_R8I: |
229 case GL_R16UI: | 202 case GL_R16UI: |
(...skipping 10864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11094 GLint copyX = 0; | 11067 GLint copyX = 0; |
11095 GLint copyY = 0; | 11068 GLint copyY = 0; |
11096 GLint copyWidth = 0; | 11069 GLint copyWidth = 0; |
11097 GLint copyHeight = 0; | 11070 GLint copyHeight = 0; |
11098 Clip(x, width, size.width(), ©X, ©Width); | 11071 Clip(x, width, size.width(), ©X, ©Width); |
11099 Clip(y, height, size.height(), ©Y, ©Height); | 11072 Clip(y, height, size.height(), ©Y, ©Height); |
11100 | 11073 |
11101 if (xoffset != 0 || yoffset != 0 || width != size.width() || | 11074 if (xoffset != 0 || yoffset != 0 || width != size.width() || |
11102 height != size.height()) { | 11075 height != size.height()) { |
11103 gfx::Rect cleared_rect; | 11076 gfx::Rect cleared_rect; |
11104 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), | 11077 if (TextureManager::CombineAdjacentRects( |
11105 gfx::Rect(xoffset, yoffset, width, height), | 11078 texture->GetLevelClearedRect(target, level), |
11106 &cleared_rect)) { | 11079 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { |
11107 DCHECK_GE(cleared_rect.size().GetArea(), | 11080 DCHECK_GE(cleared_rect.size().GetArea(), |
11108 texture->GetLevelClearedRect(target, level).size().GetArea()); | 11081 texture->GetLevelClearedRect(target, level).size().GetArea()); |
11109 texture_manager()->SetLevelClearedRect(texture_ref, target, level, | 11082 texture_manager()->SetLevelClearedRect(texture_ref, target, level, |
11110 cleared_rect); | 11083 cleared_rect); |
11111 } else { | 11084 } else { |
11112 // Otherwise clear part of texture level that is not already cleared. | 11085 // Otherwise clear part of texture level that is not already cleared. |
11113 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, | 11086 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, |
11114 level)) { | 11087 level)) { |
11115 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", | 11088 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", |
11116 "dimensions too big"); | 11089 "dimensions too big"); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11150 glCopyTexSubImage2D(target, level, | 11123 glCopyTexSubImage2D(target, level, |
11151 destX, destY, copyX, copyY, | 11124 destX, destY, copyX, copyY, |
11152 copyWidth, copyHeight); | 11125 copyWidth, copyHeight); |
11153 } | 11126 } |
11154 | 11127 |
11155 // This may be a slow command. Exit command processing to allow for | 11128 // This may be a slow command. Exit command processing to allow for |
11156 // context preemption and GPU watchdog checks. | 11129 // context preemption and GPU watchdog checks. |
11157 ExitCommandProcessingEarly(); | 11130 ExitCommandProcessingEarly(); |
11158 } | 11131 } |
11159 | 11132 |
11160 bool GLES2DecoderImpl::ValidateTexSubImage2D( | |
11161 error::Error* error, | |
11162 const char* function_name, | |
11163 GLenum target, | |
11164 GLint level, | |
11165 GLint xoffset, | |
11166 GLint yoffset, | |
11167 GLsizei width, | |
11168 GLsizei height, | |
11169 GLenum format, | |
11170 GLenum type, | |
11171 const void * data) { | |
11172 (*error) = error::kNoError; | |
11173 if (!validators_->texture_target.IsValid(target)) { | |
11174 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target"); | |
11175 return false; | |
11176 } | |
11177 // TODO(ccameron): Add a separate texture from |texture_target| for | |
11178 // [Compressed]Tex[Sub]Image2D and related functions. | |
11179 // http://crbug.com/536854 | |
11180 if (target == GL_TEXTURE_RECTANGLE_ARB) { | |
11181 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target"); | |
11182 return false; | |
11183 } | |
11184 if (width < 0) { | |
11185 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0"); | |
11186 return false; | |
11187 } | |
11188 if (height < 0) { | |
11189 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0"); | |
11190 return false; | |
11191 } | |
11192 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( | |
11193 &state_, target); | |
11194 if (!texture_ref) { | |
11195 LOCAL_SET_GL_ERROR( | |
11196 GL_INVALID_OPERATION, | |
11197 function_name, "unknown texture for target"); | |
11198 return false; | |
11199 } | |
11200 Texture* texture = texture_ref->texture(); | |
11201 GLenum current_type = 0; | |
11202 GLenum internal_format = 0; | |
11203 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) { | |
11204 LOCAL_SET_GL_ERROR( | |
11205 GL_INVALID_OPERATION, function_name, "level does not exist."); | |
11206 return false; | |
11207 } | |
11208 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(), | |
11209 function_name, format, type, internal_format, level)) { | |
11210 return false; | |
11211 } | |
11212 if (type != current_type && !feature_info_->IsES3Enabled()) { | |
11213 LOCAL_SET_GL_ERROR( | |
11214 GL_INVALID_OPERATION, | |
11215 function_name, "type does not match type of texture."); | |
11216 return false; | |
11217 } | |
11218 if (!texture->ValidForTexture( | |
11219 target, level, xoffset, yoffset, 0, width, height, 1)) { | |
11220 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions."); | |
11221 return false; | |
11222 } | |
11223 if ((GLES2Util::GetChannelsForFormat(format) & | |
11224 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 | |
11225 && !feature_info_->IsES3Enabled()) { | |
11226 LOCAL_SET_GL_ERROR( | |
11227 GL_INVALID_OPERATION, | |
11228 function_name, "can not supply data for depth or stencil textures"); | |
11229 return false; | |
11230 } | |
11231 if (data == NULL) { | |
11232 (*error) = error::kOutOfBounds; | |
11233 return false; | |
11234 } | |
11235 return true; | |
11236 } | |
11237 | |
11238 error::Error GLES2DecoderImpl::DoTexSubImage2D( | |
11239 GLenum target, | |
11240 GLint level, | |
11241 GLint xoffset, | |
11242 GLint yoffset, | |
11243 GLsizei width, | |
11244 GLsizei height, | |
11245 GLenum format, | |
11246 GLenum type, | |
11247 const void * data) { | |
11248 error::Error error = error::kNoError; | |
11249 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level, | |
11250 xoffset, yoffset, width, height, format, type, data)) { | |
11251 return error; | |
11252 } | |
11253 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( | |
11254 &state_, target); | |
11255 Texture* texture = texture_ref->texture(); | |
11256 GLsizei tex_width = 0; | |
11257 GLsizei tex_height = 0; | |
11258 bool ok = texture->GetLevelSize( | |
11259 target, level, &tex_width, &tex_height, nullptr); | |
11260 DCHECK(ok); | |
11261 if (xoffset != 0 || yoffset != 0 || | |
11262 width != tex_width || height != tex_height) { | |
11263 gfx::Rect cleared_rect; | |
11264 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), | |
11265 gfx::Rect(xoffset, yoffset, width, height), | |
11266 &cleared_rect)) { | |
11267 DCHECK_GE(cleared_rect.size().GetArea(), | |
11268 texture->GetLevelClearedRect(target, level).size().GetArea()); | |
11269 texture_manager()->SetLevelClearedRect(texture_ref, target, level, | |
11270 cleared_rect); | |
11271 } else { | |
11272 // Otherwise clear part of texture level that is not already cleared. | |
11273 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, | |
11274 level)) { | |
11275 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D", | |
11276 "dimensions too big"); | |
11277 return error::kNoError; | |
11278 } | |
11279 } | |
11280 ScopedTextureUploadTimer timer(&texture_state_); | |
11281 glTexSubImage2D( | |
11282 target, level, xoffset, yoffset, width, height, format, type, data); | |
11283 return error::kNoError; | |
11284 } | |
11285 | |
11286 if (!texture_state_.texsubimage_faster_than_teximage && | |
11287 !texture->IsImmutable() && | |
11288 !texture->HasImages()) { | |
11289 ScopedTextureUploadTimer timer(&texture_state_); | |
11290 GLenum internal_format; | |
11291 GLenum tex_type; | |
11292 texture->GetLevelType(target, level, &tex_type, &internal_format); | |
11293 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need | |
11294 // to look it up. | |
11295 glTexImage2D( | |
11296 target, level, internal_format, width, height, 0, format, type, data); | |
11297 } else { | |
11298 ScopedTextureUploadTimer timer(&texture_state_); | |
11299 glTexSubImage2D( | |
11300 target, level, xoffset, yoffset, width, height, format, type, data); | |
11301 } | |
11302 texture_manager()->SetLevelCleared(texture_ref, target, level, true); | |
11303 | |
11304 // This may be a slow command. Exit command processing to allow for | |
11305 // context preemption and GPU watchdog checks. | |
11306 ExitCommandProcessingEarly(); | |
11307 return error::kNoError; | |
11308 } | |
11309 | |
11310 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, | 11133 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, |
11311 const void* cmd_data) { | 11134 const void* cmd_data) { |
11312 const gles2::cmds::TexSubImage2D& c = | 11135 const gles2::cmds::TexSubImage2D& c = |
11313 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); | 11136 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); |
11314 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", | 11137 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", |
11315 "width", c.width, "height", c.height); | 11138 "width", c.width, "height", c.height); |
11316 GLboolean internal = static_cast<GLboolean>(c.internal); | 11139 GLboolean internal = static_cast<GLboolean>(c.internal); |
11317 if (internal == GL_TRUE && texture_state_.tex_image_failed) | 11140 if (internal == GL_TRUE && texture_state_.tex_image_failed) |
11318 return error::kNoError; | 11141 return error::kNoError; |
11319 | 11142 |
11320 GLenum target = static_cast<GLenum>(c.target); | 11143 GLenum target = static_cast<GLenum>(c.target); |
11321 GLint level = static_cast<GLint>(c.level); | 11144 GLint level = static_cast<GLint>(c.level); |
11322 GLint xoffset = static_cast<GLint>(c.xoffset); | 11145 GLint xoffset = static_cast<GLint>(c.xoffset); |
11323 GLint yoffset = static_cast<GLint>(c.yoffset); | 11146 GLint yoffset = static_cast<GLint>(c.yoffset); |
11324 GLsizei width = static_cast<GLsizei>(c.width); | 11147 GLsizei width = static_cast<GLsizei>(c.width); |
11325 GLsizei height = static_cast<GLsizei>(c.height); | 11148 GLsizei height = static_cast<GLsizei>(c.height); |
11326 GLenum format = static_cast<GLenum>(c.format); | 11149 GLenum format = static_cast<GLenum>(c.format); |
11327 GLenum type = static_cast<GLenum>(c.type); | 11150 GLenum type = static_cast<GLenum>(c.type); |
11328 uint32 data_size; | 11151 uint32 data_size; |
11329 if (!GLES2Util::ComputeImageDataSizes( | 11152 if (!GLES2Util::ComputeImageDataSizes( |
11330 width, height, 1, format, type, state_.unpack_alignment, &data_size, | 11153 width, height, 1, format, type, state_.unpack_alignment, &data_size, |
11331 NULL, NULL)) { | 11154 NULL, NULL)) { |
11332 return error::kOutOfBounds; | 11155 return error::kOutOfBounds; |
11333 } | 11156 } |
11157 | |
11334 const void* pixels = GetSharedMemoryAs<const void*>( | 11158 const void* pixels = GetSharedMemoryAs<const void*>( |
11335 c.pixels_shm_id, c.pixels_shm_offset, data_size); | 11159 c.pixels_shm_id, c.pixels_shm_offset, data_size); |
11336 return DoTexSubImage2D( | 11160 if (!pixels) |
11337 target, level, xoffset, yoffset, width, height, format, type, pixels); | 11161 return error::kOutOfBounds; |
bajones
2015/10/28 20:23:26
Seems like kInvalidArguments might be a better err
Kimmo Kinnunen
2015/10/29 06:21:17
The intention was not to change behavior wrt this.
| |
11162 | |
11163 TextureManager::DoTexSubImageArguments args = { | |
11164 target, level, xoffset, yoffset, width, | |
11165 height, format, type, pixels, data_size}; | |
11166 texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, | |
11167 &framebuffer_state_, | |
11168 "glTexSubImage2D", args); | |
11169 | |
11170 // This may be a slow command. Exit command processing to allow for | |
11171 // context preemption and GPU watchdog checks. | |
11172 ExitCommandProcessingEarly(); | |
11173 return error::kNoError; | |
11338 } | 11174 } |
11339 | 11175 |
11340 error::Error GLES2DecoderImpl::DoTexSubImage3D( | 11176 error::Error GLES2DecoderImpl::DoTexSubImage3D( |
11341 GLenum target, | 11177 GLenum target, |
11342 GLint level, | 11178 GLint level, |
11343 GLint xoffset, | 11179 GLint xoffset, |
11344 GLint yoffset, | 11180 GLint yoffset, |
11345 GLint zoffset, | 11181 GLint zoffset, |
11346 GLsizei width, | 11182 GLsizei width, |
11347 GLsizei height, | 11183 GLsizei height, |
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13265 } | 13101 } |
13266 | 13102 |
13267 int dest_width = 0; | 13103 int dest_width = 0; |
13268 int dest_height = 0; | 13104 int dest_height = 0; |
13269 bool ok = dest_texture->GetLevelSize( | 13105 bool ok = dest_texture->GetLevelSize( |
13270 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); | 13106 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); |
13271 DCHECK(ok); | 13107 DCHECK(ok); |
13272 if (xoffset != 0 || yoffset != 0 || width != dest_width || | 13108 if (xoffset != 0 || yoffset != 0 || width != dest_width || |
13273 height != dest_height) { | 13109 height != dest_height) { |
13274 gfx::Rect cleared_rect; | 13110 gfx::Rect cleared_rect; |
13275 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), | 13111 if (TextureManager::CombineAdjacentRects( |
13276 gfx::Rect(xoffset, yoffset, width, height), | 13112 dest_texture->GetLevelClearedRect(target, 0), |
13277 &cleared_rect)) { | 13113 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { |
13278 DCHECK_GE(cleared_rect.size().GetArea(), | 13114 DCHECK_GE(cleared_rect.size().GetArea(), |
13279 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); | 13115 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); |
13280 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, | 13116 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
13281 cleared_rect); | 13117 cleared_rect); |
13282 } else { | 13118 } else { |
13283 // Otherwise clear part of texture level that is not already cleared. | 13119 // Otherwise clear part of texture level that is not already cleared. |
13284 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, | 13120 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
13285 0)) { | 13121 0)) { |
13286 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", | 13122 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", |
13287 "destination texture dimensions too big"); | 13123 "destination texture dimensions too big"); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13603 } | 13439 } |
13604 | 13440 |
13605 int dest_width = 0; | 13441 int dest_width = 0; |
13606 int dest_height = 0; | 13442 int dest_height = 0; |
13607 bool ok = dest_texture->GetLevelSize( | 13443 bool ok = dest_texture->GetLevelSize( |
13608 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); | 13444 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); |
13609 DCHECK(ok); | 13445 DCHECK(ok); |
13610 if (xoffset != 0 || yoffset != 0 || width != dest_width || | 13446 if (xoffset != 0 || yoffset != 0 || width != dest_width || |
13611 height != dest_height) { | 13447 height != dest_height) { |
13612 gfx::Rect cleared_rect; | 13448 gfx::Rect cleared_rect; |
13613 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), | 13449 if (TextureManager::CombineAdjacentRects( |
13614 gfx::Rect(xoffset, yoffset, width, height), | 13450 dest_texture->GetLevelClearedRect(target, 0), |
13615 &cleared_rect)) { | 13451 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { |
13616 DCHECK_GE(cleared_rect.size().GetArea(), | 13452 DCHECK_GE(cleared_rect.size().GetArea(), |
13617 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); | 13453 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); |
13618 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, | 13454 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
13619 cleared_rect); | 13455 cleared_rect); |
13620 } else { | 13456 } else { |
13621 // Otherwise clear part of texture level that is not already cleared. | 13457 // Otherwise clear part of texture level that is not already cleared. |
13622 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, | 13458 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
13623 0)) { | 13459 0)) { |
13624 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, | 13460 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, |
13625 "glCompressedCopySubTextureCHROMIUM", | 13461 "glCompressedCopySubTextureCHROMIUM", |
(...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14980 return error::kNoError; | 14816 return error::kNoError; |
14981 } | 14817 } |
14982 | 14818 |
14983 // Include the auto-generated part of this file. We split this because it means | 14819 // Include the auto-generated part of this file. We split this because it means |
14984 // we can easily edit the non-auto generated parts right here in this file | 14820 // we can easily edit the non-auto generated parts right here in this file |
14985 // instead of having to edit some template or the code generator. | 14821 // instead of having to edit some template or the code generator. |
14986 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 14822 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
14987 | 14823 |
14988 } // namespace gles2 | 14824 } // namespace gles2 |
14989 } // namespace gpu | 14825 } // namespace gpu |
OLD | NEW |