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 10872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11102 GLint copyX = 0; | 11075 GLint copyX = 0; |
11103 GLint copyY = 0; | 11076 GLint copyY = 0; |
11104 GLint copyWidth = 0; | 11077 GLint copyWidth = 0; |
11105 GLint copyHeight = 0; | 11078 GLint copyHeight = 0; |
11106 Clip(x, width, size.width(), ©X, ©Width); | 11079 Clip(x, width, size.width(), ©X, ©Width); |
11107 Clip(y, height, size.height(), ©Y, ©Height); | 11080 Clip(y, height, size.height(), ©Y, ©Height); |
11108 | 11081 |
11109 if (xoffset != 0 || yoffset != 0 || width != size.width() || | 11082 if (xoffset != 0 || yoffset != 0 || width != size.width() || |
11110 height != size.height()) { | 11083 height != size.height()) { |
11111 gfx::Rect cleared_rect; | 11084 gfx::Rect cleared_rect; |
11112 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), | 11085 if (TextureManager::CombineAdjacentRects( |
11113 gfx::Rect(xoffset, yoffset, width, height), | 11086 texture->GetLevelClearedRect(target, level), |
11114 &cleared_rect)) { | 11087 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { |
11115 DCHECK_GE(cleared_rect.size().GetArea(), | 11088 DCHECK_GE(cleared_rect.size().GetArea(), |
11116 texture->GetLevelClearedRect(target, level).size().GetArea()); | 11089 texture->GetLevelClearedRect(target, level).size().GetArea()); |
11117 texture_manager()->SetLevelClearedRect(texture_ref, target, level, | 11090 texture_manager()->SetLevelClearedRect(texture_ref, target, level, |
11118 cleared_rect); | 11091 cleared_rect); |
11119 } else { | 11092 } else { |
11120 // Otherwise clear part of texture level that is not already cleared. | 11093 // Otherwise clear part of texture level that is not already cleared. |
11121 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, | 11094 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, |
11122 level)) { | 11095 level)) { |
11123 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", | 11096 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", |
11124 "dimensions too big"); | 11097 "dimensions too big"); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11158 glCopyTexSubImage2D(target, level, | 11131 glCopyTexSubImage2D(target, level, |
11159 destX, destY, copyX, copyY, | 11132 destX, destY, copyX, copyY, |
11160 copyWidth, copyHeight); | 11133 copyWidth, copyHeight); |
11161 } | 11134 } |
11162 | 11135 |
11163 // This may be a slow command. Exit command processing to allow for | 11136 // This may be a slow command. Exit command processing to allow for |
11164 // context preemption and GPU watchdog checks. | 11137 // context preemption and GPU watchdog checks. |
11165 ExitCommandProcessingEarly(); | 11138 ExitCommandProcessingEarly(); |
11166 } | 11139 } |
11167 | 11140 |
11168 bool GLES2DecoderImpl::ValidateTexSubImage2D( | |
11169 error::Error* error, | |
11170 const char* function_name, | |
11171 GLenum target, | |
11172 GLint level, | |
11173 GLint xoffset, | |
11174 GLint yoffset, | |
11175 GLsizei width, | |
11176 GLsizei height, | |
11177 GLenum format, | |
11178 GLenum type, | |
11179 const void * data) { | |
11180 (*error) = error::kNoError; | |
11181 if (!validators_->texture_target.IsValid(target)) { | |
11182 LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target"); | |
11183 return false; | |
11184 } | |
11185 if (width < 0) { | |
11186 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "width < 0"); | |
11187 return false; | |
11188 } | |
11189 if (height < 0) { | |
11190 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0"); | |
11191 return false; | |
11192 } | |
11193 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( | |
11194 &state_, target); | |
11195 if (!texture_ref) { | |
11196 LOCAL_SET_GL_ERROR( | |
11197 GL_INVALID_OPERATION, | |
11198 function_name, "unknown texture for target"); | |
11199 return false; | |
11200 } | |
11201 Texture* texture = texture_ref->texture(); | |
11202 GLenum current_type = 0; | |
11203 GLenum internal_format = 0; | |
11204 if (!texture->GetLevelType(target, level, ¤t_type, &internal_format)) { | |
11205 LOCAL_SET_GL_ERROR( | |
11206 GL_INVALID_OPERATION, function_name, "level does not exist."); | |
11207 return false; | |
11208 } | |
11209 if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(), | |
11210 function_name, format, type, internal_format, level)) { | |
11211 return false; | |
11212 } | |
11213 if (type != current_type && !feature_info_->IsES3Enabled()) { | |
11214 LOCAL_SET_GL_ERROR( | |
11215 GL_INVALID_OPERATION, | |
11216 function_name, "type does not match type of texture."); | |
11217 return false; | |
11218 } | |
11219 if (!texture->ValidForTexture( | |
11220 target, level, xoffset, yoffset, 0, width, height, 1)) { | |
11221 LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions."); | |
11222 return false; | |
11223 } | |
11224 if ((GLES2Util::GetChannelsForFormat(format) & | |
11225 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 | |
11226 && !feature_info_->IsES3Enabled()) { | |
11227 LOCAL_SET_GL_ERROR( | |
11228 GL_INVALID_OPERATION, | |
11229 function_name, "can not supply data for depth or stencil textures"); | |
11230 return false; | |
11231 } | |
11232 if (data == NULL) { | |
11233 (*error) = error::kOutOfBounds; | |
11234 return false; | |
11235 } | |
11236 return true; | |
11237 } | |
11238 | |
11239 error::Error GLES2DecoderImpl::DoTexSubImage2D( | |
11240 GLenum target, | |
11241 GLint level, | |
11242 GLint xoffset, | |
11243 GLint yoffset, | |
11244 GLsizei width, | |
11245 GLsizei height, | |
11246 GLenum format, | |
11247 GLenum type, | |
11248 const void * data) { | |
11249 error::Error error = error::kNoError; | |
11250 if (!ValidateTexSubImage2D(&error, "glTexSubImage2D", target, level, | |
11251 xoffset, yoffset, width, height, format, type, data)) { | |
11252 return error; | |
11253 } | |
11254 TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget( | |
11255 &state_, target); | |
11256 Texture* texture = texture_ref->texture(); | |
11257 GLsizei tex_width = 0; | |
11258 GLsizei tex_height = 0; | |
11259 bool ok = texture->GetLevelSize( | |
11260 target, level, &tex_width, &tex_height, nullptr); | |
11261 DCHECK(ok); | |
11262 if (xoffset != 0 || yoffset != 0 || | |
11263 width != tex_width || height != tex_height) { | |
11264 gfx::Rect cleared_rect; | |
11265 if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level), | |
11266 gfx::Rect(xoffset, yoffset, width, height), | |
11267 &cleared_rect)) { | |
11268 DCHECK_GE(cleared_rect.size().GetArea(), | |
11269 texture->GetLevelClearedRect(target, level).size().GetArea()); | |
11270 texture_manager()->SetLevelClearedRect(texture_ref, target, level, | |
11271 cleared_rect); | |
11272 } else { | |
11273 // Otherwise clear part of texture level that is not already cleared. | |
11274 if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, | |
11275 level)) { | |
11276 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexSubImage2D", | |
11277 "dimensions too big"); | |
11278 return error::kNoError; | |
11279 } | |
11280 } | |
11281 ScopedTextureUploadTimer timer(&texture_state_); | |
11282 glTexSubImage2D( | |
11283 target, level, xoffset, yoffset, width, height, format, type, data); | |
11284 return error::kNoError; | |
11285 } | |
11286 | |
11287 if (!texture_state_.texsubimage_faster_than_teximage && | |
11288 !texture->IsImmutable() && | |
11289 !texture->HasImages()) { | |
11290 ScopedTextureUploadTimer timer(&texture_state_); | |
11291 GLenum internal_format; | |
11292 GLenum tex_type; | |
11293 texture->GetLevelType(target, level, &tex_type, &internal_format); | |
11294 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need | |
11295 // to look it up. | |
11296 glTexImage2D( | |
11297 target, level, internal_format, width, height, 0, format, type, data); | |
11298 } else { | |
11299 ScopedTextureUploadTimer timer(&texture_state_); | |
11300 glTexSubImage2D( | |
11301 target, level, xoffset, yoffset, width, height, format, type, data); | |
11302 } | |
11303 texture_manager()->SetLevelCleared(texture_ref, target, level, true); | |
11304 | |
11305 // This may be a slow command. Exit command processing to allow for | |
11306 // context preemption and GPU watchdog checks. | |
11307 ExitCommandProcessingEarly(); | |
11308 return error::kNoError; | |
11309 } | |
11310 | |
11311 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, | 11141 error::Error GLES2DecoderImpl::HandleTexSubImage2D(uint32 immediate_data_size, |
11312 const void* cmd_data) { | 11142 const void* cmd_data) { |
11313 const gles2::cmds::TexSubImage2D& c = | 11143 const gles2::cmds::TexSubImage2D& c = |
11314 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); | 11144 *static_cast<const gles2::cmds::TexSubImage2D*>(cmd_data); |
11315 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", | 11145 TRACE_EVENT2("gpu", "GLES2DecoderImpl::HandleTexSubImage2D", |
11316 "width", c.width, "height", c.height); | 11146 "width", c.width, "height", c.height); |
11317 GLboolean internal = static_cast<GLboolean>(c.internal); | 11147 GLboolean internal = static_cast<GLboolean>(c.internal); |
11318 if (internal == GL_TRUE && texture_state_.tex_image_failed) | 11148 if (internal == GL_TRUE && texture_state_.tex_image_failed) |
11319 return error::kNoError; | 11149 return error::kNoError; |
11320 | 11150 |
11321 GLenum target = static_cast<GLenum>(c.target); | 11151 GLenum target = static_cast<GLenum>(c.target); |
11322 GLint level = static_cast<GLint>(c.level); | 11152 GLint level = static_cast<GLint>(c.level); |
11323 GLint xoffset = static_cast<GLint>(c.xoffset); | 11153 GLint xoffset = static_cast<GLint>(c.xoffset); |
11324 GLint yoffset = static_cast<GLint>(c.yoffset); | 11154 GLint yoffset = static_cast<GLint>(c.yoffset); |
11325 GLsizei width = static_cast<GLsizei>(c.width); | 11155 GLsizei width = static_cast<GLsizei>(c.width); |
11326 GLsizei height = static_cast<GLsizei>(c.height); | 11156 GLsizei height = static_cast<GLsizei>(c.height); |
11327 GLenum format = static_cast<GLenum>(c.format); | 11157 GLenum format = static_cast<GLenum>(c.format); |
11328 GLenum type = static_cast<GLenum>(c.type); | 11158 GLenum type = static_cast<GLenum>(c.type); |
11329 uint32 data_size; | 11159 uint32 data_size; |
11330 if (!GLES2Util::ComputeImageDataSizes( | 11160 if (!GLES2Util::ComputeImageDataSizes( |
11331 width, height, 1, format, type, state_.unpack_alignment, &data_size, | 11161 width, height, 1, format, type, state_.unpack_alignment, &data_size, |
11332 NULL, NULL)) { | 11162 NULL, NULL)) { |
11333 return error::kOutOfBounds; | 11163 return error::kOutOfBounds; |
11334 } | 11164 } |
| 11165 |
11335 const void* pixels = GetSharedMemoryAs<const void*>( | 11166 const void* pixels = GetSharedMemoryAs<const void*>( |
11336 c.pixels_shm_id, c.pixels_shm_offset, data_size); | 11167 c.pixels_shm_id, c.pixels_shm_offset, data_size); |
11337 return DoTexSubImage2D( | 11168 if (!pixels) |
11338 target, level, xoffset, yoffset, width, height, format, type, pixels); | 11169 return error::kOutOfBounds; |
| 11170 |
| 11171 TextureManager::DoTexSubImageArguments args = { |
| 11172 target, level, xoffset, yoffset, width, |
| 11173 height, format, type, pixels, data_size}; |
| 11174 texture_manager()->ValidateAndDoTexSubImage(this, &texture_state_, &state_, |
| 11175 &framebuffer_state_, |
| 11176 "glTexSubImage2D", args); |
| 11177 |
| 11178 // This may be a slow command. Exit command processing to allow for |
| 11179 // context preemption and GPU watchdog checks. |
| 11180 ExitCommandProcessingEarly(); |
| 11181 return error::kNoError; |
11339 } | 11182 } |
11340 | 11183 |
11341 error::Error GLES2DecoderImpl::DoTexSubImage3D( | 11184 error::Error GLES2DecoderImpl::DoTexSubImage3D( |
11342 GLenum target, | 11185 GLenum target, |
11343 GLint level, | 11186 GLint level, |
11344 GLint xoffset, | 11187 GLint xoffset, |
11345 GLint yoffset, | 11188 GLint yoffset, |
11346 GLint zoffset, | 11189 GLint zoffset, |
11347 GLsizei width, | 11190 GLsizei width, |
11348 GLsizei height, | 11191 GLsizei height, |
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13266 } | 13109 } |
13267 | 13110 |
13268 int dest_width = 0; | 13111 int dest_width = 0; |
13269 int dest_height = 0; | 13112 int dest_height = 0; |
13270 bool ok = dest_texture->GetLevelSize( | 13113 bool ok = dest_texture->GetLevelSize( |
13271 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); | 13114 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); |
13272 DCHECK(ok); | 13115 DCHECK(ok); |
13273 if (xoffset != 0 || yoffset != 0 || width != dest_width || | 13116 if (xoffset != 0 || yoffset != 0 || width != dest_width || |
13274 height != dest_height) { | 13117 height != dest_height) { |
13275 gfx::Rect cleared_rect; | 13118 gfx::Rect cleared_rect; |
13276 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), | 13119 if (TextureManager::CombineAdjacentRects( |
13277 gfx::Rect(xoffset, yoffset, width, height), | 13120 dest_texture->GetLevelClearedRect(target, 0), |
13278 &cleared_rect)) { | 13121 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { |
13279 DCHECK_GE(cleared_rect.size().GetArea(), | 13122 DCHECK_GE(cleared_rect.size().GetArea(), |
13280 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); | 13123 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); |
13281 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, | 13124 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
13282 cleared_rect); | 13125 cleared_rect); |
13283 } else { | 13126 } else { |
13284 // Otherwise clear part of texture level that is not already cleared. | 13127 // Otherwise clear part of texture level that is not already cleared. |
13285 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, | 13128 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
13286 0)) { | 13129 0)) { |
13287 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", | 13130 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", |
13288 "destination texture dimensions too big"); | 13131 "destination texture dimensions too big"); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13604 } | 13447 } |
13605 | 13448 |
13606 int dest_width = 0; | 13449 int dest_width = 0; |
13607 int dest_height = 0; | 13450 int dest_height = 0; |
13608 bool ok = dest_texture->GetLevelSize( | 13451 bool ok = dest_texture->GetLevelSize( |
13609 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); | 13452 GL_TEXTURE_2D, 0, &dest_width, &dest_height, nullptr); |
13610 DCHECK(ok); | 13453 DCHECK(ok); |
13611 if (xoffset != 0 || yoffset != 0 || width != dest_width || | 13454 if (xoffset != 0 || yoffset != 0 || width != dest_width || |
13612 height != dest_height) { | 13455 height != dest_height) { |
13613 gfx::Rect cleared_rect; | 13456 gfx::Rect cleared_rect; |
13614 if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0), | 13457 if (TextureManager::CombineAdjacentRects( |
13615 gfx::Rect(xoffset, yoffset, width, height), | 13458 dest_texture->GetLevelClearedRect(target, 0), |
13616 &cleared_rect)) { | 13459 gfx::Rect(xoffset, yoffset, width, height), &cleared_rect)) { |
13617 DCHECK_GE(cleared_rect.size().GetArea(), | 13460 DCHECK_GE(cleared_rect.size().GetArea(), |
13618 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); | 13461 dest_texture->GetLevelClearedRect(target, 0).size().GetArea()); |
13619 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, | 13462 texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
13620 cleared_rect); | 13463 cleared_rect); |
13621 } else { | 13464 } else { |
13622 // Otherwise clear part of texture level that is not already cleared. | 13465 // Otherwise clear part of texture level that is not already cleared. |
13623 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, | 13466 if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
13624 0)) { | 13467 0)) { |
13625 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, | 13468 LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, |
13626 "glCompressedCopySubTextureCHROMIUM", | 13469 "glCompressedCopySubTextureCHROMIUM", |
(...skipping 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15600 return error::kNoError; | 15443 return error::kNoError; |
15601 } | 15444 } |
15602 | 15445 |
15603 // Include the auto-generated part of this file. We split this because it means | 15446 // Include the auto-generated part of this file. We split this because it means |
15604 // we can easily edit the non-auto generated parts right here in this file | 15447 // we can easily edit the non-auto generated parts right here in this file |
15605 // instead of having to edit some template or the code generator. | 15448 // instead of having to edit some template or the code generator. |
15606 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" | 15449 #include "gpu/command_buffer/service/gles2_cmd_decoder_autogen.h" |
15607 | 15450 |
15608 } // namespace gles2 | 15451 } // namespace gles2 |
15609 } // namespace gpu | 15452 } // namespace gpu |
OLD | NEW |