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

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

Issue 2029803002: Improve CopyTex{Sub}Image2D format validation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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/common/gles2_cmd_utils.cc ('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/gles2_cmd_decoder.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 48f372e4ade7d39f84507193db85f5f318eb5df1..ad7866f04d69ca4ba744b8c964d855572e372307 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -910,7 +910,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
GLsizei height,
GLenum format,
GLsizei imageSize,
- const void * data);
+ const void* data);
// Wrapper for CompressedTexSubImage3D.
void DoCompressedTexSubImage3D(
@@ -926,6 +926,11 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
GLsizei image_size,
const void* data);
+ // Validate if |format| is valid for CopyTex{Sub}Image functions.
+ // If not, generate a GL error and return false.
+ bool ValidateCopyTexFormat(const char* func_name, GLenum internal_format,
+ GLenum read_format, GLenum read_type);
+
// Wrapper for CopyTexImage2D.
void DoCopyTexImage2D(
GLenum target,
@@ -12124,6 +12129,66 @@ static void Clip(
*out_range = range;
}
+bool GLES2DecoderImpl::ValidateCopyTexFormat(
+ const char* func_name, GLenum internal_format,
+ GLenum read_format, GLenum read_type) {
+ if (read_format == 0) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, func_name, "no valid color image");
+ return false;
+ }
+ // Check we have compatible formats.
+ uint32_t channels_exist = GLES2Util::GetChannelsForFormat(read_format);
+ uint32_t channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
+ if (!channels_needed ||
+ (channels_needed & channels_exist) != channels_needed) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, func_name, "incompatible format");
+ return false;
+ }
+ if (feature_info_->IsES3Enabled()) {
+ GLint color_encoding = GetColorEncodingFromInternalFormat(read_format);
+ if (color_encoding != GetColorEncodingFromInternalFormat(internal_format) ||
+ GLES2Util::IsFloatFormat(internal_format) ||
+ (GLES2Util::IsSignedIntegerFormat(internal_format) !=
+ GLES2Util::IsSignedIntegerFormat(read_format)) ||
+ (GLES2Util::IsUnsignedIntegerFormat(internal_format) !=
+ GLES2Util::IsUnsignedIntegerFormat(read_format))) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, func_name, "incompatible format");
+ return false;
+ }
+ }
+ if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION,
+ func_name, "can not be used with depth or stencil textures");
+ return false;
+ }
+ if (feature_info_->IsES3Enabled()) {
+ if (GLES2Util::IsSizedColorFormat(internal_format)) {
+ int sr, sg, sb, sa;
+ GLES2Util::GetColorFormatComponentSizes(
+ read_format, read_type, &sr, &sg, &sb, &sa);
+ DCHECK(sr > 0 || sg > 0 || sb > 0 || sa > 0);
+ int dr, dg, db, da;
+ GLES2Util::GetColorFormatComponentSizes(
+ internal_format, 0, &dr, &dg, &db, &da);
+ DCHECK(dr > 0 || dg > 0 || db > 0 || da > 0);
+ if ((dr > 0 && sr != dr) ||
+ (dg > 0 && sg != dg) ||
+ (db > 0 && sb != db) ||
+ (da > 0 && sa != da)) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION,
+ func_name, "imcompatible color component sizes");
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
void GLES2DecoderImpl::DoCopyTexImage2D(
GLenum target,
GLint level,
@@ -12133,68 +12198,37 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
GLsizei width,
GLsizei height,
GLint border) {
+ const char* func_name = "glCopyTexImage2D";
DCHECK(!ShouldDeferReads());
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
&state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glCopyTexImage2D", "unknown texture for target");
+ GL_INVALID_OPERATION, func_name, "unknown texture for target");
return;
}
Texture* texture = texture_ref->texture();
if (texture->IsImmutable()) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, "glCopyTexImage2D", "texture is immutable");
+ GL_INVALID_OPERATION, func_name, "texture is immutable");
return;
}
if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
border != 0) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
+ GL_INVALID_VALUE, func_name, "dimensions out of range");
return;
}
- if (!CheckBoundReadFramebufferValid("glCopyTexImage2D",
+ if (!CheckBoundReadFramebufferValid(func_name,
GL_INVALID_FRAMEBUFFER_OPERATION)) {
return;
}
GLenum read_format = GetBoundReadFrameBufferInternalFormat();
- if (read_format == 0) {
- LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTexImage2D",
- "no valid color image");
- return;
- }
-
- // Check we have compatible formats.
- uint32_t channels_exist = GLES2Util::GetChannelsForFormat(read_format);
- uint32_t channels_needed = GLES2Util::GetChannelsForFormat(internal_format);
-
- if ((channels_needed & channels_exist) != channels_needed) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
- return;
- }
-
- if (feature_info_->IsES3Enabled()) {
- GLint color_encoding = GetColorEncodingFromInternalFormat(read_format);
- if (color_encoding != GetColorEncodingFromInternalFormat(internal_format) ||
- GLES2Util::IsFloatFormat(internal_format) ||
- (GLES2Util::IsSignedIntegerFormat(internal_format) !=
- GLES2Util::IsSignedIntegerFormat(read_format)) ||
- (GLES2Util::IsUnsignedIntegerFormat(internal_format) !=
- GLES2Util::IsUnsignedIntegerFormat(read_format))) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, "glCopyTexImage2D", "incompatible format");
- return;
- }
- }
-
- if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glCopyTexImage2D", "can not be used with depth or stencil textures");
+ GLenum read_type = GetBoundReadFrameBufferTextureType();
+ if (!ValidateCopyTexFormat(func_name, internal_format,
+ read_format, read_type)) {
return;
}
@@ -12206,24 +12240,23 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
if (!GLES2Util::ComputeImageDataSizes(
width, height, 1, format, type,
state_.unpack_alignment, &pixels_size, NULL, NULL)) {
- LOCAL_SET_GL_ERROR(
- GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too large");
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, func_name, "dimensions too large");
return;
}
if (!EnsureGPUMemoryAvailable(pixels_size)) {
- LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexImage2D", "out of memory");
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, func_name, "out of memory");
return;
}
if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
- "glCopyTexImage2D", "source and destination textures are the same");
+ func_name, "source and destination textures are the same");
return;
}
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopyTexImage2D");
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(func_name);
ScopedResolvedFrameBufferBinder binder(this, false, true);
gfx::Size size = GetBoundReadFrameBufferSize();
@@ -12265,6 +12298,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
// The service id and target of the texture attached to READ_FRAMEBUFFER.
GLuint source_texture_service_id = 0;
GLenum source_texture_target = 0;
+ uint32_t channels_exist = GLES2Util::GetChannelsForFormat(read_format);
bool use_workaround = NeedsCopyTextureImageWorkaround(
final_internal_format, channels_exist, &source_texture_service_id,
&source_texture_target);
@@ -12313,7 +12347,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
copyWidth, copyHeight, border);
}
}
- GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D");
+ GLenum error = LOCAL_PEEK_GL_ERROR(func_name);
if (error == GL_NO_ERROR) {
texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format,
width, height, 1, border, format,
@@ -12335,59 +12369,41 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
GLint y,
GLsizei width,
GLsizei height) {
+ const char* func_name = "glCopyTexSubImage2D";
DCHECK(!ShouldDeferReads());
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
&state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glCopyTexSubImage2D", "unknown texture for target");
+ GL_INVALID_OPERATION, func_name, "unknown texture for target");
return;
}
Texture* texture = texture_ref->texture();
GLenum type = 0;
- GLenum format = 0;
- if (!texture->GetLevelType(target, level, &type, &format) ||
+ GLenum internal_format = 0;
+ if (!texture->GetLevelType(target, level, &type, &internal_format) ||
!texture->ValidForTexture(
target, level, xoffset, yoffset, 0, width, height, 1)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "bad dimensions.");
return;
}
- if (!CheckBoundReadFramebufferValid("glCopyTexImage2D",
+ if (!CheckBoundReadFramebufferValid(func_name,
GL_INVALID_FRAMEBUFFER_OPERATION)) {
return;
}
GLenum read_format = GetBoundReadFrameBufferInternalFormat();
- if (read_format == 0) {
- LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glCopyTexImage2D",
- "no valid color image");
- return;
- }
- // Check we have compatible formats.
- uint32_t channels_exist = GLES2Util::GetChannelsForFormat(read_format);
- uint32_t channels_needed = GLES2Util::GetChannelsForFormat(format);
-
- if (!channels_needed ||
- (channels_needed & channels_exist) != channels_needed) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, "glCopyTexSubImage2D", "incompatible format");
- return;
- }
-
- if ((channels_needed & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glCopySubImage2D", "can not be used with depth or stencil textures");
+ GLenum read_type = GetBoundReadFrameBufferTextureType();
+ if (!ValidateCopyTexFormat(func_name, internal_format,
+ read_format, read_type)) {
return;
}
if (FormsTextureCopyingFeedbackLoop(texture_ref, level)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
- "glCopyTexSubImage2D", "source and destination textures are the same");
+ func_name, "source and destination textures are the same");
return;
}
@@ -12418,8 +12434,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
// Otherwise clear part of texture level that is not already cleared.
if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
level)) {
- LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
- "dimensions too big");
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, func_name, "dimensions too big");
return;
}
}
« no previous file with comments | « gpu/command_buffer/common/gles2_cmd_utils.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698