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 c4918f32ba591c0e554c8896f9ca96a9ddb3ab71..a8b3b7032046a1f64fe8f52afde48882bc9189e5 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -1270,12 +1270,12 @@ class GLES2DecoderImpl : public GLES2Decoder, |
bool ClearLevel(Texture* texture, |
unsigned target, |
int level, |
- unsigned internal_format, |
unsigned format, |
unsigned type, |
+ int xoffset, |
+ int yoffset, |
int width, |
- int height, |
- bool is_texture_immutable) override; |
+ int height) override; |
// Restore all GL state that affects clearing. |
void RestoreClearState(); |
@@ -3550,7 +3550,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid( |
// Are all the attachments cleared? |
if (renderbuffer_manager()->HaveUnclearedRenderbuffers() || |
- texture_manager()->HaveUnclearedMips()) { |
+ texture_manager()->HaveUnsafeTextures()) { |
if (!framebuffer->IsCleared()) { |
// Can we clear them? |
if (framebuffer->GetStatus(texture_manager(), target) != |
@@ -3685,17 +3685,12 @@ void GLES2DecoderImpl::UpdateParentTextureInfo() { |
GLenum target = offscreen_saved_color_texture_info_->texture()->target(); |
glBindTexture(target, offscreen_saved_color_texture_info_->service_id()); |
texture_manager()->SetLevelInfo( |
- offscreen_saved_color_texture_info_.get(), |
- GL_TEXTURE_2D, |
+ offscreen_saved_color_texture_info_.get(), GL_TEXTURE_2D, |
0, // level |
- GL_RGBA, |
- offscreen_size_.width(), |
- offscreen_size_.height(), |
+ GL_RGBA, offscreen_size_.width(), offscreen_size_.height(), |
1, // depth |
0, // border |
- GL_RGBA, |
- GL_UNSIGNED_BYTE, |
- true); |
+ GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(offscreen_size_)); |
texture_manager()->SetParameteri( |
"UpdateParentTextureInfo", |
GetErrorState(), |
@@ -8864,19 +8859,18 @@ void GLES2DecoderImpl::DoBufferSubData( |
&state_, target, offset, size, data); |
} |
-bool GLES2DecoderImpl::ClearLevel( |
- Texture* texture, |
- unsigned target, |
- int level, |
- unsigned internal_format, |
- unsigned format, |
- unsigned type, |
- int width, |
- int height, |
- bool is_texture_immutable) { |
+bool GLES2DecoderImpl::ClearLevel(Texture* texture, |
+ unsigned target, |
+ int level, |
+ unsigned format, |
+ unsigned type, |
+ int xoffset, |
+ int yoffset, |
+ int width, |
+ int height) { |
uint32 channels = GLES2Util::GetChannelsForFormat(format); |
if (feature_info_->feature_flags().angle_depth_texture && |
- (channels & GLES2Util::kDepth) != 0) { |
+ (channels & GLES2Util::kDepth) != 0 && xoffset == 0 && yoffset == 0) { |
// It's a depth format and ANGLE doesn't allow texImage2D or texSubImage2D |
// on depth formats. |
GLuint fb = 0; |
@@ -8949,17 +8943,11 @@ bool GLES2DecoderImpl::ClearLevel( |
memset(zero.get(), 0, size); |
glBindTexture(texture->target(), texture->service_id()); |
- bool has_images = texture->HasImages(); |
GLint y = 0; |
while (y < height) { |
GLint h = y + tile_height > height ? height - y : tile_height; |
- if (is_texture_immutable || h != height || has_images) { |
- glTexSubImage2D(target, level, 0, y, width, h, format, type, zero.get()); |
- } else { |
- glTexImage2D( |
- target, level, internal_format, width, h, 0, format, type, |
- zero.get()); |
- } |
+ glTexSubImage2D(target, level, xoffset, yoffset + y, width, h, format, type, |
+ zero.get()); |
y += tile_height; |
} |
TextureRef* bound_texture = |
@@ -9320,9 +9308,9 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D( |
target, level, internal_format, width, height, border, image_size, data); |
GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D"); |
if (error == GL_NO_ERROR) { |
- texture_manager()->SetLevelInfo( |
- texture_ref, target, level, internal_format, |
- width, height, 1, border, 0, 0, true); |
+ texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, |
+ width, height, 1, border, 0, 0, |
+ gfx::Rect(width, height)); |
} |
// This may be a slow command. Exit command processing to allow for |
@@ -9507,9 +9495,9 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage3D( |
border, image_size, data); |
GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D"); |
if (error == GL_NO_ERROR) { |
- texture_manager()->SetLevelInfo( |
- texture_ref, target, level, internal_format, |
- width, height, depth, border, 0, 0, true); |
+ texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, |
+ width, height, depth, border, 0, 0, |
+ gfx::Rect(width, height)); |
} |
// This may be a slow command. Exit command processing to allow for |
@@ -9963,8 +9951,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D( |
copyWidth != width || |
copyHeight != height) { |
// some part was clipped so clear the texture. |
- if (!ClearLevel(texture, target, level, internal_format, internal_format, |
- GL_UNSIGNED_BYTE, width, height, texture->IsImmutable())) { |
+ if (!ClearLevel(texture, target, level, internal_format, GL_UNSIGNED_BYTE, |
+ 0, 0, width, height)) { |
LOCAL_SET_GL_ERROR( |
GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big"); |
return; |
@@ -9986,9 +9974,9 @@ void GLES2DecoderImpl::DoCopyTexImage2D( |
} |
GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTexImage2D"); |
if (error == GL_NO_ERROR) { |
- texture_manager()->SetLevelInfo( |
- texture_ref, target, level, internal_format, width, height, 1, |
- border, internal_format, GL_UNSIGNED_BYTE, true); |
+ texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, |
+ width, height, 1, border, internal_format, |
+ GL_UNSIGNED_BYTE, gfx::Rect(width, height)); |
} |
// This may be a slow command. Exit command processing to allow for |
@@ -10076,6 +10064,8 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( |
if (xoffset != 0 || yoffset != 0 || width != size.width() || |
height != size.height()) { |
+ // TODO(reveman): Use SetLevelClearedRect when possible instead of clearing |
+ // the texture prematurely. |
if (!texture_manager()->ClearTextureLevel(this, texture_ref, target, |
level)) { |
LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D", |
@@ -10225,6 +10215,8 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D( |
DCHECK(ok); |
if (xoffset != 0 || yoffset != 0 || |
width != tex_width || height != tex_height) { |
+ // TODO(reveman): Use SetLevelClearedRect when possible instead of clearing |
+ // the texture prematurely. |
if (!texture_manager()->ClearTextureLevel(this, texture_ref, |
target, level)) { |
LOCAL_SET_GL_ERROR( |
@@ -11741,8 +11733,8 @@ void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( |
} |
texture_manager()->SetLevelInfo( |
- texture_ref, target, 0, GL_RGBA, width, height, 1, 0, |
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true); |
+ texture_ref, target, 0, GL_RGBA, width, height, 1, 0, GL_BGRA, |
+ GL_UNSIGNED_INT_8_8_8_8_REV, gfx::Rect(width, height)); |
#else |
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, |
@@ -11965,7 +11957,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(GLenum target, |
texture_manager()->SetLevelInfo( |
dest_texture_ref, GL_TEXTURE_2D, 0, internal_format, source_width, |
- source_height, 1, 0, internal_format, dest_type, true); |
+ source_height, 1, 0, internal_format, dest_type, |
+ gfx::Rect(source_width, source_height)); |
} else { |
texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0, |
true); |
@@ -12111,11 +12104,22 @@ void GLES2DecoderImpl::DoCopySubTextureCHROMIUM(GLenum target, |
DCHECK(ok); |
if (xoffset != 0 || yoffset != 0 || width != dest_width || |
height != dest_height) { |
- if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
- 0)) { |
- LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", |
- "destination texture dimensions too big"); |
- return; |
+ gfx::Rect cleared_rect(xoffset, yoffset, width, height); |
+ gfx::Rect level_cleared_rect = dest_texture->GetLevelClearedRect(target, 0); |
+ // Try to grow cleared rectangle. |
+ if (level_cleared_rect.IsEmpty() || |
+ level_cleared_rect.SharesEdgeWith(cleared_rect)) { |
+ cleared_rect.Union(level_cleared_rect); |
+ texture_manager()->SetLevelClearedRect(dest_texture_ref, target, 0, |
+ cleared_rect); |
+ } else { |
+ // Otherwise clear part of texture level that is not already cleared. |
+ if (!texture_manager()->ClearTextureLevel(this, dest_texture_ref, target, |
+ 0)) { |
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopySubTextureCHROMIUM", |
+ "destination texture dimensions too big"); |
+ return; |
+ } |
} |
} else { |
texture_manager()->SetLevelCleared(dest_texture_ref, GL_TEXTURE_2D, 0, |
@@ -12261,9 +12265,9 @@ void GLES2DecoderImpl::DoTexStorage2DEXT( |
GLsizei level_width = width; |
GLsizei level_height = height; |
for (int ii = 0; ii < levels; ++ii) { |
- texture_manager()->SetLevelInfo( |
- texture_ref, target, ii, format, |
- level_width, level_height, 1, 0, format, type, false); |
+ texture_manager()->SetLevelInfo(texture_ref, target, ii, format, |
+ level_width, level_height, 1, 0, format, |
+ type, gfx::Rect()); |
level_width = std::max(1, level_width >> 1); |
level_height = std::max(1, level_height >> 1); |
} |
@@ -12613,9 +12617,9 @@ void GLES2DecoderImpl::DoBindTexImage2DCHROMIUM( |
gfx::Size size = gl_image->GetSize(); |
texture_manager()->SetLevelInfo( |
- texture_ref, target, 0, gl_image->GetInternalFormat(), |
- size.width(), size.height(), 1, 0, |
- gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, true); |
+ texture_ref, target, 0, gl_image->GetInternalFormat(), size.width(), |
+ size.height(), 1, 0, gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, |
+ gfx::Rect(size)); |
texture_manager()->SetLevelImage(texture_ref, target, 0, gl_image); |
} |
@@ -12654,7 +12658,7 @@ void GLES2DecoderImpl::DoReleaseTexImage2DCHROMIUM( |
texture_manager()->SetLevelInfo( |
texture_ref, target, 0, gl_image->GetInternalFormat(), 0, 0, 1, 0, |
- gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, false); |
+ gl_image->GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect()); |
} |
error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( |