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