| 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 1832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1843 return NULL; | 1843 return NULL; |
| 1844 } | 1844 } |
| 1845 | 1845 |
| 1846 GLsizei TextureManager::ComputeMipMapCount(GLenum target, | 1846 GLsizei TextureManager::ComputeMipMapCount(GLenum target, |
| 1847 GLsizei width, | 1847 GLsizei width, |
| 1848 GLsizei height, | 1848 GLsizei height, |
| 1849 GLsizei depth) { | 1849 GLsizei depth) { |
| 1850 switch (target) { | 1850 switch (target) { |
| 1851 case GL_TEXTURE_EXTERNAL_OES: | 1851 case GL_TEXTURE_EXTERNAL_OES: |
| 1852 return 1; | 1852 return 1; |
| 1853 case GL_TEXTURE_3D: |
| 1854 return 1 + |
| 1855 base::bits::Log2Floor(std::max(std::max(width, height), depth)); |
| 1853 default: | 1856 default: |
| 1854 return 1 + | 1857 return 1 + |
| 1855 base::bits::Log2Floor(std::max(std::max(width, height), depth)); | 1858 base::bits::Log2Floor(std::max(width, height)); |
| 1856 } | 1859 } |
| 1857 } | 1860 } |
| 1858 | 1861 |
| 1859 void TextureManager::SetLevelImage(TextureRef* ref, | 1862 void TextureManager::SetLevelImage(TextureRef* ref, |
| 1860 GLenum target, | 1863 GLenum target, |
| 1861 GLint level, | 1864 GLint level, |
| 1862 gl::GLImage* image, | 1865 gl::GLImage* image, |
| 1863 Texture::ImageState state) { | 1866 Texture::ImageState state) { |
| 1864 DCHECK(ref); | 1867 DCHECK(ref); |
| 1865 ref->texture()->SetLevelImage(target, level, image, state); | 1868 ref->texture()->SetLevelImage(target, level, image, state); |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2120 function_name, texture_ref, args); | 2123 function_name, texture_ref, args); |
| 2121 } | 2124 } |
| 2122 | 2125 |
| 2123 bool TextureManager::ValidateTexSubImage(ContextState* state, | 2126 bool TextureManager::ValidateTexSubImage(ContextState* state, |
| 2124 const char* function_name, | 2127 const char* function_name, |
| 2125 const DoTexSubImageArguments& args, | 2128 const DoTexSubImageArguments& args, |
| 2126 TextureRef** texture_ref) { | 2129 TextureRef** texture_ref) { |
| 2127 ErrorState* error_state = state->GetErrorState(); | 2130 ErrorState* error_state = state->GetErrorState(); |
| 2128 const Validators* validators = feature_info_->validators(); | 2131 const Validators* validators = feature_info_->validators(); |
| 2129 | 2132 |
| 2130 if (!validators->texture_target.IsValid(args.target)) { | 2133 if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D && |
| 2134 !validators->texture_target.IsValid(args.target)) || |
| 2135 (args.command_type == DoTexSubImageArguments::kTexSubImage3D && |
| 2136 !validators->texture_3_d_target.IsValid(args.target))) { |
| 2131 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, | 2137 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name, |
| 2132 args.target, "target"); | 2138 args.target, "target"); |
| 2133 return false; | 2139 return false; |
| 2134 } | 2140 } |
| 2135 if (args.width < 0) { | 2141 if (args.width < 0) { |
| 2136 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | 2142 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2137 "width < 0"); | 2143 "width < 0"); |
| 2138 return false; | 2144 return false; |
| 2139 } | 2145 } |
| 2140 if (args.height < 0) { | 2146 if (args.height < 0) { |
| 2141 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | 2147 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2142 "height < 0"); | 2148 "height < 0"); |
| 2143 return false; | 2149 return false; |
| 2144 } | 2150 } |
| 2151 if (args.depth < 0) { |
| 2152 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2153 "depth < 0"); |
| 2154 return false; |
| 2155 } |
| 2145 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); | 2156 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target); |
| 2146 if (!local_texture_ref) { | 2157 if (!local_texture_ref) { |
| 2147 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, | 2158 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
| 2148 "unknown texture for target"); | 2159 "unknown texture for target"); |
| 2149 return false; | 2160 return false; |
| 2150 } | 2161 } |
| 2151 Texture* texture = local_texture_ref->texture(); | 2162 Texture* texture = local_texture_ref->texture(); |
| 2152 GLenum current_type = 0; | 2163 GLenum current_type = 0; |
| 2153 GLenum internal_format = 0; | 2164 GLenum internal_format = 0; |
| 2154 if (!texture->GetLevelType(args.target, args.level, ¤t_type, | 2165 if (!texture->GetLevelType(args.target, args.level, ¤t_type, |
| 2155 &internal_format)) { | 2166 &internal_format)) { |
| 2156 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, | 2167 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
| 2157 "level does not exist."); | 2168 "level does not exist."); |
| 2158 return false; | 2169 return false; |
| 2159 } | 2170 } |
| 2160 if (!ValidateTextureParameters(error_state, function_name, args.format, | 2171 if (!ValidateTextureParameters(error_state, function_name, args.format, |
| 2161 args.type, internal_format, args.level)) { | 2172 args.type, internal_format, args.level)) { |
| 2162 return false; | 2173 return false; |
| 2163 } | 2174 } |
| 2164 if (args.type != current_type && !feature_info_->IsES3Enabled()) { | 2175 if (args.type != current_type && !feature_info_->IsES3Enabled()) { |
| 2176 // It isn't explicitly required in the ES2 spec, but some drivers generate |
| 2177 // an error. It is better to be consistent across drivers. |
| 2165 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, | 2178 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name, |
| 2166 "type does not match type of texture."); | 2179 "type does not match type of texture."); |
| 2167 return false; | 2180 return false; |
| 2168 } | 2181 } |
| 2169 if (!texture->ValidForTexture(args.target, args.level, args.xoffset, | 2182 if (!texture->ValidForTexture(args.target, args.level, |
| 2170 args.yoffset, 0, args.width, args.height, 1)) { | 2183 args.xoffset, args.yoffset, args.zoffset, |
| 2184 args.width, args.height, args.depth)) { |
| 2171 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, | 2185 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name, |
| 2172 "bad dimensions."); | 2186 "bad dimensions."); |
| 2173 return false; | 2187 return false; |
| 2174 } | 2188 } |
| 2175 if ((GLES2Util::GetChannelsForFormat(args.format) & | 2189 if ((GLES2Util::GetChannelsForFormat(args.format) & |
| 2176 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && | 2190 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && |
| 2177 !feature_info_->IsES3Enabled()) { | 2191 !feature_info_->IsES3Enabled()) { |
| 2178 ERRORSTATE_SET_GL_ERROR( | 2192 ERRORSTATE_SET_GL_ERROR( |
| 2179 error_state, GL_INVALID_OPERATION, function_name, | 2193 error_state, GL_INVALID_OPERATION, function_name, |
| 2180 "can not supply data for depth or stencil textures"); | 2194 "can not supply data for depth or stencil textures"); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2194 const DoTexSubImageArguments& args) { | 2208 const DoTexSubImageArguments& args) { |
| 2195 ErrorState* error_state = state->GetErrorState(); | 2209 ErrorState* error_state = state->GetErrorState(); |
| 2196 TextureRef* texture_ref; | 2210 TextureRef* texture_ref; |
| 2197 if (!ValidateTexSubImage(state, function_name, args, &texture_ref)) { | 2211 if (!ValidateTexSubImage(state, function_name, args, &texture_ref)) { |
| 2198 return; | 2212 return; |
| 2199 } | 2213 } |
| 2200 | 2214 |
| 2201 Texture* texture = texture_ref->texture(); | 2215 Texture* texture = texture_ref->texture(); |
| 2202 GLsizei tex_width = 0; | 2216 GLsizei tex_width = 0; |
| 2203 GLsizei tex_height = 0; | 2217 GLsizei tex_height = 0; |
| 2218 GLsizei tex_depth = 0; |
| 2204 bool ok = texture->GetLevelSize(args.target, args.level, &tex_width, | 2219 bool ok = texture->GetLevelSize(args.target, args.level, &tex_width, |
| 2205 &tex_height, nullptr); | 2220 &tex_height, &tex_depth); |
| 2206 DCHECK(ok); | 2221 DCHECK(ok); |
| 2207 if (args.xoffset != 0 || args.yoffset != 0 || args.width != tex_width || | 2222 if (args.xoffset != 0 || args.yoffset != 0 || args.zoffset != 0 || |
| 2208 args.height != tex_height) { | 2223 args.width != tex_width || args.height != tex_height || |
| 2224 args.depth != tex_depth) { |
| 2225 // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. |
| 2209 gfx::Rect cleared_rect; | 2226 gfx::Rect cleared_rect; |
| 2210 if (CombineAdjacentRects( | 2227 if (CombineAdjacentRects( |
| 2211 texture->GetLevelClearedRect(args.target, args.level), | 2228 texture->GetLevelClearedRect(args.target, args.level), |
| 2212 gfx::Rect(args.xoffset, args.yoffset, args.width, args.height), | 2229 gfx::Rect(args.xoffset, args.yoffset, args.width, args.height), |
| 2213 &cleared_rect)) { | 2230 &cleared_rect)) { |
| 2214 DCHECK_GE(cleared_rect.size().GetArea(), | 2231 DCHECK_GE(cleared_rect.size().GetArea(), |
| 2215 texture->GetLevelClearedRect(args.target, args.level) | 2232 texture->GetLevelClearedRect(args.target, args.level) |
| 2216 .size() | 2233 .size() |
| 2217 .GetArea()); | 2234 .GetArea()); |
| 2218 SetLevelClearedRect(texture_ref, args.target, args.level, cleared_rect); | 2235 SetLevelClearedRect(texture_ref, args.target, args.level, cleared_rect); |
| 2219 } else { | 2236 } else { |
| 2220 // Otherwise clear part of texture level that is not already cleared. | 2237 // Otherwise clear part of texture level that is not already cleared. |
| 2221 if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) { | 2238 if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) { |
| 2222 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, | 2239 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, |
| 2223 "glTexSubImage2D", "dimensions too big"); | 2240 function_name, "dimensions too big"); |
| 2224 return; | 2241 return; |
| 2225 } | 2242 } |
| 2226 } | 2243 } |
| 2227 ScopedTextureUploadTimer timer(texture_state); | 2244 ScopedTextureUploadTimer timer(texture_state); |
| 2228 glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, | 2245 if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { |
| 2229 args.width, args.height, AdjustTexFormat(args.format), | 2246 glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset, |
| 2230 args.type, args.pixels); | 2247 args.zoffset, args.width, args.height, args.depth, |
| 2231 return; | 2248 AdjustTexFormat(args.format), args.type, args.pixels); |
| 2249 } else { |
| 2250 glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, |
| 2251 args.width, args.height, AdjustTexFormat(args.format), |
| 2252 args.type, args.pixels); |
| 2253 return; |
| 2254 } |
| 2232 } | 2255 } |
| 2233 | 2256 |
| 2234 if (!texture_state->texsubimage_faster_than_teximage && | 2257 if (!texture_state->texsubimage_faster_than_teximage && |
| 2235 !texture->IsImmutable() && !texture->HasImages()) { | 2258 !texture->IsImmutable() && !texture->HasImages()) { |
| 2236 ScopedTextureUploadTimer timer(texture_state); | 2259 ScopedTextureUploadTimer timer(texture_state); |
| 2237 GLenum internal_format; | 2260 GLenum internal_format; |
| 2238 GLenum tex_type; | 2261 GLenum tex_type; |
| 2239 texture->GetLevelType(args.target, args.level, &tex_type, &internal_format); | 2262 texture->GetLevelType(args.target, args.level, &tex_type, &internal_format); |
| 2240 // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need | 2263 // NOTE: In OpenGL ES 2/3 border is always zero. If that changes we'll need |
| 2241 // to look it up. | 2264 // to look it up. |
| 2242 glTexImage2D(args.target, args.level, internal_format, args.width, | 2265 if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { |
| 2243 args.height, 0, AdjustTexFormat(args.format), args.type, | 2266 glTexImage3D(args.target, args.level, internal_format, args.width, |
| 2244 args.pixels); | 2267 args.height, args.depth, 0, AdjustTexFormat(args.format), |
| 2268 args.type, args.pixels); |
| 2269 } else { |
| 2270 glTexImage2D(args.target, args.level, internal_format, args.width, |
| 2271 args.height, 0, AdjustTexFormat(args.format), args.type, |
| 2272 args.pixels); |
| 2273 } |
| 2245 } else { | 2274 } else { |
| 2246 ScopedTextureUploadTimer timer(texture_state); | 2275 ScopedTextureUploadTimer timer(texture_state); |
| 2247 glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, | 2276 if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) { |
| 2248 args.width, args.height, AdjustTexFormat(args.format), | 2277 glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset, |
| 2249 args.type, args.pixels); | 2278 args.zoffset, args.width, args.height, args.depth, |
| 2279 AdjustTexFormat(args.format), args.type, args.pixels); |
| 2280 } else { |
| 2281 glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset, |
| 2282 args.width, args.height, AdjustTexFormat(args.format), |
| 2283 args.type, args.pixels); |
| 2284 } |
| 2250 } | 2285 } |
| 2251 SetLevelCleared(texture_ref, args.target, args.level, true); | 2286 SetLevelCleared(texture_ref, args.target, args.level, true); |
| 2252 return; | 2287 return; |
| 2253 } | 2288 } |
| 2254 | 2289 |
| 2255 GLenum TextureManager::AdjustTexFormat(GLenum format) const { | 2290 GLenum TextureManager::AdjustTexFormat(GLenum format) const { |
| 2256 // TODO(bajones): GLES 3 allows for internal format and format to differ. | 2291 // TODO(bajones): GLES 3 allows for internal format and format to differ. |
| 2257 // This logic may need to change as a result. | 2292 // This logic may need to change as a result. |
| 2258 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { | 2293 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { |
| 2259 if (format == GL_SRGB_EXT) | 2294 if (format == GL_SRGB_EXT) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2280 bool level_is_same = | 2315 bool level_is_same = |
| 2281 texture->GetLevelSize( | 2316 texture->GetLevelSize( |
| 2282 args.target, args.level, &tex_width, &tex_height, &tex_depth) && | 2317 args.target, args.level, &tex_width, &tex_height, &tex_depth) && |
| 2283 texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) && | 2318 texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) && |
| 2284 args.width == tex_width && args.height == tex_height && | 2319 args.width == tex_width && args.height == tex_height && |
| 2285 args.depth == tex_depth && args.type == tex_type && | 2320 args.depth == tex_depth && args.type == tex_type && |
| 2286 args.format == tex_format; | 2321 args.format == tex_format; |
| 2287 | 2322 |
| 2288 if (level_is_same && !args.pixels) { | 2323 if (level_is_same && !args.pixels) { |
| 2289 // Just set the level texture but mark the texture as uncleared. | 2324 // Just set the level texture but mark the texture as uncleared. |
| 2290 SetLevelInfo(texture_ref, args.target, args.level, args.internal_format, | 2325 // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. |
| 2291 args.width, args.height, args.depth, args.border, args.format, | 2326 bool set_as_cleared = |
| 2292 args.type, gfx::Rect()); | 2327 (args.command_type == DoTexImageArguments::kTexImage3D); |
| 2328 SetLevelInfo( |
| 2329 texture_ref, args.target, args.level, args.internal_format, args.width, |
| 2330 args.height, args.depth, args.border, args.format, args.type, |
| 2331 set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
| 2293 texture_state->tex_image_failed = false; | 2332 texture_state->tex_image_failed = false; |
| 2294 return; | 2333 return; |
| 2295 } | 2334 } |
| 2296 | 2335 |
| 2297 if (texture->IsAttachedToFramebuffer()) { | 2336 if (texture->IsAttachedToFramebuffer()) { |
| 2298 framebuffer_state->clear_state_dirty = true; | 2337 framebuffer_state->clear_state_dirty = true; |
| 2299 } | 2338 } |
| 2300 | 2339 |
| 2301 if (texture_state->texsubimage_faster_than_teximage && | 2340 if (texture_state->texsubimage_faster_than_teximage && |
| 2302 level_is_same && args.pixels) { | 2341 level_is_same && args.pixels) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2333 } | 2372 } |
| 2334 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); | 2373 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); |
| 2335 if (args.command_type == DoTexImageArguments::kTexImage3D) { | 2374 if (args.command_type == DoTexImageArguments::kTexImage3D) { |
| 2336 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage3D", error, | 2375 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage3D", error, |
| 2337 GetAllGLErrors()); | 2376 GetAllGLErrors()); |
| 2338 } else { | 2377 } else { |
| 2339 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage2D", error, | 2378 UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error.TexImage2D", error, |
| 2340 GetAllGLErrors()); | 2379 GetAllGLErrors()); |
| 2341 } | 2380 } |
| 2342 if (error == GL_NO_ERROR) { | 2381 if (error == GL_NO_ERROR) { |
| 2382 // TODO(zmo): Implement clearing of 3D textures. crbug.com/597201. |
| 2383 bool set_as_cleared = (args.pixels != nullptr || |
| 2384 args.command_type == DoTexImageArguments::kTexImage3D); |
| 2343 SetLevelInfo( | 2385 SetLevelInfo( |
| 2344 texture_ref, args.target, args.level, args.internal_format, args.width, | 2386 texture_ref, args.target, args.level, args.internal_format, args.width, |
| 2345 args.height, args.depth, args.border, args.format, args.type, | 2387 args.height, args.depth, args.border, args.format, args.type, |
| 2346 args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); | 2388 set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
| 2347 texture_state->tex_image_failed = false; | 2389 texture_state->tex_image_failed = false; |
| 2348 } | 2390 } |
| 2349 } | 2391 } |
| 2350 | 2392 |
| 2351 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, | 2393 bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1, |
| 2352 const gfx::Rect& rect2, | 2394 const gfx::Rect& rect2, |
| 2353 gfx::Rect* result) { | 2395 gfx::Rect* result) { |
| 2354 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|. | 2396 // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|. |
| 2355 if (rect1.IsEmpty() || rect2.Contains(rect1)) { | 2397 if (rect1.IsEmpty() || rect2.Contains(rect1)) { |
| 2356 *result = rect2; | 2398 *result = rect2; |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2706 uint32_t TextureManager::GetServiceIdGeneration() const { | 2748 uint32_t TextureManager::GetServiceIdGeneration() const { |
| 2707 return current_service_id_generation_; | 2749 return current_service_id_generation_; |
| 2708 } | 2750 } |
| 2709 | 2751 |
| 2710 void TextureManager::IncrementServiceIdGeneration() { | 2752 void TextureManager::IncrementServiceIdGeneration() { |
| 2711 current_service_id_generation_++; | 2753 current_service_id_generation_++; |
| 2712 } | 2754 } |
| 2713 | 2755 |
| 2714 } // namespace gles2 | 2756 } // namespace gles2 |
| 2715 } // namespace gpu | 2757 } // namespace gpu |
| OLD | NEW |