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/texture_manager.h" | 5 #include "gpu/command_buffer/service/texture_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 case GL_BLUE: | 295 case GL_BLUE: |
296 return swizzle->blue; | 296 return swizzle->blue; |
297 case GL_ALPHA: | 297 case GL_ALPHA: |
298 return swizzle->alpha; | 298 return swizzle->alpha; |
299 default: | 299 default: |
300 NOTREACHED(); | 300 NOTREACHED(); |
301 return GL_NONE; | 301 return GL_NONE; |
302 } | 302 } |
303 } | 303 } |
304 | 304 |
| 305 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint. |
| 306 GLuint ToGLuint(const void* ptr) { |
| 307 return static_cast<GLuint>(reinterpret_cast<size_t>(ptr)); |
| 308 } |
| 309 |
305 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = | 310 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = |
306 LAZY_INSTANCE_INITIALIZER; | 311 LAZY_INSTANCE_INITIALIZER; |
307 | 312 |
308 } // namespace anonymous | 313 } // namespace anonymous |
309 | 314 |
310 TextureManager::DestructionObserver::DestructionObserver() {} | 315 TextureManager::DestructionObserver::DestructionObserver() {} |
311 | 316 |
312 TextureManager::DestructionObserver::~DestructionObserver() {} | 317 TextureManager::DestructionObserver::~DestructionObserver() {} |
313 | 318 |
314 TextureManager::~TextureManager() { | 319 TextureManager::~TextureManager() { |
(...skipping 1899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2214 "unknown texture for target"); | 2219 "unknown texture for target"); |
2215 return false; | 2220 return false; |
2216 } | 2221 } |
2217 if (local_texture_ref->texture()->IsImmutable()) { | 2222 if (local_texture_ref->texture()->IsImmutable()) { |
2218 ERRORSTATE_SET_GL_ERROR( | 2223 ERRORSTATE_SET_GL_ERROR( |
2219 error_state, GL_INVALID_OPERATION, function_name, | 2224 error_state, GL_INVALID_OPERATION, function_name, |
2220 "texture is immutable"); | 2225 "texture is immutable"); |
2221 return false; | 2226 return false; |
2222 } | 2227 } |
2223 | 2228 |
| 2229 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); |
| 2230 if (buffer) { |
| 2231 if (buffer->GetMappedRange()) { |
| 2232 ERRORSTATE_SET_GL_ERROR( |
| 2233 error_state, GL_INVALID_OPERATION, function_name, |
| 2234 "pixel unpack buffer should not be mapped to client memory"); |
| 2235 return error::kNoError; |
| 2236 } |
| 2237 base::CheckedNumeric<uint32_t> size = args.pixels_size; |
| 2238 GLuint offset = ToGLuint(args.pixels); |
| 2239 size += offset; |
| 2240 if (!size.IsValid()) { |
| 2241 ERRORSTATE_SET_GL_ERROR( |
| 2242 error_state, GL_INVALID_VALUE, function_name, |
| 2243 "size + offset overflow"); |
| 2244 return error::kNoError; |
| 2245 } |
| 2246 uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); |
| 2247 if (buffer_size < size.ValueOrDefault(0)) { |
| 2248 ERRORSTATE_SET_GL_ERROR( |
| 2249 error_state, GL_INVALID_OPERATION, function_name, |
| 2250 "pixel unpack buffer is not large enough"); |
| 2251 return error::kNoError; |
| 2252 } |
| 2253 size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type); |
| 2254 DCHECK_LT(0u, type_size); |
| 2255 if (offset % type_size != 0) { |
| 2256 ERRORSTATE_SET_GL_ERROR( |
| 2257 error_state, GL_INVALID_OPERATION, function_name, |
| 2258 "offset is not evenly divisible by elements"); |
| 2259 return error::kNoError; |
| 2260 } |
| 2261 } |
| 2262 |
2224 if (!memory_type_tracker_->EnsureGPUMemoryAvailable(args.pixels_size)) { | 2263 if (!memory_type_tracker_->EnsureGPUMemoryAvailable(args.pixels_size)) { |
2225 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, | 2264 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, |
2226 "out of memory"); | 2265 "out of memory"); |
2227 return false; | 2266 return false; |
2228 } | 2267 } |
2229 | 2268 |
2230 // Write the TextureReference since this is valid. | 2269 // Write the TextureReference since this is valid. |
2231 *texture_ref = local_texture_ref; | 2270 *texture_ref = local_texture_ref; |
2232 return true; | 2271 return true; |
2233 } | 2272 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2278 ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY, | 2317 ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY, |
2279 function_name, "out of memory"); | 2318 function_name, "out of memory"); |
2280 return; | 2319 return; |
2281 } | 2320 } |
2282 DoTexImageArguments new_args = args; | 2321 DoTexImageArguments new_args = args; |
2283 scoped_ptr<char[]> zero(new char[args.pixels_size]); | 2322 scoped_ptr<char[]> zero(new char[args.pixels_size]); |
2284 memset(zero.get(), 0, args.pixels_size); | 2323 memset(zero.get(), 0, args.pixels_size); |
2285 for (GLenum face : undefined_faces) { | 2324 for (GLenum face : undefined_faces) { |
2286 new_args.target = face; | 2325 new_args.target = face; |
2287 new_args.pixels = zero.get(); | 2326 new_args.pixels = zero.get(); |
2288 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, | 2327 DoTexImage(texture_state, state, framebuffer_state, |
2289 function_name, texture_ref, new_args); | 2328 function_name, texture_ref, new_args); |
2290 texture->MarkLevelAsInternalWorkaround(face, args.level); | 2329 texture->MarkLevelAsInternalWorkaround(face, args.level); |
2291 } | 2330 } |
2292 } | 2331 } |
2293 | 2332 |
2294 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, | 2333 DoTexImage(texture_state, state, framebuffer_state, |
2295 function_name, texture_ref, args); | 2334 function_name, texture_ref, args); |
2296 } | 2335 } |
2297 | 2336 |
2298 bool TextureManager::ValidateTexSubImage(ContextState* state, | 2337 bool TextureManager::ValidateTexSubImage(ContextState* state, |
2299 const char* function_name, | 2338 const char* function_name, |
2300 const DoTexSubImageArguments& args, | 2339 const DoTexSubImageArguments& args, |
2301 TextureRef** texture_ref) { | 2340 TextureRef** texture_ref) { |
2302 ErrorState* error_state = state->GetErrorState(); | 2341 ErrorState* error_state = state->GetErrorState(); |
2303 const Validators* validators = feature_info_->validators(); | 2342 const Validators* validators = feature_info_->validators(); |
2304 | 2343 |
2305 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && | 2344 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && |
2306 !validators->texture_target.IsValid(args.target)) || | 2345 !validators->texture_target.IsValid(args.target)) || |
2307 (args.command_type == DoTexSubImageArguments::kTexSubImage3D && | 2346 (args.command_type == DoTexSubImageArguments::kTexSubImage3D && |
2308 !validators->texture_3_d_target.IsValid(args.target))) { | 2347 !validators->texture_3_d_target.IsValid(args.target))) { |
2309 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, | 2348 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, |
2310 args.target, "target"); | 2349 args.target, "target"); |
2311 return false; | 2350 return false; |
2312 } | 2351 } |
2313 if (args.width < 0) { | 2352 DCHECK(args.width >= 0 && args.height >= 0 && args.depth >= 0); |
2314 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | |
2315 "width < 0"); | |
2316 return false; | |
2317 } | |
2318 if (args.height < 0) { | |
2319 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | |
2320 "height < 0"); | |
2321 return false; | |
2322 } | |
2323 if (args.depth < 0) { | |
2324 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | |
2325 "depth < 0"); | |
2326 return false; | |
2327 } | |
2328 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); | 2353 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); |
2329 if (!local_texture_ref) { | 2354 if (!local_texture_ref) { |
2330 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, | 2355 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
2331 "unknown texture for target"); | 2356 "unknown texture for target"); |
2332 return false; | 2357 return false; |
2333 } | 2358 } |
2334 Texture* texture = local_texture_ref->texture(); | 2359 Texture* texture = local_texture_ref->texture(); |
2335 GLenum current_type = 0; | 2360 GLenum current_type = 0; |
2336 GLenum internal_format = 0; | 2361 GLenum internal_format = 0; |
2337 if (!texture->GetLevelType(args.target, args.level, ¤t_type, | 2362 if (!texture->GetLevelType(args.target, args.level, ¤t_type, |
(...skipping 21 matching lines...) Expand all Loading... |
2359 return false; | 2384 return false; |
2360 } | 2385 } |
2361 if ((GLES2Util::GetChannelsForFormat(args.format) & | 2386 if ((GLES2Util::GetChannelsForFormat(args.format) & |
2362 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && | 2387 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && |
2363 !feature_info_->IsES3Enabled()) { | 2388 !feature_info_->IsES3Enabled()) { |
2364 ERRORSTATE_SET_GL_ERROR( | 2389 ERRORSTATE_SET_GL_ERROR( |
2365 error_state, GL_INVALID_OPERATION, function_name, | 2390 error_state, GL_INVALID_OPERATION, function_name, |
2366 "can not supply data for depth or stencil textures"); | 2391 "can not supply data for depth or stencil textures"); |
2367 return false; | 2392 return false; |
2368 } | 2393 } |
2369 DCHECK(args.pixels); | 2394 |
| 2395 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); |
| 2396 if (buffer) { |
| 2397 if (buffer->GetMappedRange()) { |
| 2398 ERRORSTATE_SET_GL_ERROR( |
| 2399 error_state, GL_INVALID_OPERATION, function_name, |
| 2400 "pixel unpack buffer should not be mapped to client memory"); |
| 2401 return error::kNoError; |
| 2402 } |
| 2403 base::CheckedNumeric<uint32_t> size = args.pixels_size; |
| 2404 GLuint offset = ToGLuint(args.pixels); |
| 2405 size += offset; |
| 2406 if (!size.IsValid()) { |
| 2407 ERRORSTATE_SET_GL_ERROR( |
| 2408 error_state, GL_INVALID_VALUE, function_name, |
| 2409 "size + offset overflow"); |
| 2410 return error::kNoError; |
| 2411 } |
| 2412 uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); |
| 2413 if (buffer_size < size.ValueOrDefault(0)) { |
| 2414 ERRORSTATE_SET_GL_ERROR( |
| 2415 error_state, GL_INVALID_OPERATION, function_name, |
| 2416 "pixel unpack buffer is not large enough"); |
| 2417 return error::kNoError; |
| 2418 } |
| 2419 size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type); |
| 2420 DCHECK_LT(0u, type_size); |
| 2421 if (offset % type_size != 0) { |
| 2422 ERRORSTATE_SET_GL_ERROR( |
| 2423 error_state, GL_INVALID_OPERATION, function_name, |
| 2424 "offset is not evenly divisible by elements"); |
| 2425 return error::kNoError; |
| 2426 } |
| 2427 } |
2370 *texture_ref = local_texture_ref; | 2428 *texture_ref = local_texture_ref; |
2371 return true; | 2429 return true; |
2372 } | 2430 } |
2373 | 2431 |
2374 void TextureManager::ValidateAndDoTexSubImage( | 2432 void TextureManager::ValidateAndDoTexSubImage( |
2375 GLES2Decoder* decoder, | 2433 GLES2Decoder* decoder, |
2376 DecoderTextureState* texture_state, | 2434 DecoderTextureState* texture_state, |
2377 ContextState* state, | 2435 ContextState* state, |
2378 DecoderFramebufferState* framebuffer_state, | 2436 DecoderFramebufferState* framebuffer_state, |
2379 const char* function_name, | 2437 const char* function_name, |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2482 const Texture::CompatibilitySwizzle* swizzle = | 2540 const Texture::CompatibilitySwizzle* swizzle = |
2483 GetCompatibilitySwizzle(format); | 2541 GetCompatibilitySwizzle(format); |
2484 if (swizzle) | 2542 if (swizzle) |
2485 return swizzle->dest_format; | 2543 return swizzle->dest_format; |
2486 } | 2544 } |
2487 return format; | 2545 return format; |
2488 } | 2546 } |
2489 | 2547 |
2490 void TextureManager::DoTexImage( | 2548 void TextureManager::DoTexImage( |
2491 DecoderTextureState* texture_state, | 2549 DecoderTextureState* texture_state, |
2492 ErrorState* error_state, | 2550 ContextState* state, |
2493 DecoderFramebufferState* framebuffer_state, | 2551 DecoderFramebufferState* framebuffer_state, |
2494 const char* function_name, | 2552 const char* function_name, |
2495 TextureRef* texture_ref, | 2553 TextureRef* texture_ref, |
2496 const DoTexImageArguments& args) { | 2554 const DoTexImageArguments& args) { |
| 2555 ErrorState* error_state = state->GetErrorState(); |
2497 Texture* texture = texture_ref->texture(); | 2556 Texture* texture = texture_ref->texture(); |
2498 GLsizei tex_width = 0; | 2557 GLsizei tex_width = 0; |
2499 GLsizei tex_height = 0; | 2558 GLsizei tex_height = 0; |
2500 GLsizei tex_depth = 0; | 2559 GLsizei tex_depth = 0; |
2501 GLenum tex_type = 0; | 2560 GLenum tex_type = 0; |
2502 GLenum tex_internal_format = 0; | 2561 GLenum tex_internal_format = 0; |
2503 bool level_is_same = | 2562 bool level_is_same = |
2504 texture->GetLevelSize( | 2563 texture->GetLevelSize( |
2505 args.target, args.level, &tex_width, &tex_height, &tex_depth) && | 2564 args.target, args.level, &tex_width, &tex_height, &tex_depth) && |
2506 args.width == tex_width && args.height == tex_height && | 2565 args.width == tex_width && args.height == tex_height && |
2507 args.depth == tex_depth && | 2566 args.depth == tex_depth && |
2508 texture->GetLevelType( | 2567 texture->GetLevelType( |
2509 args.target, args.level, &tex_type, &tex_internal_format) && | 2568 args.target, args.level, &tex_type, &tex_internal_format) && |
2510 args.type == tex_type && args.internal_format == tex_internal_format; | 2569 args.type == tex_type && args.internal_format == tex_internal_format; |
2511 | 2570 |
2512 if (level_is_same && !args.pixels) { | 2571 bool unpack_buffer_bound = |
| 2572 (state->bound_pixel_unpack_buffer.get() != nullptr); |
| 2573 |
| 2574 if (level_is_same && !args.pixels && !unpack_buffer_bound) { |
2513 // Just set the level texture but mark the texture as uncleared. | 2575 // Just set the level texture but mark the texture as uncleared. |
2514 SetLevelInfo( | 2576 SetLevelInfo( |
2515 texture_ref, args.target, args.level, args.internal_format, args.width, | 2577 texture_ref, args.target, args.level, args.internal_format, args.width, |
2516 args.height, args.depth, args.border, args.format, args.type, | 2578 args.height, args.depth, args.border, args.format, args.type, |
2517 gfx::Rect()); | 2579 gfx::Rect()); |
2518 texture_state->tex_image_failed = false; | 2580 texture_state->tex_image_failed = false; |
2519 return; | 2581 return; |
2520 } | 2582 } |
2521 | 2583 |
2522 if (texture->IsAttachedToFramebuffer()) { | 2584 if (texture->IsAttachedToFramebuffer()) { |
2523 framebuffer_state->clear_state_dirty = true; | 2585 framebuffer_state->clear_state_dirty = true; |
2524 } | 2586 } |
2525 | 2587 |
2526 if (texture_state->texsubimage_faster_than_teximage && | 2588 if (texture_state->texsubimage_faster_than_teximage && |
2527 level_is_same && args.pixels) { | 2589 level_is_same && args.pixels && !unpack_buffer_bound) { |
2528 { | 2590 { |
2529 ScopedTextureUploadTimer timer(texture_state); | 2591 ScopedTextureUploadTimer timer(texture_state); |
2530 if (args.command_type == DoTexImageArguments::kTexImage3D) { | 2592 if (args.command_type == DoTexImageArguments::kTexImage3D) { |
2531 glTexSubImage3D(args.target, args.level, 0, 0, 0, | 2593 glTexSubImage3D(args.target, args.level, 0, 0, 0, |
2532 args.width, args.height, args.depth, | 2594 args.width, args.height, args.depth, |
2533 args.format, args.type, args.pixels); | 2595 args.format, args.type, args.pixels); |
2534 } else { | 2596 } else { |
2535 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, | 2597 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, |
2536 AdjustTexFormat(args.format), args.type, args.pixels); | 2598 AdjustTexFormat(args.format), args.type, args.pixels); |
2537 } | 2599 } |
(...skipping 21 matching lines...) Expand all Loading... |
2559 } | 2621 } |
2560 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); | 2622 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); |
2561 if (args.command_type == DoTexImageArguments::kTexImage3D) { | 2623 if (args.command_type == DoTexImageArguments::kTexImage3D) { |
2562 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage3D", error, | 2624 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage3D", error, |
2563 GetAllGLErrors()); | 2625 GetAllGLErrors()); |
2564 } else { | 2626 } else { |
2565 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage2D", error, | 2627 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage2D", error, |
2566 GetAllGLErrors()); | 2628 GetAllGLErrors()); |
2567 } | 2629 } |
2568 if (error == GL_NO_ERROR) { | 2630 if (error == GL_NO_ERROR) { |
2569 bool set_as_cleared = (args.pixels != nullptr); | 2631 bool set_as_cleared = (args.pixels != nullptr || unpack_buffer_bound); |
2570 SetLevelInfo( | 2632 SetLevelInfo( |
2571 texture_ref, args.target, args.level, args.internal_format, args.width, | 2633 texture_ref, args.target, args.level, args.internal_format, args.width, |
2572 args.height, args.depth, args.border, args.format, args.type, | 2634 args.height, args.depth, args.border, args.format, args.type, |
2573 set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); | 2635 set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
2574 texture->ApplyFormatWorkarounds(feature_info_.get()); | 2636 texture->ApplyFormatWorkarounds(feature_info_.get()); |
2575 texture_state->tex_image_failed = false; | 2637 texture_state->tex_image_failed = false; |
2576 } | 2638 } |
2577 } | 2639 } |
2578 | 2640 |
2579 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, | 2641 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2934 uint32_t TextureManager::GetServiceIdGeneration() const { | 2996 uint32_t TextureManager::GetServiceIdGeneration() const { |
2935 return current_service_id_generation_; | 2997 return current_service_id_generation_; |
2936 } | 2998 } |
2937 | 2999 |
2938 void TextureManager::IncrementServiceIdGeneration() { | 3000 void TextureManager::IncrementServiceIdGeneration() { |
2939 current_service_id_generation_++; | 3001 current_service_id_generation_++; |
2940 } | 3002 } |
2941 | 3003 |
2942 } // namespace gles2 | 3004 } // namespace gles2 |
2943 } // namespace gpu | 3005 } // namespace gpu |
OLD | NEW |