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 <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bits.h" | 11 #include "base/bits.h" |
12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
15 #include "base/trace_event/memory_dump_manager.h" | 15 #include "base/trace_event/memory_dump_manager.h" |
16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
17 #include "gpu/command_buffer/service/context_state.h" | 17 #include "gpu/command_buffer/service/context_state.h" |
18 #include "gpu/command_buffer/service/error_state.h" | 18 #include "gpu/command_buffer/service/error_state.h" |
19 #include "gpu/command_buffer/service/feature_info.h" | 19 #include "gpu/command_buffer/service/feature_info.h" |
20 #include "gpu/command_buffer/service/framebuffer_manager.h" | 20 #include "gpu/command_buffer/service/framebuffer_manager.h" |
21 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 21 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
22 #include "gpu/command_buffer/service/mailbox_manager.h" | 22 #include "gpu/command_buffer/service/mailbox_manager.h" |
23 #include "gpu/command_buffer/service/memory_tracking.h" | 23 #include "gpu/command_buffer/service/memory_tracking.h" |
24 #include "ui/gl/gl_implementation.h" | 24 #include "ui/gl/gl_implementation.h" |
| 25 #include "ui/gl/gl_version_info.h" |
25 #include "ui/gl/trace_util.h" | 26 #include "ui/gl/trace_util.h" |
26 | 27 |
27 namespace gpu { | 28 namespace gpu { |
28 namespace gles2 { | 29 namespace gles2 { |
29 | 30 |
30 namespace { | 31 namespace { |
31 | 32 |
32 // This should contain everything to uniquely identify a Texture. | 33 // This should contain everything to uniquely identify a Texture. |
33 const char TextureTag[] = "|Texture|"; | 34 const char TextureTag[] = "|Texture|"; |
34 struct TextureSignature { | 35 struct TextureSignature { |
(...skipping 1960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1995 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, | 1996 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, |
1996 function_name, texture_ref, new_args); | 1997 function_name, texture_ref, new_args); |
1997 } | 1998 } |
1998 return; | 1999 return; |
1999 } | 2000 } |
2000 | 2001 |
2001 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, | 2002 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state, |
2002 function_name, texture_ref, args); | 2003 function_name, texture_ref, args); |
2003 } | 2004 } |
2004 | 2005 |
| 2006 bool TextureManager::ValidateTexSubImage(ContextState* state, |
| 2007 const char* function_name, |
| 2008 const DoTexSubImageArguments& args, |
| 2009 TextureRef** texture_ref) { |
| 2010 ErrorState* error_state = state->GetErrorState(); |
| 2011 const Validators* validators = feature_info_->validators(); |
| 2012 |
| 2013 if (!validators->texture_target.IsValid(args.target)) { |
| 2014 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, |
| 2015 args.target, "target"); |
| 2016 return false; |
| 2017 } |
| 2018 if (args.width < 0) { |
| 2019 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2020 "width < 0"); |
| 2021 return false; |
| 2022 } |
| 2023 if (args.height < 0) { |
| 2024 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2025 "height < 0"); |
| 2026 return false; |
| 2027 } |
| 2028 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); |
| 2029 if (!local_texture_ref) { |
| 2030 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
| 2031 "unknown texture for target"); |
| 2032 return false; |
| 2033 } |
| 2034 Texture* texture = local_texture_ref->texture(); |
| 2035 GLenum current_type = 0; |
| 2036 GLenum internal_format = 0; |
| 2037 if (!texture->GetLevelType(args.target, args.level, ¤t_type, |
| 2038 &internal_format)) { |
| 2039 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
| 2040 "level does not exist."); |
| 2041 return false; |
| 2042 } |
| 2043 if (!ValidateTextureParameters(error_state, function_name, args.format, |
| 2044 args.type, internal_format, args.level)) { |
| 2045 return false; |
| 2046 } |
| 2047 if (args.type != current_type && !feature_info_->IsES3Enabled()) { |
| 2048 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
| 2049 "type does not match type of texture."); |
| 2050 return false; |
| 2051 } |
| 2052 if (!texture->ValidForTexture(args.target, args.level, args.xoffset, |
| 2053 args.yoffset, 0, args.width, args.height, 1)) { |
| 2054 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2055 "bad dimensions."); |
| 2056 return false; |
| 2057 } |
| 2058 if ((GLES2Util::GetChannelsForFormat(args.format) & |
| 2059 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && |
| 2060 !feature_info_->IsES3Enabled()) { |
| 2061 ERRORSTATE_SET_GL_ERROR( |
| 2062 error_state, GL_INVALID_OPERATION, function_name, |
| 2063 "can not supply data for depth or stencil textures"); |
| 2064 return false; |
| 2065 } |
| 2066 DCHECK(args.pixels); |
| 2067 *texture_ref = local_texture_ref; |
| 2068 return true; |
| 2069 } |
| 2070 |
| 2071 void TextureManager::ValidateAndDoTexSubImage( |
| 2072 GLES2Decoder* decoder, |
| 2073 DecoderTextureState* texture_state, |
| 2074 ContextState* state, |
| 2075 DecoderFramebufferState* framebuffer_state, |
| 2076 const char* function_name, |
| 2077 const DoTexSubImageArguments& args) { |
| 2078 ErrorState* error_state = state->GetErrorState(); |
| 2079 TextureRef* texture_ref; |
| 2080 if (!ValidateTexSubImage(state, function_name, args, &texture_ref)) { |
| 2081 return; |
| 2082 } |
| 2083 |
| 2084 Texture* texture = texture_ref->texture(); |
| 2085 GLsizei tex_width = 0; |
| 2086 GLsizei tex_height = 0; |
| 2087 bool ok = texture->GetLevelSize(args.target, args.level, &tex_width, |
| 2088 &tex_height, nullptr); |
| 2089 DCHECK(ok); |
| 2090 if (args.xoffset != 0 || args.yoffset != 0 || args.width != tex_width || |
| 2091 args.height != tex_height) { |
| 2092 gfx::Rect cleared_rect; |
| 2093 if (CombineAdjacentRects( |
| 2094 texture->GetLevelClearedRect(args.target, args.level), |
| 2095 gfx::Rect(args.xoffset, args.yoffset, args.width, args.height), |
| 2096 &cleared_rect)) { |
| 2097 DCHECK_GE(cleared_rect.size().GetArea(), |
| 2098 texture->GetLevelClearedRect(args.target, args.level) |
| 2099 .size() |
| 2100 .GetArea()); |
| 2101 SetLevelClearedRect(texture_ref, args.target, args.level, cleared_rect); |
| 2102 } else { |
| 2103 // Otherwise clear part of texture level that is not already cleared. |
| 2104 if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) { |
| 2105 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, |
| 2106 "glTexSubImage2D", "dimensions too big"); |
| 2107 return; |
| 2108 } |
| 2109 } |
| 2110 ScopedTextureUploadTimer timer(texture_state); |
| 2111 glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, |
| 2112 args.width, args.height, AdjustTexFormat(args.format), |
| 2113 args.type, args.pixels); |
| 2114 return; |
| 2115 } |
| 2116 |
| 2117 if (!texture_state->texsubimage_faster_than_teximage && |
| 2118 !texture->IsImmutable() && !texture->HasImages()) { |
| 2119 ScopedTextureUploadTimer timer(texture_state); |
| 2120 GLenum internal_format; |
| 2121 GLenum tex_type; |
| 2122 texture->GetLevelType(args.target, args.level, &tex_type, &internal_format); |
| 2123 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need |
| 2124 // to look it up. |
| 2125 glTexImage2D(args.target, args.level, internal_format, args.width, |
| 2126 args.height, 0, AdjustTexFormat(args.format), args.type, |
| 2127 args.pixels); |
| 2128 } else { |
| 2129 ScopedTextureUploadTimer timer(texture_state); |
| 2130 glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, |
| 2131 args.width, args.height, AdjustTexFormat(args.format), |
| 2132 args.type, args.pixels); |
| 2133 } |
| 2134 SetLevelCleared(texture_ref, args.target, args.level, true); |
| 2135 return; |
| 2136 } |
| 2137 |
2005 GLenum TextureManager::AdjustTexFormat(GLenum format) const { | 2138 GLenum TextureManager::AdjustTexFormat(GLenum format) const { |
2006 // TODO(bajones): GLES 3 allows for internal format and format to differ. | 2139 // TODO(bajones): GLES 3 allows for internal format and format to differ. |
2007 // This logic may need to change as a result. | 2140 // This logic may need to change as a result. |
2008 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { | 2141 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { |
2009 if (format == GL_SRGB_EXT) | 2142 if (format == GL_SRGB_EXT) |
2010 return GL_RGB; | 2143 return GL_RGB; |
2011 if (format == GL_SRGB_ALPHA_EXT) | 2144 if (format == GL_SRGB_ALPHA_EXT) |
2012 return GL_RGBA; | 2145 return GL_RGBA; |
2013 } | 2146 } |
2014 return format; | 2147 return format; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2082 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); | 2215 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); |
2083 if (error == GL_NO_ERROR) { | 2216 if (error == GL_NO_ERROR) { |
2084 SetLevelInfo( | 2217 SetLevelInfo( |
2085 texture_ref, args.target, args.level, args.internal_format, args.width, | 2218 texture_ref, args.target, args.level, args.internal_format, args.width, |
2086 args.height, args.depth, args.border, args.format, args.type, | 2219 args.height, args.depth, args.border, args.format, args.type, |
2087 args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); | 2220 args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
2088 texture_state->tex_image_failed = false; | 2221 texture_state->tex_image_failed = false; |
2089 } | 2222 } |
2090 } | 2223 } |
2091 | 2224 |
| 2225 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, |
| 2226 const gfx::Rect& rect2, |
| 2227 gfx::Rect* result) { |
| 2228 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|. |
| 2229 if (rect1.IsEmpty() || rect2.Contains(rect1)) { |
| 2230 *result = rect2; |
| 2231 return true; |
| 2232 } |
| 2233 |
| 2234 // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|. |
| 2235 if (rect2.IsEmpty() || rect1.Contains(rect2)) { |
| 2236 *result = rect1; |
| 2237 return true; |
| 2238 } |
| 2239 |
| 2240 // Return the union of |rect1| and |rect2| if they share an edge. |
| 2241 if (rect1.SharesEdgeWith(rect2)) { |
| 2242 *result = gfx::UnionRects(rect1, rect2); |
| 2243 return true; |
| 2244 } |
| 2245 |
| 2246 // Return false if it's not possible to combine |rect1| and |rect2|. |
| 2247 return false; |
| 2248 } |
| 2249 |
2092 ScopedTextureUploadTimer::ScopedTextureUploadTimer( | 2250 ScopedTextureUploadTimer::ScopedTextureUploadTimer( |
2093 DecoderTextureState* texture_state) | 2251 DecoderTextureState* texture_state) |
2094 : texture_state_(texture_state), | 2252 : texture_state_(texture_state), |
2095 begin_time_(base::TimeTicks::Now()) { | 2253 begin_time_(base::TimeTicks::Now()) { |
2096 } | 2254 } |
2097 | 2255 |
2098 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { | 2256 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { |
2099 texture_state_->texture_upload_count++; | 2257 texture_state_->texture_upload_count++; |
2100 texture_state_->total_texture_upload_time += | 2258 texture_state_->total_texture_upload_time += |
2101 base::TimeTicks::Now() - begin_time_; | 2259 base::TimeTicks::Now() - begin_time_; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2160 pmd->AddOwnershipEdge(client_guid, service_guid, importance); | 2318 pmd->AddOwnershipEdge(client_guid, service_guid, importance); |
2161 | 2319 |
2162 // Dump all sub-levels held by the texture. They will appear below the main | 2320 // Dump all sub-levels held by the texture. They will appear below the main |
2163 // gl/textures/client_X/texture_Y dump. | 2321 // gl/textures/client_X/texture_Y dump. |
2164 ref->texture()->DumpLevelMemory(pmd, memory_tracker_->ClientTracingId(), | 2322 ref->texture()->DumpLevelMemory(pmd, memory_tracker_->ClientTracingId(), |
2165 dump_name); | 2323 dump_name); |
2166 } | 2324 } |
2167 | 2325 |
2168 } // namespace gles2 | 2326 } // namespace gles2 |
2169 } // namespace gpu | 2327 } // namespace gpu |
OLD | NEW |