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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 (lhs.format == rhs.format) && | 256 (lhs.format == rhs.format) && |
257 (lhs.type < rhs.type))); | 257 (lhs.type < rhs.type))); |
258 } | 258 } |
259 }; | 259 }; |
260 | 260 |
261 // This class needs to be thread safe, so once supported_combinations_ | 261 // This class needs to be thread safe, so once supported_combinations_ |
262 // are initialized in the constructor, it should never be modified later. | 262 // are initialized in the constructor, it should never be modified later. |
263 std::set<FormatType, FormatTypeCompare> supported_combinations_; | 263 std::set<FormatType, FormatTypeCompare> supported_combinations_; |
264 }; | 264 }; |
265 | 265 |
266 // A 32-bit and 64-bit compatible way of converting a pointer to a GLuint. | |
267 GLuint ToGLuint(const void* ptr) { | |
268 return static_cast<GLuint>(reinterpret_cast<size_t>(ptr)); | |
269 } | |
270 | |
266 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = | 271 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator = |
267 LAZY_INSTANCE_INITIALIZER; | 272 LAZY_INSTANCE_INITIALIZER; |
268 | 273 |
269 } // namespace anonymous | 274 } // namespace anonymous |
270 | 275 |
271 TextureManager::DestructionObserver::DestructionObserver() {} | 276 TextureManager::DestructionObserver::DestructionObserver() {} |
272 | 277 |
273 TextureManager::DestructionObserver::~DestructionObserver() {} | 278 TextureManager::DestructionObserver::~DestructionObserver() {} |
274 | 279 |
275 TextureManager::~TextureManager() { | 280 TextureManager::~TextureManager() { |
(...skipping 1831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2107 "unknown texture for target"); | 2112 "unknown texture for target"); |
2108 return false; | 2113 return false; |
2109 } | 2114 } |
2110 if (local_texture_ref->texture()->IsImmutable()) { | 2115 if (local_texture_ref->texture()->IsImmutable()) { |
2111 ERRORSTATE_SET_GL_ERROR( | 2116 ERRORSTATE_SET_GL_ERROR( |
2112 error_state, GL_INVALID_OPERATION, function_name, | 2117 error_state, GL_INVALID_OPERATION, function_name, |
2113 "texture is immutable"); | 2118 "texture is immutable"); |
2114 return false; | 2119 return false; |
2115 } | 2120 } |
2116 | 2121 |
2122 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); | |
2123 if (buffer) { | |
2124 if (buffer->GetMappedRange()) { | |
2125 ERRORSTATE_SET_GL_ERROR( | |
2126 error_state, GL_INVALID_OPERATION, function_name, | |
2127 "pixel unpack buffer should not be mapped to client memory"); | |
2128 return error::kNoError; | |
2129 } | |
2130 base::CheckedNumeric<uint32_t> size = args.pixels_size; | |
2131 size += ToGLuint(args.pixels); | |
2132 if (!size.IsValid()) { | |
2133 ERRORSTATE_SET_GL_ERROR( | |
2134 error_state, GL_INVALID_VALUE, function_name, | |
2135 "size + offset overflow"); | |
2136 return error::kNoError; | |
2137 } | |
2138 uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); | |
2139 if (buffer_size < size.ValueOrDefault(0)) { | |
2140 ERRORSTATE_SET_GL_ERROR( | |
2141 error_state, GL_INVALID_OPERATION, function_name, | |
2142 "pixel unpack buffer is not large enough"); | |
2143 return error::kNoError; | |
2144 } | |
2145 size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type); | |
2146 DCHECK_LT(0u, type_size); | |
2147 if (buffer_size % type_size != 0) { | |
piman
2016/03/08 01:56:50
Why this check? The buffer size doesn't matter, as
Zhenyao Mo
2016/03/09 18:41:05
See ES Spec 3.0.4 page 113, under $3.7 -> Unpackin
piman
2016/03/09 18:52:05
I still don't get it. The 2 requirements are:
1- t
| |
2148 ERRORSTATE_SET_GL_ERROR( | |
2149 error_state, GL_INVALID_OPERATION, function_name, | |
2150 "buffer size is not evenly divisible by elements"); | |
2151 return error::kNoError; | |
2152 } | |
2153 } | |
2154 | |
2117 if (!memory_type_tracker_->EnsureGPUMemoryAvailable(args.pixels_size)) { | 2155 if (!memory_type_tracker_->EnsureGPUMemoryAvailable(args.pixels_size)) { |
2118 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, | 2156 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name, |
2119 "out of memory"); | 2157 "out of memory"); |
2120 return false; | 2158 return false; |
2121 } | 2159 } |
2122 | 2160 |
2123 // Write the TextureReference since this is valid. | 2161 // Write the TextureReference since this is valid. |
2124 *texture_ref = local_texture_ref; | 2162 *texture_ref = local_texture_ref; |
2125 return true; | 2163 return true; |
2126 } | 2164 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2171 ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY, | 2209 ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY, |
2172 function_name, "out of memory"); | 2210 function_name, "out of memory"); |
2173 return; | 2211 return; |
2174 } | 2212 } |
2175 DoTexImageArguments new_args = args; | 2213 DoTexImageArguments new_args = args; |
2176 scoped_ptr<char[]> zero(new char[args.pixels_size]); | 2214 scoped_ptr<char[]> zero(new char[args.pixels_size]); |
2177 memset(zero.get(), 0, args.pixels_size); | 2215 memset(zero.get(), 0, args.pixels_size); |
2178 for (GLenum face : undefined_faces) { | 2216 for (GLenum face : undefined_faces) { |
2179 new_args.target = face; | 2217 new_args.target = face; |
2180 new_args.pixels = zero.get(); | 2218 new_args.pixels = zero.get(); |
2181 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, | 2219 DoTexImage(texture_state, state, framebuffer_state, |
2182 function_name, texture_ref, new_args); | 2220 function_name, texture_ref, new_args); |
2183 texture->MarkLevelAsInternalWorkaround(face, args.level); | 2221 texture->MarkLevelAsInternalWorkaround(face, args.level); |
2184 } | 2222 } |
2185 } | 2223 } |
2186 | 2224 |
2187 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, | 2225 DoTexImage(texture_state, state, framebuffer_state, |
2188 function_name, texture_ref, args); | 2226 function_name, texture_ref, args); |
2189 } | 2227 } |
2190 | 2228 |
2191 bool TextureManager::ValidateTexSubImage(ContextState* state, | 2229 bool TextureManager::ValidateTexSubImage(ContextState* state, |
2192 const char* function_name, | 2230 const char* function_name, |
2193 const DoTexSubImageArguments& args, | 2231 const DoTexSubImageArguments& args, |
2194 TextureRef** texture_ref) { | 2232 TextureRef** texture_ref) { |
2195 ErrorState* error_state = state->GetErrorState(); | 2233 ErrorState* error_state = state->GetErrorState(); |
2196 const Validators* validators = feature_info_->validators(); | 2234 const Validators* validators = feature_info_->validators(); |
2197 | 2235 |
2198 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && | 2236 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && |
2199 !validators->texture_target.IsValid(args.target)) || | 2237 !validators->texture_target.IsValid(args.target)) || |
2200 (args.command_type == DoTexSubImageArguments::kTexSubImage3D && | 2238 (args.command_type == DoTexSubImageArguments::kTexSubImage3D && |
2201 !validators->texture_3_d_target.IsValid(args.target))) { | 2239 !validators->texture_3_d_target.IsValid(args.target))) { |
2202 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, | 2240 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, |
2203 args.target, "target"); | 2241 args.target, "target"); |
2204 return false; | 2242 return false; |
2205 } | 2243 } |
2206 if (args.width < 0) { | 2244 DCHECK(args.width >= 0 && args.height >= 0 && args.depth >= 0); |
2207 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | |
2208 "width < 0"); | |
2209 return false; | |
2210 } | |
2211 if (args.height < 0) { | |
2212 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | |
2213 "height < 0"); | |
2214 return false; | |
2215 } | |
2216 if (args.depth < 0) { | |
2217 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | |
2218 "depth < 0"); | |
2219 return false; | |
2220 } | |
2221 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); | 2245 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); |
2222 if (!local_texture_ref) { | 2246 if (!local_texture_ref) { |
2223 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, | 2247 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
2224 "unknown texture for target"); | 2248 "unknown texture for target"); |
2225 return false; | 2249 return false; |
2226 } | 2250 } |
2227 Texture* texture = local_texture_ref->texture(); | 2251 Texture* texture = local_texture_ref->texture(); |
2228 GLenum current_type = 0; | 2252 GLenum current_type = 0; |
2229 GLenum internal_format = 0; | 2253 GLenum internal_format = 0; |
2230 if (!texture->GetLevelType(args.target, args.level, ¤t_type, | 2254 if (!texture->GetLevelType(args.target, args.level, ¤t_type, |
(...skipping 21 matching lines...) Expand all Loading... | |
2252 return false; | 2276 return false; |
2253 } | 2277 } |
2254 if ((GLES2Util::GetChannelsForFormat(args.format) & | 2278 if ((GLES2Util::GetChannelsForFormat(args.format) & |
2255 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && | 2279 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && |
2256 !feature_info_->IsES3Enabled()) { | 2280 !feature_info_->IsES3Enabled()) { |
2257 ERRORSTATE_SET_GL_ERROR( | 2281 ERRORSTATE_SET_GL_ERROR( |
2258 error_state, GL_INVALID_OPERATION, function_name, | 2282 error_state, GL_INVALID_OPERATION, function_name, |
2259 "can not supply data for depth or stencil textures"); | 2283 "can not supply data for depth or stencil textures"); |
2260 return false; | 2284 return false; |
2261 } | 2285 } |
2262 DCHECK(args.pixels); | 2286 |
2287 Buffer* buffer = state->bound_pixel_unpack_buffer.get(); | |
2288 if (buffer) { | |
2289 if (buffer->GetMappedRange()) { | |
2290 ERRORSTATE_SET_GL_ERROR( | |
2291 error_state, GL_INVALID_OPERATION, function_name, | |
2292 "pixel unpack buffer should not be mapped to client memory"); | |
2293 return error::kNoError; | |
2294 } | |
2295 base::CheckedNumeric<uint32_t> size = args.pixels_size; | |
2296 size += ToGLuint(args.pixels); | |
2297 if (!size.IsValid()) { | |
2298 ERRORSTATE_SET_GL_ERROR( | |
2299 error_state, GL_INVALID_VALUE, function_name, | |
2300 "size + offset overflow"); | |
2301 return error::kNoError; | |
2302 } | |
2303 uint32_t buffer_size = static_cast<uint32_t>(buffer->size()); | |
2304 if (buffer_size < size.ValueOrDefault(0)) { | |
2305 ERRORSTATE_SET_GL_ERROR( | |
2306 error_state, GL_INVALID_OPERATION, function_name, | |
2307 "pixel unpack buffer is not large enough"); | |
2308 return error::kNoError; | |
2309 } | |
2310 size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type); | |
2311 DCHECK_LT(0u, type_size); | |
2312 if (buffer_size % type_size != 0) { | |
piman
2016/03/08 01:56:50
Same here
Zhenyao Mo
2016/03/09 18:41:05
Same answer. It is specified in a difference plac
| |
2313 ERRORSTATE_SET_GL_ERROR( | |
2314 error_state, GL_INVALID_OPERATION, function_name, | |
2315 "buffer size is not evenly divisible by elements"); | |
2316 return error::kNoError; | |
2317 } | |
2318 } | |
2263 *texture_ref = local_texture_ref; | 2319 *texture_ref = local_texture_ref; |
2264 return true; | 2320 return true; |
2265 } | 2321 } |
2266 | 2322 |
2267 void TextureManager::ValidateAndDoTexSubImage( | 2323 void TextureManager::ValidateAndDoTexSubImage( |
2268 GLES2Decoder* decoder, | 2324 GLES2Decoder* decoder, |
2269 DecoderTextureState* texture_state, | 2325 DecoderTextureState* texture_state, |
2270 ContextState* state, | 2326 ContextState* state, |
2271 DecoderFramebufferState* framebuffer_state, | 2327 DecoderFramebufferState* framebuffer_state, |
2272 const char* function_name, | 2328 const char* function_name, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2358 if (format == GL_SRGB_EXT) | 2414 if (format == GL_SRGB_EXT) |
2359 return GL_RGB; | 2415 return GL_RGB; |
2360 if (format == GL_SRGB_ALPHA_EXT) | 2416 if (format == GL_SRGB_ALPHA_EXT) |
2361 return GL_RGBA; | 2417 return GL_RGBA; |
2362 } | 2418 } |
2363 return format; | 2419 return format; |
2364 } | 2420 } |
2365 | 2421 |
2366 void TextureManager::DoTexImage( | 2422 void TextureManager::DoTexImage( |
2367 DecoderTextureState* texture_state, | 2423 DecoderTextureState* texture_state, |
2368 ErrorState* error_state, | 2424 ContextState* state, |
2369 DecoderFramebufferState* framebuffer_state, | 2425 DecoderFramebufferState* framebuffer_state, |
2370 const char* function_name, | 2426 const char* function_name, |
2371 TextureRef* texture_ref, | 2427 TextureRef* texture_ref, |
2372 const DoTexImageArguments& args) { | 2428 const DoTexImageArguments& args) { |
2429 ErrorState* error_state = state->GetErrorState(); | |
2373 Texture* texture = texture_ref->texture(); | 2430 Texture* texture = texture_ref->texture(); |
2374 GLsizei tex_width = 0; | 2431 GLsizei tex_width = 0; |
2375 GLsizei tex_height = 0; | 2432 GLsizei tex_height = 0; |
2376 GLsizei tex_depth = 0; | 2433 GLsizei tex_depth = 0; |
2377 GLenum tex_type = 0; | 2434 GLenum tex_type = 0; |
2378 GLenum tex_internal_format = 0; | 2435 GLenum tex_internal_format = 0; |
2379 bool level_is_same = | 2436 bool level_is_same = |
2380 texture->GetLevelSize( | 2437 texture->GetLevelSize( |
2381 args.target, args.level, &tex_width, &tex_height, &tex_depth) && | 2438 args.target, args.level, &tex_width, &tex_height, &tex_depth) && |
2382 args.width == tex_width && args.height == tex_height && | 2439 args.width == tex_width && args.height == tex_height && |
2383 args.depth == tex_depth && | 2440 args.depth == tex_depth && |
2384 texture->GetLevelType( | 2441 texture->GetLevelType( |
2385 args.target, args.level, &tex_type, &tex_internal_format) && | 2442 args.target, args.level, &tex_type, &tex_internal_format) && |
2386 args.type == tex_type && args.internal_format == tex_internal_format; | 2443 args.type == tex_type && args.internal_format == tex_internal_format; |
2387 | 2444 |
2388 if (level_is_same && !args.pixels) { | 2445 bool unpack_buffer_bound = |
2446 (state->bound_pixel_unpack_buffer.get() != nullptr); | |
2447 | |
2448 if (level_is_same && !args.pixels && !unpack_buffer_bound) { | |
2389 // Just set the level texture but mark the texture as uncleared. | 2449 // Just set the level texture but mark the texture as uncleared. |
2390 SetLevelInfo( | 2450 SetLevelInfo( |
2391 texture_ref, args.target, args.level, args.internal_format, args.width, | 2451 texture_ref, args.target, args.level, args.internal_format, args.width, |
2392 args.height, args.depth, args.border, args.format, args.type, | 2452 args.height, args.depth, args.border, args.format, args.type, |
2393 gfx::Rect()); | 2453 gfx::Rect()); |
2394 texture_state->tex_image_failed = false; | 2454 texture_state->tex_image_failed = false; |
2395 return; | 2455 return; |
2396 } | 2456 } |
2397 | 2457 |
2398 if (texture->IsAttachedToFramebuffer()) { | 2458 if (texture->IsAttachedToFramebuffer()) { |
2399 framebuffer_state->clear_state_dirty = true; | 2459 framebuffer_state->clear_state_dirty = true; |
2400 } | 2460 } |
2401 | 2461 |
2402 if (texture_state->texsubimage_faster_than_teximage && | 2462 if (texture_state->texsubimage_faster_than_teximage && |
2403 level_is_same && args.pixels) { | 2463 level_is_same && args.pixels && !unpack_buffer_bound) { |
2404 { | 2464 { |
2405 ScopedTextureUploadTimer timer(texture_state); | 2465 ScopedTextureUploadTimer timer(texture_state); |
2406 if (args.command_type == DoTexImageArguments::kTexImage3D) { | 2466 if (args.command_type == DoTexImageArguments::kTexImage3D) { |
2407 glTexSubImage3D(args.target, args.level, 0, 0, 0, | 2467 glTexSubImage3D(args.target, args.level, 0, 0, 0, |
2408 args.width, args.height, args.depth, | 2468 args.width, args.height, args.depth, |
2409 args.format, args.type, args.pixels); | 2469 args.format, args.type, args.pixels); |
2410 } else { | 2470 } else { |
2411 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, | 2471 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height, |
2412 AdjustTexFormat(args.format), args.type, args.pixels); | 2472 AdjustTexFormat(args.format), args.type, args.pixels); |
2413 } | 2473 } |
(...skipping 20 matching lines...) Expand all Loading... | |
2434 } | 2494 } |
2435 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); | 2495 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); |
2436 if (args.command_type == DoTexImageArguments::kTexImage3D) { | 2496 if (args.command_type == DoTexImageArguments::kTexImage3D) { |
2437 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage3D", error, | 2497 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage3D", error, |
2438 GetAllGLErrors()); | 2498 GetAllGLErrors()); |
2439 } else { | 2499 } else { |
2440 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage2D", error, | 2500 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage2D", error, |
2441 GetAllGLErrors()); | 2501 GetAllGLErrors()); |
2442 } | 2502 } |
2443 if (error == GL_NO_ERROR) { | 2503 if (error == GL_NO_ERROR) { |
2444 bool set_as_cleared = (args.pixels != nullptr); | 2504 bool set_as_cleared = (args.pixels != nullptr || unpack_buffer_bound); |
2445 SetLevelInfo( | 2505 SetLevelInfo( |
2446 texture_ref, args.target, args.level, args.internal_format, args.width, | 2506 texture_ref, args.target, args.level, args.internal_format, args.width, |
2447 args.height, args.depth, args.border, args.format, args.type, | 2507 args.height, args.depth, args.border, args.format, args.type, |
2448 set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); | 2508 set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
2449 texture_state->tex_image_failed = false; | 2509 texture_state->tex_image_failed = false; |
2450 } | 2510 } |
2451 } | 2511 } |
2452 | 2512 |
2453 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, | 2513 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, |
2454 const gfx::Rect& rect2, | 2514 const gfx::Rect& rect2, |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2808 uint32_t TextureManager::GetServiceIdGeneration() const { | 2868 uint32_t TextureManager::GetServiceIdGeneration() const { |
2809 return current_service_id_generation_; | 2869 return current_service_id_generation_; |
2810 } | 2870 } |
2811 | 2871 |
2812 void TextureManager::IncrementServiceIdGeneration() { | 2872 void TextureManager::IncrementServiceIdGeneration() { |
2813 current_service_id_generation_++; | 2873 current_service_id_generation_++; |
2814 } | 2874 } |
2815 | 2875 |
2816 } // namespace gles2 | 2876 } // namespace gles2 |
2817 } // namespace gpu | 2877 } // namespace gpu |
OLD | NEW |