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 |
193 GLenum ExtractFormatFromStorageFormat(GLenum internalformat) { | 220 GLenum ExtractFormatFromStorageFormat(GLenum internalformat) { |
194 switch (internalformat) { | 221 switch (internalformat) { |
195 case GL_R8: | 222 case GL_R8: |
196 case GL_R8_SNORM: | 223 case GL_R8_SNORM: |
197 case GL_R16F: | 224 case GL_R16F: |
198 case GL_R32F: | 225 case GL_R32F: |
199 return GL_RED; | 226 return GL_RED; |
200 case GL_R8UI: | 227 case GL_R8UI: |
201 case GL_R8I: | 228 case GL_R8I: |
202 case GL_R16UI: | 229 case GL_R16UI: |
(...skipping 10856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11059 GLint copyX = 0; | 11086 GLint copyX = 0; |
11060 GLint copyY = 0; | 11087 GLint copyY = 0; |
11061 GLint copyWidth = 0; | 11088 GLint copyWidth = 0; |
11062 GLint copyHeight = 0; | 11089 GLint copyHeight = 0; |
11063 Clip(x, width, size.width(), ©X, ©Width); | 11090 Clip(x, width, size.width(), ©X, ©Width); |
11064 Clip(y, height, size.height(), ©Y, ©Height); | 11091 Clip(y, height, size.height(), ©Y, ©Height); |
11065 | 11092 |
11066 if (xoffset != 0 || yoffset != 0 || width != size.width() || | 11093 if (xoffset != 0 || yoffset != 0 || width != size.width() || |
11067 height != size.height()) { | 11094 height != size.height()) { |
11068 gfx::Rect cleared_rect; | 11095 gfx::Rect cleared_rect; |
11069 if (TextureManager::CombineAdjacentRects( | 11096 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), |
11070 texture->GetLevelClearedRect(target, level), | 11097 gfx::Rect(xoffset, yoffset, width, height), |
11071 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { | 11098 &cleared_rect)) { |
11072 DCHECK_GE(cleared_rect.size().GetArea(), | 11099 DCHECK_GE(cleared_rect.size().GetArea(), |
11073 texture->GetLevelClearedRect(target, level).size().GetArea()); | 11100 texture->GetLevelClearedRect(target, level).size().GetArea()); |
11074 texture_manager()->SetLevelClearedRect(texture_ref, target, level, | 11101 texture_manager()->SetLevelClearedRect(texture_ref, target, level, |
11075 cleared_rect); | 11102 cleared_rect); |
11076 } else { | 11103 } else { |
11077 // Otherwise clear part of texture level that is not already cleared. | 11104 // Otherwise clear part of texture level that is not already cleared. |
11078 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, | 11105 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, |
11079 level)) { | 11106 level)) { |
11080 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", | 11107 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", |
11081 "dimensions too big"); | 11108 "dimensions too big"); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11115 glCopyTexSubImage2D(target, level, | 11142 glCopyTexSubImage2D(target, level, |
11116 destX, destY, copyX, copyY, | 11143 destX, destY, copyX, copyY, |
11117 copyWidth, copyHeight); | 11144 copyWidth, copyHeight); |
11118 } | 11145 } |
11119 | 11146 |
11120 // This may be a slow command. Exit command processing to allow for | 11147 // This may be a slow command. Exit command processing to allow for |
11121 // context preemption and GPU watchdog checks. | 11148 // context preemption and GPU watchdog checks. |
11122 ExitCommandProcessingEarly(); | 11149 ExitCommandProcessingEarly(); |
11123 } | 11150 } |
11124 | 11151 |
| 11152 bool GLES2DecoderImpl::ValidateTexSubImage2D( |
| 11153 error::Error* error, |
| 11154 const char* function_name, |
| 11155 GLenum target, |
| 11156 GLint level, |
| 11157 GLint xoffset, |
| 11158 GLint yoffset, |
| 11159 GLsizei width, |
| 11160 GLsizei height, |
| 11161 GLenum format, |
| 11162 GLenum type, |
| 11163 const void * data) { |
| 11164 (*error) = error::kNoError; |
| 11165 if (!validators_->texture_target.IsValid(target)) { |
| 11166 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target"); |
| 11167 return false; |
| 11168 } |
| 11169 if (width < 0) { |
| 11170 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0"); |
| 11171 return false; |
| 11172 } |
| 11173 if (height < 0) { |
| 11174 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0"); |
| 11175 return false; |
| 11176 } |
| 11177 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( |
| 11178 &state_, target); |
| 11179 if (!texture_ref) { |
| 11180 LOCAL_SET_GL_ERROR( |
| 11181 GL_INVALID_OPERATION, |
| 11182 function_name, "unknown texture for target"); |
| 11183 return false; |
| 11184 } |
| 11185 Texture* texture = texture_ref->texture(); |
| 11186 GLenum current_type = 0; |
| 11187 GLenum internal_format = 0; |
| 11188 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) { |
| 11189 LOCAL_SET_GL_ERROR( |
| 11190 GL_INVALID_OPERATION, function_name, "level does not exist."); |
| 11191 return false; |
| 11192 } |
| 11193 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(), |
| 11194 function_name, format, type, internal_format, level)) { |
| 11195 return false; |
| 11196 } |
| 11197 if (type != current_type && !feature_info_->IsES3Enabled()) { |
| 11198 LOCAL_SET_GL_ERROR( |
| 11199 GL_INVALID_OPERATION, |
| 11200 function_name, "type does not match type of texture."); |
| 11201 return false; |
| 11202 } |
| 11203 if (!texture->ValidForTexture( |
| 11204 target, level, xoffset, yoffset, 0, width, height, 1)) { |
| 11205 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions."); |
| 11206 return false; |
| 11207 } |
| 11208 if ((GLES2Util::GetChannelsForFormat(format) & |
| 11209 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 |
| 11210 && !feature_info_->IsES3Enabled()) { |
| 11211 LOCAL_SET_GL_ERROR( |
| 11212 GL_INVALID_OPERATION, |
| 11213 function_name, "can not supply data for depth or stencil textures"); |
| 11214 return false; |
| 11215 } |
| 11216 if (data == NULL) { |
| 11217 (*error) = error::kOutOfBounds; |
| 11218 return false; |
| 11219 } |
| 11220 return true; |
| 11221 } |
| 11222 |
| 11223 error::Error GLES2DecoderImpl::DoTexSubImage2D( |
| 11224 GLenum target, |
| 11225 GLint level, |
| 11226 GLint xoffset, |
| 11227 GLint yoffset, |
| 11228 GLsizei width, |
| 11229 GLsizei height, |
| 11230 GLenum format, |
| 11231 GLenum type, |
| 11232 const void * data) { |
| 11233 error::Error error = error::kNoError; |
| 11234 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level, |
| 11235 xoffset, yoffset, width, height, format, type, data)) { |
| 11236 return error; |
| 11237 } |
| 11238 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( |
| 11239 &state_, target); |
| 11240 Texture* texture = texture_ref->texture(); |
| 11241 GLsizei tex_width = 0; |
| 11242 GLsizei tex_height = 0; |
| 11243 bool ok = texture->GetLevelSize( |
| 11244 target, level, &tex_width, &tex_height, nullptr); |
| 11245 DCHECK(ok); |
| 11246 if (xoffset != 0 || yoffset != 0 || |
| 11247 width != tex_width || height != tex_height) { |
| 11248 gfx::Rect cleared_rect; |
| 11249 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), |
| 11250 gfx::Rect(xoffset, yoffset, width, height), |
| 11251 &cleared_rect)) { |
| 11252 DCHECK_GE(cleared_rect.size().GetArea(), |
| 11253 texture->GetLevelClearedRect(target, level).size().GetArea()); |
| 11254 texture_manager()->SetLevelClearedRect(texture_ref, target, level, |
| 11255 cleared_rect); |
| 11256 } else { |
| 11257 // Otherwise clear part of texture level that is not already cleared. |
| 11258 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, |
| 11259 level)) { |
| 11260 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D", |
| 11261 "dimensions too big"); |
| 11262 return error::kNoError; |
| 11263 } |
| 11264 } |
| 11265 ScopedTextureUploadTimer timer(&texture_state_); |
| 11266 glTexSubImage2D( |
| 11267 target, level, xoffset, yoffset, width, height, format, type, data); |
| 11268 return error::kNoError; |
| 11269 } |
| 11270 |
| 11271 if (!texture_state_.texsubimage_faster_than_teximage && |
| 11272 !texture->IsImmutable() && |
| 11273 !texture->HasImages()) { |
| 11274 ScopedTextureUploadTimer timer(&texture_state_); |
| 11275 GLenum internal_format; |
| 11276 GLenum tex_type; |
| 11277 texture->GetLevelType(target, level, &tex_type, &internal_format); |
| 11278 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need |
| 11279 // to look it up. |
| 11280 glTexImage2D( |
| 11281 target, level, internal_format, width, height, 0, format, type, data); |
| 11282 } else { |
| 11283 ScopedTextureUploadTimer timer(&texture_state_); |
| 11284 glTexSubImage2D( |
| 11285 target, level, xoffset, yoffset, width, height, format, type, data); |
| 11286 } |
| 11287 texture_manager()->SetLevelCleared(texture_ref, target, level, true); |
| 11288 |
| 11289 // This may be a slow command. Exit command processing to allow for |
| 11290 // context preemption and GPU watchdog checks. |
| 11291 ExitCommandProcessingEarly(); |
| 11292 return error::kNoError; |
| 11293 } |
| 11294 |
11125 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, | 11295 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, |
11126 const void* cmd_data) { | 11296 const void* cmd_data) { |
11127 const gles2::cmds::TexSubImage2D& c = | 11297 const gles2::cmds::TexSubImage2D& c = |
11128 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); | 11298 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); |
11129 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", | 11299 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", |
11130 "width", c.width, "height", c.height); | 11300 "width", c.width, "height", c.height); |
11131 GLboolean internal = static_cast<GLboolean>(c.internal); | 11301 GLboolean internal = static_cast<GLboolean>(c.internal); |
11132 if (internal == GL_TRUE && texture_state_.tex_image_failed) | 11302 if (internal == GL_TRUE && texture_state_.tex_image_failed) |
11133 return error::kNoError; | 11303 return error::kNoError; |
11134 | 11304 |
11135 GLenum target = static_cast<GLenum>(c.target); | 11305 GLenum target = static_cast<GLenum>(c.target); |
11136 GLint level = static_cast<GLint>(c.level); | 11306 GLint level = static_cast<GLint>(c.level); |
11137 GLint xoffset = static_cast<GLint>(c.xoffset); | 11307 GLint xoffset = static_cast<GLint>(c.xoffset); |
11138 GLint yoffset = static_cast<GLint>(c.yoffset); | 11308 GLint yoffset = static_cast<GLint>(c.yoffset); |
11139 GLsizei width = static_cast<GLsizei>(c.width); | 11309 GLsizei width = static_cast<GLsizei>(c.width); |
11140 GLsizei height = static_cast<GLsizei>(c.height); | 11310 GLsizei height = static_cast<GLsizei>(c.height); |
11141 GLenum format = static_cast<GLenum>(c.format); | 11311 GLenum format = static_cast<GLenum>(c.format); |
11142 GLenum type = static_cast<GLenum>(c.type); | 11312 GLenum type = static_cast<GLenum>(c.type); |
11143 uint32 data_size; | 11313 uint32 data_size; |
11144 if (!GLES2Util::ComputeImageDataSizes( | 11314 if (!GLES2Util::ComputeImageDataSizes( |
11145 width, height, 1, format, type, state_.unpack_alignment, &data_size, | 11315 width, height, 1, format, type, state_.unpack_alignment, &data_size, |
11146 NULL, NULL)) { | 11316 NULL, NULL)) { |
11147 return error::kOutOfBounds; | 11317 return error::kOutOfBounds; |
11148 } | 11318 } |
11149 | |
11150 const void* pixels = GetSharedMemoryAs<const void*>( | 11319 const void* pixels = GetSharedMemoryAs<const void*>( |
11151 c.pixels_shm_id, c.pixels_shm_offset, data_size); | 11320 c.pixels_shm_id, c.pixels_shm_offset, data_size); |
11152 if (!pixels) | 11321 return DoTexSubImage2D( |
11153 return error::kOutOfBounds; | 11322 target, level, xoffset, yoffset, width, height, format, type, pixels); |
11154 | |
11155 TextureManager::DoTexSubImageArguments args = { | |
11156 target, level, xoffset, yoffset, width, | |
11157 height, format, type, pixels, data_size}; | |
11158 texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, | |
11159 &framebuffer_state_, | |
11160 "glTexSubImage2D", args); | |
11161 | |
11162 // This may be a slow command. Exit command processing to allow for | |
11163 // context preemption and GPU watchdog checks. | |
11164 ExitCommandProcessingEarly(); | |
11165 return error::kNoError; | |
11166 } | 11323 } |
11167 | 11324 |
11168 error::Error GLES2DecoderImpl::DoTexSubImage3D( | 11325 error::Error GLES2DecoderImpl::DoTexSubImage3D( |
11169 GLenum target, | 11326 GLenum target, |
11170 GLint level, | 11327 GLint level, |
11171 GLint xoffset, | 11328 GLint xoffset, |
11172 GLint yoffset, | 11329 GLint yoffset, |
11173 GLint zoffset, | 11330 GLint zoffset, |
11174 GLsizei width, | 11331 GLsizei width, |
11175 GLsizei height, | 11332 GLsizei height, |
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13093 } | 13250 } |
13094 | 13251 |
13095 int dest_width = 0; | 13252 int dest_width = 0; |
13096 int dest_height = 0; | 13253 int dest_height = 0; |
13097 bool ok = dest_texture->GetLevelSize( | 13254 bool ok = dest_texture->GetLevelSize( |
13098 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); | 13255 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); |
13099 DCHECK(ok); | 13256 DCHECK(ok); |
13100 if (xoffset != 0 || yoffset != 0 || width != dest_width || | 13257 if (xoffset != 0 || yoffset != 0 || width != dest_width || |
13101 height != dest_height) { | 13258 height != dest_height) { |
13102 gfx::Rect cleared_rect; | 13259 gfx::Rect cleared_rect; |
13103 if (TextureManager::CombineAdjacentRects( | 13260 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), |
13104 dest_texture->GetLevelClearedRect(target, 0), | 13261 gfx::Rect(xoffset, yoffset, width, height), |
13105 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { | 13262 &cleared_rect)) { |
13106 DCHECK_GE(cleared_rect.size().GetArea(), | 13263 DCHECK_GE(cleared_rect.size().GetArea(), |
13107 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); | 13264 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); |
13108 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, | 13265 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
13109 cleared_rect); | 13266 cleared_rect); |
13110 } else { | 13267 } else { |
13111 // Otherwise clear part of texture level that is not already cleared. | 13268 // Otherwise clear part of texture level that is not already cleared. |
13112 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, | 13269 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
13113 0)) { | 13270 0)) { |
13114 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", | 13271 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", |
13115 "destination texture dimensions too big"); | 13272 "destination texture dimensions too big"); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13431 } | 13588 } |
13432 | 13589 |
13433 int dest_width = 0; | 13590 int dest_width = 0; |
13434 int dest_height = 0; | 13591 int dest_height = 0; |
13435 bool ok = dest_texture->GetLevelSize( | 13592 bool ok = dest_texture->GetLevelSize( |
13436 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); | 13593 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); |
13437 DCHECK(ok); | 13594 DCHECK(ok); |
13438 if (xoffset != 0 || yoffset != 0 || width != dest_width || | 13595 if (xoffset != 0 || yoffset != 0 || width != dest_width || |
13439 height != dest_height) { | 13596 height != dest_height) { |
13440 gfx::Rect cleared_rect; | 13597 gfx::Rect cleared_rect; |
13441 if (TextureManager::CombineAdjacentRects( | 13598 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), |
13442 dest_texture->GetLevelClearedRect(target, 0), | 13599 gfx::Rect(xoffset, yoffset, width, height), |
13443 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { | 13600 &cleared_rect)) { |
13444 DCHECK_GE(cleared_rect.size().GetArea(), | 13601 DCHECK_GE(cleared_rect.size().GetArea(), |
13445 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); | 13602 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); |
13446 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, | 13603 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
13447 cleared_rect); | 13604 cleared_rect); |
13448 } else { | 13605 } else { |
13449 // Otherwise clear part of texture level that is not already cleared. | 13606 // Otherwise clear part of texture level that is not already cleared. |
13450 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, | 13607 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
13451 0)) { | 13608 0)) { |
13452 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, | 13609 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, |
13453 "glCompressedCopySubTextureCHROMIUM", | 13610 "glCompressedCopySubTextureCHROMIUM", |
(...skipping 1816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15270 return error::kNoError; | 15427 return error::kNoError; |
15271 } | 15428 } |
15272 | 15429 |
15273 // Include the auto-generated part of this file. We split this because it means | 15430 // Include the auto-generated part of this file. We split this because it means |
15274 // we can easily edit the non-auto generated parts right here in this file | 15431 // we can easily edit the non-auto generated parts right here in this file |
15275 // instead of having to edit some template or the code generator. | 15432 // instead of having to edit some template or the code generator. |
15276 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 15433 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
15277 | 15434 |
15278 } // namespace gles2 | 15435 } // namespace gles2 |
15279 } // namespace gpu | 15436 } // namespace gpu |
OLD | NEW |