diff options
19 files changed, 335 insertions, 33 deletions
diff --git a/cc/test/test_gpu_memory_buffer_manager.cc b/cc/test/test_gpu_memory_buffer_manager.cc index 196922f..7430051 100644 --- a/cc/test/test_gpu_memory_buffer_manager.cc +++ b/cc/test/test_gpu_memory_buffer_manager.cc @@ -12,6 +12,14 @@ namespace { size_t StrideInBytes(size_t width, gfx::GpuMemoryBuffer::Format format) { switch (format) { + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT5: + return width; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::ETC1: + DCHECK_EQ(width % 2, 0U); + return width / 2; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::BGRA_8888: diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.cc b/content/common/gpu/client/gpu_memory_buffer_impl.cc index 4b05bbf..e2a48be 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl.cc @@ -8,6 +8,7 @@ #include "base/numerics/safe_math.h" #include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h" #include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_image_memory.h" #if defined(OS_MACOSX) #include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h" @@ -33,6 +34,7 @@ GpuMemoryBufferImpl::GpuMemoryBufferImpl(gfx::GpuMemoryBufferId id, callback_(callback), mapped_(false), destruction_sync_point_(0) { + DCHECK(gfx::GLImageMemory::ValidSize(size, format)); } GpuMemoryBufferImpl::~GpuMemoryBufferImpl() { @@ -82,6 +84,20 @@ bool GpuMemoryBufferImpl::StrideInBytes(size_t width, size_t* stride_in_bytes) { base::CheckedNumeric<size_t> s = width; switch (format) { + case ATCIA: + case DXT5: + *stride_in_bytes = width; + return true; + case ATC: + case DXT1: + case ETC1: + DCHECK_EQ(width % 2, 0U); + s /= 2; + if (!s.IsValid()) + return false; + + *stride_in_bytes = s.ValueOrDie(); + return true; case RGBA_8888: case RGBX_8888: case BGRA_8888: diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc index 1ea7301..ade8e1a 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc @@ -115,6 +115,11 @@ GpuMemoryBufferImplSharedMemory::CreateFromHandle( // static bool GpuMemoryBufferImplSharedMemory::IsFormatSupported(Format format) { switch (format) { + case ATC: + case ATCIA: + case DXT1: + case DXT5: + case ETC1: case RGBA_8888: case BGRA_8888: return true; diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc b/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc index b645b8c..440dbfc 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc @@ -16,6 +16,11 @@ int WindowFormat(gfx::GpuMemoryBuffer::Format format) { switch (format) { case gfx::GpuMemoryBuffer::RGBA_8888: return WINDOW_FORMAT_RGBA_8888; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::BGRA_8888: NOTREACHED(); diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 87f0d05..c108a99 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -140,6 +140,29 @@ DevToolsChannelData::CreateForChannel(GpuChannel* channel) { return new DevToolsChannelData(res.release()); } +bool IsSupportedImageFormat(const gpu::Capabilities& capabilities, + gfx::GpuMemoryBuffer::Format format) { + switch (format) { + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + return capabilities.texture_format_atc; + case gfx::GpuMemoryBuffer::BGRA_8888: + return capabilities.texture_format_bgra8888; + case gfx::GpuMemoryBuffer::DXT1: + return capabilities.texture_format_dxt1; + case gfx::GpuMemoryBuffer::DXT5: + return capabilities.texture_format_dxt5; + case gfx::GpuMemoryBuffer::ETC1: + return capabilities.texture_format_etc1; + case gfx::GpuMemoryBuffer::RGBA_8888: + case gfx::GpuMemoryBuffer::RGBX_8888: + return true; + } + + NOTREACHED(); + return false; +} + } // namespace GpuCommandBufferStub::GpuCommandBufferStub( @@ -956,6 +979,11 @@ void GpuCommandBufferStub::OnCreateImage(int32 id, return; } + if (!IsSupportedImageFormat(decoder_->GetCapabilities(), format)) { + LOG(ERROR) << "Image format is not supported."; + return; + } + scoped_refptr<gfx::GLImage> image = channel()->CreateImageForGpuMemoryBuffer( handle, size, format, internalformat); if (!image.get()) diff --git a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc index ba00ea2..604c1b4 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc @@ -31,6 +31,11 @@ int32 BytesPerPixel(gfx::GpuMemoryBuffer::Format format) { switch (format) { case gfx::GpuMemoryBuffer::BGRA_8888: return 4; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: NOTREACHED(); @@ -45,6 +50,11 @@ int32 PixelFormat(gfx::GpuMemoryBuffer::Format format) { switch (format) { case gfx::GpuMemoryBuffer::BGRA_8888: return 'BGRA'; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: NOTREACHED(); diff --git a/gpu/command_buffer/common/capabilities.cc b/gpu/command_buffer/common/capabilities.cc index 97c26d8..58efef0 100644 --- a/gpu/command_buffer/common/capabilities.cc +++ b/gpu/command_buffer/common/capabilities.cc @@ -28,7 +28,10 @@ Capabilities::Capabilities() uniform_buffer_offset_alignment(1), post_sub_buffer(false), egl_image_external(false), + texture_format_atc(false), texture_format_bgra8888(false), + texture_format_dxt1(false), + texture_format_dxt5(false), texture_format_etc1(false), texture_format_etc1_npot(false), texture_rectangle(false), diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h index 92c3c19..b749d5c 100644 --- a/gpu/command_buffer/common/capabilities.h +++ b/gpu/command_buffer/common/capabilities.h @@ -81,7 +81,10 @@ struct GPU_EXPORT Capabilities { bool post_sub_buffer; bool egl_image_external; + bool texture_format_atc; bool texture_format_bgra8888; + bool texture_format_dxt1; + bool texture_format_dxt5; bool texture_format_etc1; bool texture_format_etc1_npot; bool texture_rectangle; diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 803b121..cb05749 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -132,7 +132,10 @@ FeatureInfo::FeatureFlags::FeatureFlags() use_arb_occlusion_query2_for_occlusion_query_boolean(false), use_arb_occlusion_query_for_occlusion_query_boolean(false), native_vertex_array_object(false), + ext_texture_format_atc(false), ext_texture_format_bgra8888(false), + ext_texture_format_dxt1(false), + ext_texture_format_dxt5(false), enable_shader_name_hashing(false), enable_samplers(false), ext_draw_buffers(false), @@ -333,6 +336,8 @@ void FeatureInfo::InitializeFeatures() { } if (enable_dxt1) { + feature_flags_.ext_texture_format_dxt1 = true; + AddExtensionString("GL_EXT_texture_compression_dxt1"); validators_.compressed_texture_format.AddValue( GL_COMPRESSED_RGB_S3TC_DXT1_EXT); @@ -350,6 +355,8 @@ void FeatureInfo::InitializeFeatures() { } if (enable_dxt5) { + feature_flags_.ext_texture_format_dxt5 = true; + // The difference between GL_EXT_texture_compression_s3tc and // GL_CHROMIUM_texture_compression_dxt5 is that the former // requires on the fly compression. The latter does not. @@ -358,6 +365,17 @@ void FeatureInfo::InitializeFeatures() { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); } + bool have_atc = extensions.Contains("GL_AMD_compressed_ATC_texture") || + extensions.Contains("GL_ATI_texture_compression_atitc"); + if (have_atc) { + feature_flags_.ext_texture_format_atc = true; + + AddExtensionString("GL_AMD_compressed_ATC_texture"); + validators_.compressed_texture_format.AddValue(GL_ATC_RGB_AMD); + validators_.compressed_texture_format.AddValue( + GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD); + } + // Check if we should enable GL_EXT_texture_filter_anisotropic. if (extensions.Contains("GL_EXT_texture_filter_anisotropic")) { AddExtensionString("GL_EXT_texture_filter_anisotropic"); diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index 8bc3e4f..1a1870d 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h @@ -56,7 +56,10 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> { bool use_arb_occlusion_query2_for_occlusion_query_boolean; bool use_arb_occlusion_query_for_occlusion_query_boolean; bool native_vertex_array_object; + bool ext_texture_format_atc; bool ext_texture_format_bgra8888; + bool ext_texture_format_dxt1; + bool ext_texture_format_dxt5; bool enable_shader_name_hashing; bool enable_samplers; bool ext_draw_buffers; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6b254e0..c96cb79 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -2858,8 +2858,14 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { caps.egl_image_external = feature_info_->feature_flags().oes_egl_image_external; + caps.texture_format_atc = + feature_info_->feature_flags().ext_texture_format_atc; caps.texture_format_bgra8888 = feature_info_->feature_flags().ext_texture_format_bgra8888; + caps.texture_format_dxt1 = + feature_info_->feature_flags().ext_texture_format_dxt1; + caps.texture_format_dxt5 = + feature_info_->feature_flags().ext_texture_format_dxt5; caps.texture_format_etc1 = feature_info_->feature_flags().oes_compressed_etc1_rgb8_texture; caps.texture_format_etc1_npot = diff --git a/gpu/command_buffer/service/image_factory.cc b/gpu/command_buffer/service/image_factory.cc index 0b740d8..1665c1e 100644 --- a/gpu/command_buffer/service/image_factory.cc +++ b/gpu/command_buffer/service/image_factory.cc @@ -22,6 +22,16 @@ gfx::GpuMemoryBuffer::Format ImageFactory::ImageFormatToGpuMemoryBufferFormat( return gfx::GpuMemoryBuffer::RGBX_8888; case GL_RGBA: return gfx::GpuMemoryBuffer::RGBA_8888; + case GL_ATC_RGB_AMD: + return gfx::GpuMemoryBuffer::ATC; + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + return gfx::GpuMemoryBuffer::ATCIA; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return gfx::GpuMemoryBuffer::DXT1; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return gfx::GpuMemoryBuffer::DXT5; + case GL_ETC1_RGB8_OES: + return gfx::GpuMemoryBuffer::ETC1; default: NOTREACHED(); return gfx::GpuMemoryBuffer::RGBA_8888; @@ -49,6 +59,11 @@ bool ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat( switch (internalformat) { case GL_RGB: switch (format) { + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBX_8888: return true; case gfx::GpuMemoryBuffer::RGBA_8888: @@ -61,6 +76,11 @@ bool ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat( switch (format) { case gfx::GpuMemoryBuffer::RGBX_8888: return false; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: return true; diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 43120b9..4e4eccb 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -40,6 +40,14 @@ namespace { size_t StrideInBytes(size_t width, gfx::GpuMemoryBuffer::Format format) { switch (format) { + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT5: + return width; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::ETC1: + DCHECK_EQ(width % 2, 0U); + return width / 2; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: return width * 4; diff --git a/gpu/ipc/gpu_command_buffer_traits_multi.h b/gpu/ipc/gpu_command_buffer_traits_multi.h index 2f834a0..810dbf8 100644 --- a/gpu/ipc/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/gpu_command_buffer_traits_multi.h @@ -47,7 +47,10 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities) IPC_STRUCT_TRAITS_MEMBER(uniform_buffer_offset_alignment) IPC_STRUCT_TRAITS_MEMBER(post_sub_buffer) IPC_STRUCT_TRAITS_MEMBER(egl_image_external) + IPC_STRUCT_TRAITS_MEMBER(texture_format_atc) IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888) + IPC_STRUCT_TRAITS_MEMBER(texture_format_dxt1) + IPC_STRUCT_TRAITS_MEMBER(texture_format_dxt5) IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1) IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1_npot) IPC_STRUCT_TRAITS_MEMBER(texture_rectangle) diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index e6ce5d2..3aa0964 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h @@ -42,7 +42,18 @@ class GFX_EXPORT GpuMemoryBuffer { public: // The format needs to be taken into account when mapping a buffer into the // client's address space. - enum Format { RGBA_8888, RGBX_8888, BGRA_8888, FORMAT_LAST = BGRA_8888 }; + enum Format { + ATC, + ATCIA, + DXT1, + DXT5, + ETC1, + RGBA_8888, + RGBX_8888, + BGRA_8888, + + FORMAT_LAST = BGRA_8888 + }; // The usage mode affects how a buffer can be used. Only buffers created with // MAP can be mapped into the client's address space and accessed by the CPU. diff --git a/ui/gl/gl_image_linux_dma_buffer.cc b/ui/gl/gl_image_linux_dma_buffer.cc index 1dec942..04ad06b 100644 --- a/ui/gl/gl_image_linux_dma_buffer.cc +++ b/ui/gl/gl_image_linux_dma_buffer.cc @@ -18,10 +18,25 @@ namespace { bool ValidFormat(unsigned internalformat, gfx::GpuMemoryBuffer::Format format) { switch (internalformat) { + case GL_ATC_RGB_AMD: + return format == gfx::GpuMemoryBuffer::ATC; + case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + return format == gfx::GpuMemoryBuffer::ATCIA; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return format == gfx::GpuMemoryBuffer::DXT1; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return format == gfx::GpuMemoryBuffer::DXT5; + case GL_ETC1_RGB8_OES: + return format == gfx::GpuMemoryBuffer::ETC1; case GL_RGB: switch (format) { case gfx::GpuMemoryBuffer::RGBX_8888: return true; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: return false; @@ -32,6 +47,11 @@ bool ValidFormat(unsigned internalformat, gfx::GpuMemoryBuffer::Format format) { switch (format) { case gfx::GpuMemoryBuffer::BGRA_8888: return true; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::RGBA_8888: return false; @@ -49,6 +69,11 @@ EGLint FourCC(gfx::GpuMemoryBuffer::Format format) { return DRM_FORMAT_ARGB8888; case gfx::GpuMemoryBuffer::RGBX_8888: return DRM_FORMAT_XRGB8888; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBA_8888: NOTREACHED(); return 0; diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc index e92cc1f..6b9a519 100644 --- a/ui/gl/gl_image_memory.cc +++ b/ui/gl/gl_image_memory.cc @@ -28,6 +28,11 @@ bool ValidInternalFormat(unsigned internalformat) { bool ValidFormat(gfx::GpuMemoryBuffer::Format format) { switch (format) { + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: return true; @@ -39,8 +44,36 @@ bool ValidFormat(gfx::GpuMemoryBuffer::Format format) { return false; } +bool IsCompressedFormat(gfx::GpuMemoryBuffer::Format format) { + switch (format) { + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: + return true; + case gfx::GpuMemoryBuffer::RGBA_8888: + case gfx::GpuMemoryBuffer::BGRA_8888: + case gfx::GpuMemoryBuffer::RGBX_8888: + return false; + } + + NOTREACHED(); + return false; +} + GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) { switch (format) { + case gfx::GpuMemoryBuffer::ATC: + return GL_ATC_RGB_AMD; + case gfx::GpuMemoryBuffer::ATCIA: + return GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD; + case gfx::GpuMemoryBuffer::DXT1: + return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + case gfx::GpuMemoryBuffer::DXT5: + return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + case gfx::GpuMemoryBuffer::ETC1: + return GL_ETC1_RGB8_OES; case gfx::GpuMemoryBuffer::RGBA_8888: return GL_RGBA; case gfx::GpuMemoryBuffer::BGRA_8888: @@ -63,6 +96,11 @@ GLenum DataType(gfx::GpuMemoryBuffer::Format format) { case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: return GL_UNSIGNED_BYTE; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBX_8888: NOTREACHED(); return 0; @@ -72,6 +110,15 @@ GLenum DataType(gfx::GpuMemoryBuffer::Format format) { return 0; } +GLsizei SizeInBytes(const gfx::Size& size, + gfx::GpuMemoryBuffer::Format format) { + size_t stride_in_bytes = 0; + bool valid_stride = GLImageMemory::StrideInBytes( + size.width(), format, &stride_in_bytes); + DCHECK(valid_stride); + return static_cast<GLsizei>(stride_in_bytes * size.height()); +} + } // namespace GLImageMemory::GLImageMemory(const gfx::Size& size, unsigned internalformat) @@ -105,6 +152,20 @@ bool GLImageMemory::StrideInBytes(size_t width, size_t* stride_in_bytes) { base::CheckedNumeric<size_t> s = width; switch (format) { + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT5: + *stride_in_bytes = width; + return true; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::ETC1: + DCHECK_EQ(width % 2, 0U); + s /= 2; + if (!s.IsValid()) + return false; + + *stride_in_bytes = s.ValueOrDie(); + return true; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: s *= 4; @@ -122,6 +183,30 @@ bool GLImageMemory::StrideInBytes(size_t width, return false; } +// static +bool GLImageMemory::ValidSize(const gfx::Size& size, + gfx::GpuMemoryBuffer::Format format) { + switch (format) { + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::ATCIA: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::DXT5: + case gfx::GpuMemoryBuffer::ETC1: + // Compressed images must have a width and height that's evenly divisible + // by the block size. + return size.width() % 4 == 0 && size.height() % 4 == 0; + case gfx::GpuMemoryBuffer::RGBA_8888: + case gfx::GpuMemoryBuffer::BGRA_8888: + return true; + case gfx::GpuMemoryBuffer::RGBX_8888: + NOTREACHED(); + return false; + } + + NOTREACHED(); + return false; +} + bool GLImageMemory::Initialize(const unsigned char* memory, gfx::GpuMemoryBuffer::Format format) { if (!ValidInternalFormat(internalformat_)) { @@ -187,11 +272,21 @@ bool GLImageMemory::CopyTexImage(unsigned target) { return false; DCHECK(memory_); - glTexSubImage2D(target, 0, // level - 0, // x - 0, // y - size_.width(), size_.height(), DataFormat(format_), - DataType(format_), memory_); + if (IsCompressedFormat(format_)) { + glCompressedTexSubImage2D(target, + 0, // level + 0, // x-offset + 0, // y-offset + size_.width(), size_.height(), + DataFormat(format_), SizeInBytes(size_, format_), + memory_); + } else { + glTexSubImage2D(target, 0, // level + 0, // x + 0, // y + size_.width(), size_.height(), DataFormat(format_), + DataType(format_), memory_); + } return true; } @@ -240,15 +335,24 @@ void GLImageMemory::DoBindTexImage(unsigned target) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, - 0, // mip level - TextureFormat(format_), - size_.width(), - size_.height(), - 0, // border - DataFormat(format_), - DataType(format_), - memory_); + if (IsCompressedFormat(format_)) { + glCompressedTexImage2D(GL_TEXTURE_2D, + 0, // mip level + TextureFormat(format_), size_.width(), + size_.height(), + 0, // border + SizeInBytes(size_, format_), memory_); + } else { + glTexImage2D(GL_TEXTURE_2D, + 0, // mip level + TextureFormat(format_), + size_.width(), + size_.height(), + 0, // border + DataFormat(format_), + DataType(format_), + memory_); + } } EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; @@ -265,15 +369,26 @@ void GLImageMemory::DoBindTexImage(unsigned target) { } else { ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_); - glTexSubImage2D(GL_TEXTURE_2D, - 0, // mip level - 0, // x-offset - 0, // y-offset - size_.width(), - size_.height(), - DataFormat(format_), - DataType(format_), - memory_); + if (IsCompressedFormat(format_)) { + glCompressedTexSubImage2D(GL_TEXTURE_2D, + 0, // mip level + 0, // x-offset + 0, // y-offset + size_.width(), size_.height(), + DataFormat(format_), + SizeInBytes(size_, format_), + memory_); + } else { + glTexSubImage2D(GL_TEXTURE_2D, + 0, // mip level + 0, // x-offset + 0, // y-offset + size_.width(), + size_.height(), + DataFormat(format_), + DataType(format_), + memory_); + } } glEGLImageTargetTexture2DOES(target, egl_image_); @@ -283,15 +398,24 @@ void GLImageMemory::DoBindTexImage(unsigned target) { #endif DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target); - glTexImage2D(target, - 0, // mip level - TextureFormat(format_), - size_.width(), - size_.height(), - 0, // border - DataFormat(format_), - DataType(format_), - memory_); + if (IsCompressedFormat(format_)) { + glCompressedTexImage2D(target, + 0, // mip level + TextureFormat(format_), size_.width(), + size_.height(), + 0, // border + SizeInBytes(size_, format_), memory_); + } else { + glTexImage2D(target, + 0, // mip level + TextureFormat(format_), + size_.width(), + size_.height(), + 0, // border + DataFormat(format_), + DataType(format_), + memory_); + } } } // namespace gfx diff --git a/ui/gl/gl_image_memory.h b/ui/gl/gl_image_memory.h index a50a380..befc3a8 100644 --- a/ui/gl/gl_image_memory.h +++ b/ui/gl/gl_image_memory.h @@ -26,6 +26,9 @@ class GL_EXPORT GLImageMemory : public GLImage { gfx::GpuMemoryBuffer::Format format, size_t* stride_in_bytes); + static bool ValidSize(const gfx::Size& size, + gfx::GpuMemoryBuffer::Format format); + bool Initialize(const unsigned char* memory, gfx::GpuMemoryBuffer::Format format); diff --git a/ui/gl/gl_image_shared_memory.cc b/ui/gl/gl_image_shared_memory.cc index d9e31a7..363ebf5 100644 --- a/ui/gl/gl_image_shared_memory.cc +++ b/ui/gl/gl_image_shared_memory.cc @@ -18,6 +18,9 @@ bool SizeInBytes(const gfx::Size& size, if (size.IsEmpty()) return false; + if (!GLImageMemory::ValidSize(size, format)) + return false; + size_t stride_in_bytes = 0; if (!GLImageMemory::StrideInBytes(size.width(), format, &stride_in_bytes)) return false; |