Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(853)

Unified Diff: gpu/command_buffer/service/texture_manager.cc

Issue 1750123002: Upgrade Tex{Sub}Image{2|3}D to handle ES3 unpack parameters. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Attemp to fix random crashes on windows Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/service/texture_manager.cc
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 7e8ea5a0a543d191cb76381c94cc86103009fa30..d2bc3256214d8451fce6bcd1877eaadd4902dc23 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -302,6 +302,11 @@ GLenum GetSwizzleForChannel(GLenum channel,
}
}
+// A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
+GLuint ToGLuint(const void* ptr) {
+ return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
+}
+
base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator =
LAZY_INSTANCE_INITIALIZER;
@@ -2221,6 +2226,40 @@ bool TextureManager::ValidateTexImage(
return false;
}
+ Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+ if (buffer) {
+ if (buffer->GetMappedRange()) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "pixel unpack buffer should not be mapped to client memory");
+ return error::kNoError;
+ }
+ base::CheckedNumeric<uint32_t> size = args.pixels_size;
+ GLuint offset = ToGLuint(args.pixels);
+ size += offset;
+ if (!size.IsValid()) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_VALUE, function_name,
+ "size + offset overflow");
+ return error::kNoError;
+ }
+ uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
+ if (buffer_size < size.ValueOrDefault(0)) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "pixel unpack buffer is not large enough");
+ return error::kNoError;
+ }
+ size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type);
+ DCHECK_LT(0u, type_size);
+ if (offset % type_size != 0) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "offset is not evenly divisible by elements");
+ return error::kNoError;
+ }
+ }
+
if (!memory_type_tracker_->EnsureGPUMemoryAvailable(args.pixels_size)) {
ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
"out of memory");
@@ -2285,13 +2324,13 @@ void TextureManager::ValidateAndDoTexImage(
for (GLenum face : undefined_faces) {
new_args.target = face;
new_args.pixels = zero.get();
- DoTexImage(texture_state, state->GetErrorState(), framebuffer_state,
+ DoTexImage(texture_state, state, framebuffer_state,
function_name, texture_ref, new_args);
texture->MarkLevelAsInternalWorkaround(face, args.level);
}
}
- DoTexImage(texture_state, state->GetErrorState(), framebuffer_state,
+ DoTexImage(texture_state, state, framebuffer_state,
function_name, texture_ref, args);
}
@@ -2310,21 +2349,7 @@ bool TextureManager::ValidateTexSubImage(ContextState* state,
args.target, "target");
return false;
}
- if (args.width < 0) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
- "width < 0");
- return false;
- }
- if (args.height < 0) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
- "height < 0");
- return false;
- }
- if (args.depth < 0) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
- "depth < 0");
- return false;
- }
+ DCHECK(args.width >= 0 && args.height >= 0 && args.depth >= 0);
TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
if (!local_texture_ref) {
ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
@@ -2366,7 +2391,40 @@ bool TextureManager::ValidateTexSubImage(ContextState* state,
"can not supply data for depth or stencil textures");
return false;
}
- DCHECK(args.pixels);
+
+ Buffer* buffer = state->bound_pixel_unpack_buffer.get();
+ if (buffer) {
+ if (buffer->GetMappedRange()) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "pixel unpack buffer should not be mapped to client memory");
+ return error::kNoError;
+ }
+ base::CheckedNumeric<uint32_t> size = args.pixels_size;
+ GLuint offset = ToGLuint(args.pixels);
+ size += offset;
+ if (!size.IsValid()) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_VALUE, function_name,
+ "size + offset overflow");
+ return error::kNoError;
+ }
+ uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
+ if (buffer_size < size.ValueOrDefault(0)) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "pixel unpack buffer is not large enough");
+ return error::kNoError;
+ }
+ size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type);
+ DCHECK_LT(0u, type_size);
+ if (offset % type_size != 0) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "offset is not evenly divisible by elements");
+ return error::kNoError;
+ }
+ }
*texture_ref = local_texture_ref;
return true;
}
@@ -2489,11 +2547,12 @@ GLenum TextureManager::AdjustTexFormat(GLenum format) const {
void TextureManager::DoTexImage(
DecoderTextureState* texture_state,
- ErrorState* error_state,
+ ContextState* state,
DecoderFramebufferState* framebuffer_state,
const char* function_name,
TextureRef* texture_ref,
const DoTexImageArguments& args) {
+ ErrorState* error_state = state->GetErrorState();
Texture* texture = texture_ref->texture();
GLsizei tex_width = 0;
GLsizei tex_height = 0;
@@ -2509,7 +2568,10 @@ void TextureManager::DoTexImage(
args.target, args.level, &tex_type, &tex_internal_format) &&
args.type == tex_type && args.internal_format == tex_internal_format;
- if (level_is_same && !args.pixels) {
+ bool unpack_buffer_bound =
+ (state->bound_pixel_unpack_buffer.get() != nullptr);
+
+ if (level_is_same && !args.pixels && !unpack_buffer_bound) {
// Just set the level texture but mark the texture as uncleared.
SetLevelInfo(
texture_ref, args.target, args.level, args.internal_format, args.width,
@@ -2524,7 +2586,7 @@ void TextureManager::DoTexImage(
}
if (texture_state->texsubimage_faster_than_teximage &&
- level_is_same && args.pixels) {
+ level_is_same && args.pixels && !unpack_buffer_bound) {
{
ScopedTextureUploadTimer timer(texture_state);
if (args.command_type == DoTexImageArguments::kTexImage3D) {
@@ -2566,7 +2628,7 @@ void TextureManager::DoTexImage(
GetAllGLErrors());
}
if (error == GL_NO_ERROR) {
- bool set_as_cleared = (args.pixels != nullptr);
+ bool set_as_cleared = (args.pixels != nullptr || unpack_buffer_bound);
SetLevelInfo(
texture_ref, args.target, args.level, args.internal_format, args.width,
args.height, args.depth, args.border, args.format, args.type,
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698