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

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

Issue 1154053002: gpu: Use a rectangle to keep track of the cleared area of each texture level. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix GLES2DecoderImpl::DoCopyTexImage2D Created 5 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/service/gles2_cmd_decoder.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder_mock.h » ('j') | 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 951bbd62406e49e96adfa62320ad201a7f37cd24..0ac4e96530e175f5b0884876951bcad35a186cc1 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -191,6 +191,33 @@ struct Vec4f {
GLfloat v[4];
};
+// Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
+// contains the other rectangle or shares an edge with the other rectangle.
+bool CombineAdjacentRects(const gfx::Rect& rect1,
+ const gfx::Rect& rect2,
+ gfx::Rect* result) {
+ // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
+ if (rect1.IsEmpty() || rect2.Contains(rect1)) {
+ *result = rect2;
+ return true;
+ }
+
+ // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
+ if (rect2.IsEmpty() || rect1.Contains(rect2)) {
+ *result = rect1;
+ return true;
+ }
+
+ // Return the union of |rect1| and |rect2| if they share an edge.
+ if (rect1.SharesEdgeWith(rect2)) {
+ *result = gfx::UnionRects(rect1, rect2);
+ return true;
+ }
+
+ // Return false if it's not possible to combine |rect1| and |rect2|.
+ return false;
+}
+
} // namespace
class GLES2DecoderImpl;
@@ -1270,12 +1297,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 +3577,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 +3712,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(),
@@ -8865,19 +8887,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.
piman 2015/06/05 19:55:49 It sounds like this is still true in the xoffset !
reveman 2015/06/05 20:39:43 Yes, I was trying to avoid that but we have to han
GLuint fb = 0;
@@ -8950,17 +8971,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 =
@@ -9321,9 +9336,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
@@ -9508,9 +9523,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
@@ -9974,13 +9989,20 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
copyY != y ||
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())) {
+ // some part was clipped so clear the rect.
+ uint32 pixels_size = 0;
+ if (!GLES2Util::ComputeImageDataSizes(
+ width, height, 1, internal_format, GL_UNSIGNED_BYTE,
+ state_.unpack_alignment, &pixels_size, NULL, NULL)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY, "glCopyTexImage2D", "dimensions too big");
return;
}
+ scoped_ptr<char[]> zero(new char[pixels_size]);
+ memset(zero.get(), 0, pixels_size);
+ ScopedModifyPixels modify(texture_ref);
+ glTexImage2D(target, level, internal_format, width, height, border,
+ internal_format, GL_UNSIGNED_BYTE, zero.get());
reveman 2015/06/05 19:38:37 I changed this code to be more consistent with DoC
piman 2015/06/05 19:55:50 That's a nice catch, thanks!
if (copyHeight > 0 && copyWidth > 0) {
GLint dx = copyX - x;
GLint dy = copyY - y;
@@ -9998,9 +10020,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
@@ -10088,11 +10110,22 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
if (xoffset != 0 || yoffset != 0 || width != size.width() ||
height != size.height()) {
- if (!texture_manager()->ClearTextureLevel(this, texture_ref, target,
- level)) {
- LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glCopyTexSubImage2D",
- "dimensions too big");
- return;
+ gfx::Rect cleared_rect;
+ if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
+ gfx::Rect(xoffset, yoffset, width, height),
+ &cleared_rect)) {
+ DCHECK_GE(cleared_rect.size().GetArea(),
+ texture->GetLevelClearedRect(target, level).size().GetArea());
+ texture_manager()->SetLevelClearedRect(texture_ref, target, level,
+ cleared_rect);
+ } else {
+ // 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");
+ return;
+ }
}
} else {
// Write all pixels in below.
@@ -10237,11 +10270,22 @@ error::Error GLES2DecoderImpl::DoTexSubImage2D(
DCHECK(ok);
if (xoffset != 0 || yoffset != 0 ||
width != tex_width || height != tex_height) {
- if (!texture_manager()->ClearTextureLevel(this, texture_ref,
- target, level)) {
- LOCAL_SET_GL_ERROR(
- GL_OUT_OF_MEMORY, "glTexSubImage2D", "dimensions too big");
- return error::kNoError;
+ gfx::Rect cleared_rect;
+ if (CombineAdjacentRects(texture->GetLevelClearedRect(target, level),
+ gfx::Rect(xoffset, yoffset, width, height),
+ &cleared_rect)) {
+ DCHECK_GE(cleared_rect.size().GetArea(),
+ texture->GetLevelClearedRect(target, level).size().GetArea());
+ texture_manager()->SetLevelClearedRect(texture_ref, target, level,
+ cleared_rect);
+ } else {
+ // 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, "glTexSubImage2D",
+ "dimensions too big");
+ return error::kNoError;
+ }
}
ScopedTextureUploadTimer timer(&texture_state_);
glTexSubImage2D(
@@ -11757,8 +11801,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,
@@ -11981,7 +12025,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);
@@ -12127,11 +12172,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;
+ if (CombineAdjacentRects(dest_texture->GetLevelClearedRect(target, 0),
+ gfx::Rect(xoffset, yoffset, width, height),
+ &cleared_rect)) {
+ DCHECK_GE(cleared_rect.size().GetArea(),
+ dest_texture->GetLevelClearedRect(target, 0).size().GetArea());
+ 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,
@@ -12277,9 +12333,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);
}
@@ -12629,9 +12685,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);
}
@@ -12670,7 +12726,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(
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_decoder.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder_mock.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698