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

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

Issue 1426903002: gpu: Make glTexSubImage2D work with GL_SRGB_ALPHA on OpenGL (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove an unneeded hunk now that workarounds are used Created 5 years, 1 month 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') | gpu/command_buffer/tests/gl_ext_srgb_unittest.cc » ('j') | 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 4f856d6ae234b326ac0154ed9c650aa2e57a8efb..bd93329f00e14d9c7888a0cca4695b26229ef1e0 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -22,6 +22,7 @@
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_version_info.h"
#include "ui/gl/trace_util.h"
namespace gpu {
@@ -2002,6 +2003,138 @@ void TextureManager::ValidateAndDoTexImage(
function_name, texture_ref, args);
}
+bool TextureManager::ValidateTexSubImage(ContextState* state,
+ const char* function_name,
+ const DoTexSubImageArguments& args,
+ TextureRef** texture_ref) {
+ ErrorState* error_state = state->GetErrorState();
+ const Validators* validators = feature_info_->validators();
+
+ if (!validators->texture_target.IsValid(args.target)) {
+ ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name,
+ 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;
+ }
+ TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
+ if (!local_texture_ref) {
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
+ "unknown texture for target");
+ return false;
+ }
+ Texture* texture = local_texture_ref->texture();
+ GLenum current_type = 0;
+ GLenum internal_format = 0;
+ if (!texture->GetLevelType(args.target, args.level, &current_type,
+ &internal_format)) {
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
+ "level does not exist.");
+ return false;
+ }
+ if (!ValidateTextureParameters(error_state, function_name, args.format,
+ args.type, internal_format, args.level)) {
+ return false;
+ }
+ if (args.type != current_type && !feature_info_->IsES3Enabled()) {
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
+ "type does not match type of texture.");
+ return false;
+ }
+ if (!texture->ValidForTexture(args.target, args.level, args.xoffset,
+ args.yoffset, 0, args.width, args.height, 1)) {
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
+ "bad dimensions.");
+ return false;
+ }
+ if ((GLES2Util::GetChannelsForFormat(args.format) &
+ (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 &&
+ !feature_info_->IsES3Enabled()) {
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_OPERATION, function_name,
+ "can not supply data for depth or stencil textures");
+ return false;
+ }
+ DCHECK(args.pixels);
+ *texture_ref = local_texture_ref;
+ return true;
+}
+
+void TextureManager::ValidateAndDoTexSubImage(
+ GLES2Decoder* decoder,
+ DecoderTextureState* texture_state,
+ ContextState* state,
+ DecoderFramebufferState* framebuffer_state,
+ const char* function_name,
+ const DoTexSubImageArguments& args) {
+ ErrorState* error_state = state->GetErrorState();
+ TextureRef* texture_ref;
+ if (!ValidateTexSubImage(state, function_name, args, &texture_ref)) {
+ return;
+ }
+
+ Texture* texture = texture_ref->texture();
+ GLsizei tex_width = 0;
+ GLsizei tex_height = 0;
+ bool ok = texture->GetLevelSize(args.target, args.level, &tex_width,
+ &tex_height, nullptr);
+ DCHECK(ok);
+ if (args.xoffset != 0 || args.yoffset != 0 || args.width != tex_width ||
+ args.height != tex_height) {
+ gfx::Rect cleared_rect;
+ if (CombineAdjacentRects(
+ texture->GetLevelClearedRect(args.target, args.level),
+ gfx::Rect(args.xoffset, args.yoffset, args.width, args.height),
+ &cleared_rect)) {
+ DCHECK_GE(cleared_rect.size().GetArea(),
+ texture->GetLevelClearedRect(args.target, args.level)
+ .size()
+ .GetArea());
+ SetLevelClearedRect(texture_ref, args.target, args.level, cleared_rect);
+ } else {
+ // Otherwise clear part of texture level that is not already cleared.
+ if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) {
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY,
+ "glTexSubImage2D", "dimensions too big");
+ return;
+ }
+ }
+ ScopedTextureUploadTimer timer(texture_state);
+ glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
+ args.width, args.height, AdjustTexFormat(args.format),
+ args.type, args.pixels);
+ return;
+ }
+
+ if (!texture_state->texsubimage_faster_than_teximage &&
+ !texture->IsImmutable() && !texture->HasImages()) {
+ ScopedTextureUploadTimer timer(texture_state);
+ GLenum internal_format;
+ GLenum tex_type;
+ texture->GetLevelType(args.target, args.level, &tex_type, &internal_format);
+ // NOTE: In OpenGL ES 2.0 border is always zero. If that changes we'll need
+ // to look it up.
+ glTexImage2D(args.target, args.level, internal_format, args.width,
+ args.height, 0, AdjustTexFormat(args.format), args.type,
+ args.pixels);
+ } else {
+ ScopedTextureUploadTimer timer(texture_state);
+ glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
+ args.width, args.height, AdjustTexFormat(args.format),
+ args.type, args.pixels);
+ }
+ SetLevelCleared(texture_ref, args.target, args.level, true);
+ return;
+}
+
GLenum TextureManager::AdjustTexFormat(GLenum format) const {
// TODO(bajones): GLES 3 allows for internal format and format to differ.
// This logic may need to change as a result.
@@ -2089,6 +2222,31 @@ void TextureManager::DoTexImage(
}
}
+bool TextureManager::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;
+}
+
ScopedTextureUploadTimer::ScopedTextureUploadTimer(
DecoderTextureState* texture_state)
: texture_state_(texture_state),
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | gpu/command_buffer/tests/gl_ext_srgb_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698