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

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

Issue 1872663002: Enable TexStorage on Desktop GL lower than 4.2 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
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 f28cc4387e7832e07bdf8335f303ff646fd0293c..25e33abb51b1f8fdceb28f72f560c568c146ab02 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -983,6 +983,12 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
void DoCompressedCopyTextureCHROMIUM(GLuint source_id, GLuint dest_id);
+ // Helper for DoTexStorage2DEXT and DoTexStorage3D.
+ void TexStorageImpl(
+ GLenum target, GLint levels, GLenum internal_format,
+ GLsizei width, GLsizei height, GLsizei depth,
+ ContextState::Dimension dimension, const char* function_name);
+
// Wrapper for TexStorage2DEXT.
void DoTexStorage2DEXT(
GLenum target,
@@ -8823,12 +8829,36 @@ void GLES2DecoderImpl::DoGetSamplerParameteriv(
void GLES2DecoderImpl::DoGetTexParameterfv(
GLenum target, GLenum pname, GLfloat* params) {
InitTextureMaxAnisotropyIfNeeded(target, pname);
+ if (pname == GL_TEXTURE_IMMUTABLE_FORMAT &&
+ feature_info_->gl_version_info().IsLowerThanGL(4, 2) &&
+ !features().ext_texture_storage) {
piman 2016/04/11 22:59:31 I'm not sure when that condition would be true. GL
Zhenyao Mo 2016/04/11 23:17:19 This will be removed for option 2.
+ // We emulate TexStorage calls in such situations.
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
+ if (texture_ref) {
+ Texture* texture = texture_ref->texture();
+ *params = static_cast<GLfloat>(texture->IsImmutable());
+ return;
+ }
+ }
glGetTexParameterfv(target, pname, params);
}
void GLES2DecoderImpl::DoGetTexParameteriv(
GLenum target, GLenum pname, GLint* params) {
InitTextureMaxAnisotropyIfNeeded(target, pname);
+ if (pname == GL_TEXTURE_IMMUTABLE_FORMAT &&
+ feature_info_->gl_version_info().IsLowerThanGL(4, 2) &&
+ !features().ext_texture_storage) {
+ // We emulate TexStorage calls in such situations.
+ TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
+ &state_, target);
+ if (texture_ref) {
+ Texture* texture = texture_ref->texture();
+ *params = static_cast<GLint>(texture->IsImmutable());
+ return;
+ }
+ }
glGetTexParameteriv(target, pname, params);
}
@@ -14298,143 +14328,65 @@ void GLES2DecoderImpl::DoCompressedCopyTextureCHROMIUM(GLuint source_id,
false, false);
}
-void GLES2DecoderImpl::DoTexStorage2DEXT(
- GLenum target,
- GLint levels,
- GLenum internal_format,
- GLsizei width,
- GLsizei height) {
- TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2DEXT",
- "width", width, "height", height);
- if (!texture_manager()->ValidForTarget(target, 0, width, height, 1) ||
- TextureManager::ComputeMipMapCount(target, width, height, 1) < levels) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glTexStorage2DEXT", "dimensions out of range");
- return;
- }
- TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
- &state_, target);
- if (!texture_ref) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glTexStorage2DEXT", "unknown texture for target");
- return;
- }
- Texture* texture = texture_ref->texture();
- if (texture->IsAttachedToFramebuffer()) {
- framebuffer_state_.clear_state_dirty = true;
- }
- if (texture->IsImmutable()) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glTexStorage2DEXT", "texture is immutable");
- return;
- }
-
- GLenum format = TextureManager::ExtractFormatFromStorageFormat(
- internal_format);
- GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format);
-
- {
- GLsizei level_width = width;
- GLsizei level_height = height;
- uint32_t estimated_size = 0;
- for (int ii = 0; ii < levels; ++ii) {
- uint32_t level_size = 0;
- if (!GLES2Util::ComputeImageDataSizes(
- level_width, level_height, 1, format, type, state_.unpack_alignment,
- &estimated_size, NULL, NULL) ||
- !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
- LOCAL_SET_GL_ERROR(
- GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "dimensions too large");
- return;
- }
- level_width = std::max(1, level_width >> 1);
- level_height = std::max(1, level_height >> 1);
- }
- if (!EnsureGPUMemoryAvailable(estimated_size)) {
- LOCAL_SET_GL_ERROR(
- GL_OUT_OF_MEMORY, "glTexStorage2DEXT", "out of memory");
+void GLES2DecoderImpl::TexStorageImpl(
+ GLenum target, GLint levels, GLenum internal_format,
+ GLsizei width, GLsizei height, GLsizei depth,
+ ContextState::Dimension dimension, const char* function_name) {
+ if (dimension == ContextState::k2D) {
+ if (!validators_->texture_bind_target.IsValid(target)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
return;
}
- }
-
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage2DEXT");
- glTexStorage2DEXT(target, levels, internal_format, width, height);
- GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage2DEXT");
- if (error == GL_NO_ERROR) {
- GLsizei level_width = width;
- GLsizei level_height = height;
-
- GLenum cur_format = feature_info_->IsES3Enabled() ?
- internal_format : format;
- for (int ii = 0; ii < levels; ++ii) {
- if (target == GL_TEXTURE_CUBE_MAP) {
- for (int jj = 0; jj < 6; ++jj) {
- GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
- texture_manager()->SetLevelInfo(texture_ref, face, ii, cur_format,
- level_width, level_height, 1, 0,
- format, type, gfx::Rect());
- }
- } else {
- texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_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);
+ } else {
+ if (!validators_->texture_3_d_target.IsValid(target)) {
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target");
+ return;
}
- texture->SetImmutable(true);
- }
-}
-
-void GLES2DecoderImpl::DoTexStorage3D(
- GLenum target,
- GLint levels,
- GLenum internal_format,
- GLsizei width,
- GLsizei height,
- GLsizei depth) {
- TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage3D",
- "widthXheight", width * height, "depth", depth);
- if (!validators_->texture_3_d_target.IsValid(target)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", target, "target");
- return;
}
if (levels <= 0) {
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "levels <= 0");
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "levels <= 0");
return;
}
if (!validators_->texture_internal_format_storage.IsValid(internal_format)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM("glTexStorage3D", internal_format,
- "internal_format");
- return;
- }
- if (width <= 0) {
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "width <= 0");
- return;
- }
- if (height <= 0) {
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "height <= 0");
+ LOCAL_SET_GL_ERROR_INVALID_ENUM(
+ function_name, internal_format, "internal_format");
return;
}
- if (depth <= 0) {
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage3D", "depth <= 0");
- return;
+ bool is_compressed_format;
+ switch (internal_format) {
+ case GL_COMPRESSED_R11_EAC:
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ case GL_COMPRESSED_RG11_EAC:
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ case GL_COMPRESSED_RGB8_ETC2:
+ case GL_COMPRESSED_SRGB8_ETC2:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ is_compressed_format = true;
+ if (target == GL_TEXTURE_3D) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, function_name, "target invalid for format");
+ return;
+ }
+ break;
+ default:
+ is_compressed_format = false;
+ break;
}
if (!texture_manager()->ValidForTarget(target, 0, width, height, depth) ||
TextureManager::ComputeMipMapCount(
target, width, height, depth) < levels) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glTexStorage3D", "dimensions out of range");
+ GL_INVALID_VALUE, function_name, "dimensions out of range");
return;
}
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
&state_, target);
if (!texture_ref) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glTexStorage3D", "unknown texture for target");
+ GL_INVALID_OPERATION, function_name, "unknown texture for target");
return;
}
Texture* texture = texture_ref->texture();
@@ -14443,7 +14395,7 @@ void GLES2DecoderImpl::DoTexStorage3D(
}
if (texture->IsImmutable()) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, "glTexStorage3D", "texture is immutable");
+ GL_INVALID_OPERATION, function_name, "texture is immutable");
return;
}
@@ -14451,48 +14403,140 @@ void GLES2DecoderImpl::DoTexStorage3D(
internal_format);
GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format);
+ std::vector<int32_t> level_size(levels);
{
GLsizei level_width = width;
GLsizei level_height = height;
GLsizei level_depth = depth;
- uint32_t estimated_size = 0;
+ base::CheckedNumeric<uint32_t> estimated_size(0);
+ PixelStoreParams params;
+ params.alignment = 1;
for (int ii = 0; ii < levels; ++ii) {
- uint32_t level_size = 0;
- if (!GLES2Util::ComputeImageDataSizes(
- level_width, level_height, level_depth, format, type,
- state_.unpack_alignment,
- &estimated_size, NULL, NULL) ||
- !SafeAddUint32(estimated_size, level_size, &estimated_size)) {
- LOCAL_SET_GL_ERROR(
- GL_OUT_OF_MEMORY, "glTexStorage3D", "dimensions too large");
- return;
+ uint32_t size;
+ if (is_compressed_format) {
+ if (!GetCompressedTexSizeInBytes(function_name,
+ level_width, level_height, level_depth,
+ internal_format, &level_size[ii])) {
+ // GetCompressedTexSizeInBytes() already generates a GL error.
+ return;
+ }
+ size = static_cast<uint32_t>(level_size[ii]);
+ } else {
+ if (!GLES2Util::ComputeImageDataSizesES3(level_width,
+ level_height,
+ level_depth,
+ format, type,
+ params,
+ &size,
+ nullptr, nullptr,
+ nullptr, nullptr)) {
+ LOCAL_SET_GL_ERROR(
+ GL_OUT_OF_MEMORY, function_name, "dimensions too large");
+ return;
+ }
}
+ estimated_size += size;
level_width = std::max(1, level_width >> 1);
level_height = std::max(1, level_height >> 1);
if (target == GL_TEXTURE_3D)
level_depth = std::max(1, level_depth >> 1);
}
- if (!EnsureGPUMemoryAvailable(estimated_size)) {
- LOCAL_SET_GL_ERROR(
- GL_OUT_OF_MEMORY, "glTexStorage3D", "out of memory");
+ if (!estimated_size.IsValid() ||
+ !EnsureGPUMemoryAvailable(estimated_size.ValueOrDefault(0))) {
+ LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, function_name, "out of memory");
return;
}
}
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glTexStorage3D");
- glTexStorage3D(target, levels, internal_format, width, height, depth);
- GLenum error = LOCAL_PEEK_GL_ERROR("glTexStorage3D");
- if (error == GL_NO_ERROR) {
+ if (feature_info_->gl_version_info().IsLowerThanGL(4, 2) &&
+ !features().ext_texture_storage) {
+ // Emulate TexStorage with TexImage or CompressedTexImage.
+ Buffer* bound_buffer = buffer_manager()->GetBufferInfoForTarget(
+ &state_, GL_PIXEL_UNPACK_BUFFER);
+ if (bound_buffer) {
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ }
+
+ scoped_ptr<char[]> zero_data;
+ if (is_compressed_format) {
+ zero_data.reset(new char[level_size[0]]);
+ memset(zero_data.get(), 0, level_size[0]);
+ }
+
GLsizei level_width = width;
GLsizei level_height = height;
GLsizei level_depth = depth;
+ for (int ii = 0; ii < levels; ++ii) {
+ if (dimension == ContextState::k2D) {
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ for (int jj = 0; jj < 6; ++jj) {
+ GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
+ if (is_compressed_format) {
+ glCompressedTexImage2D(face, ii, internal_format,
+ level_width, level_height, 0,
+ level_size[ii], zero_data.get());
+ } else {
+ glTexImage2D(face, ii, internal_format, level_width, level_height,
+ 0, format, type, nullptr);
+ }
+ }
+ } else {
+ if (is_compressed_format) {
+ glCompressedTexImage2D(target, ii, internal_format,
+ level_width, level_height, 0,
+ level_size[ii], zero_data.get());
+ } else {
+ glTexImage2D(target, ii, internal_format, level_width, level_height,
+ 0, format, type, nullptr);
+ }
+ }
+ } else { // dimension == ContextState::k3D
+ if (is_compressed_format) {
+ DCHECK(target != GL_TEXTURE_3D);
+ glCompressedTexImage3D(target, ii, internal_format,
+ level_width, level_height, level_depth, 0,
+ level_size[ii], zero_data.get());
+ } else {
+ glTexImage3D(target, ii, internal_format, width, height, depth,
+ 0, format, type, nullptr);
+ }
+ }
+ level_width = std::max(1, level_width >> 1);
+ level_height = std::max(1, level_height >> 1);
+ if (target == GL_TEXTURE_3D)
+ level_depth = std::max(1, level_depth >> 1);
+ } // end of for-loop
+ if (bound_buffer) {
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bound_buffer->service_id());
+ }
+ } else {
+ if (dimension == ContextState::k2D)
+ glTexStorage2DEXT(target, levels, internal_format, width, height);
+ else
+ glTexStorage3D(target, levels, internal_format, width, height, depth);
+ }
- GLenum cur_format = feature_info_->IsES3Enabled() ?
- internal_format : format;
+ {
+ GLsizei level_width = width;
+ GLsizei level_height = height;
+ GLsizei level_depth = depth;
+ GLenum adjusted_format =
+ feature_info_->IsES3Enabled() ? internal_format : format;
for (int ii = 0; ii < levels; ++ii) {
- texture_manager()->SetLevelInfo(texture_ref, target, ii, cur_format,
- level_width, level_height, level_depth, 0,
- format, type, gfx::Rect());
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ for (int jj = 0; jj < 6; ++jj) {
+ GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + jj;
+ texture_manager()->SetLevelInfo(texture_ref, face, ii,
+ adjusted_format,
+ level_width, level_height, 1,
+ 0, format, type, gfx::Rect());
+ }
+ } else {
+ texture_manager()->SetLevelInfo(texture_ref, target, ii,
+ adjusted_format,
+ level_width, level_height, level_depth,
+ 0, format, type, gfx::Rect());
+ }
level_width = std::max(1, level_width >> 1);
level_height = std::max(1, level_height >> 1);
if (target == GL_TEXTURE_3D)
@@ -14502,6 +14546,31 @@ void GLES2DecoderImpl::DoTexStorage3D(
}
}
+void GLES2DecoderImpl::DoTexStorage2DEXT(
+ GLenum target,
+ GLint levels,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height) {
+ TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage2D",
+ "width", width, "height", height);
+ TexStorageImpl(target, levels, internal_format, width, height, 1,
+ ContextState::k2D, "glTexStorage2D");
+}
+
+void GLES2DecoderImpl::DoTexStorage3D(
+ GLenum target,
+ GLint levels,
+ GLenum internal_format,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth) {
+ TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoTexStorage3D",
+ "widthXheight", width * height, "depth", depth);
+ TexStorageImpl(target, levels, internal_format, width, height, depth,
+ ContextState::k3D, "glTexStorage3D");
+}
+
error::Error GLES2DecoderImpl::HandleGenMailboxCHROMIUM(
uint32_t immediate_data_size,
const void* cmd_data) {

Powered by Google App Engine
This is Rietveld 408576698