| Index: ui/gl/gl_image_memory.cc
|
| diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc
|
| index 045c50c464fa143353938887763329af87e22911..ad1e6b944b645179923b5a6b93a79525ceb0c783 100644
|
| --- a/ui/gl/gl_image_memory.cc
|
| +++ b/ui/gl/gl_image_memory.cc
|
| @@ -6,7 +6,10 @@
|
|
|
| #include "base/logging.h"
|
| #include "base/trace_event/trace_event.h"
|
| +#include "ui/gfx/buffer_format_util.h"
|
| #include "ui/gl/gl_bindings.h"
|
| +#include "ui/gl/gl_context.h"
|
| +#include "ui/gl/gl_version_info.h"
|
|
|
| namespace gfx {
|
| namespace {
|
| @@ -19,6 +22,7 @@ bool ValidInternalFormat(unsigned internalformat) {
|
| case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
| case GL_ETC1_RGB8_OES:
|
| case GL_R8:
|
| + case GL_RGB:
|
| case GL_RGBA:
|
| case GL_BGRA_EXT:
|
| return true;
|
| @@ -36,10 +40,11 @@ bool ValidFormat(BufferFormat format) {
|
| case BufferFormat::ETC1:
|
| case BufferFormat::R_8:
|
| case BufferFormat::RGBA_4444:
|
| + case BufferFormat::RGBX_8888:
|
| case BufferFormat::RGBA_8888:
|
| + case BufferFormat::BGRX_8888:
|
| case BufferFormat::BGRA_8888:
|
| return true;
|
| - case BufferFormat::BGRX_8888:
|
| case BufferFormat::YUV_420:
|
| case BufferFormat::YUV_420_BIPLANAR:
|
| case BufferFormat::UYVY_422:
|
| @@ -60,9 +65,10 @@ bool IsCompressedFormat(BufferFormat format) {
|
| return true;
|
| case BufferFormat::R_8:
|
| case BufferFormat::RGBA_4444:
|
| + case BufferFormat::RGBX_8888:
|
| case BufferFormat::RGBA_8888:
|
| - case BufferFormat::BGRA_8888:
|
| case BufferFormat::BGRX_8888:
|
| + case BufferFormat::BGRA_8888:
|
| case BufferFormat::YUV_420:
|
| case BufferFormat::YUV_420_BIPLANAR:
|
| case BufferFormat::UYVY_422:
|
| @@ -92,7 +98,9 @@ GLenum TextureFormat(BufferFormat format) {
|
| return GL_RGBA;
|
| case BufferFormat::BGRA_8888:
|
| return GL_BGRA_EXT;
|
| + case BufferFormat::RGBX_8888:
|
| case BufferFormat::BGRX_8888:
|
| + return GL_RGB;
|
| case BufferFormat::YUV_420:
|
| case BufferFormat::YUV_420_BIPLANAR:
|
| case BufferFormat::UYVY_422:
|
| @@ -105,14 +113,37 @@ GLenum TextureFormat(BufferFormat format) {
|
| }
|
|
|
| GLenum DataFormat(BufferFormat format) {
|
| - return TextureFormat(format);
|
| + switch (format) {
|
| + case BufferFormat::RGBX_8888:
|
| + return GL_RGBA;
|
| + case BufferFormat::BGRX_8888:
|
| + return GL_BGRA_EXT;
|
| + case BufferFormat::RGBA_4444:
|
| + case BufferFormat::RGBA_8888:
|
| + case BufferFormat::BGRA_8888:
|
| + case BufferFormat::R_8:
|
| + case BufferFormat::ATC:
|
| + case BufferFormat::ATCIA:
|
| + case BufferFormat::DXT1:
|
| + case BufferFormat::DXT5:
|
| + case BufferFormat::ETC1:
|
| + case BufferFormat::YUV_420:
|
| + case BufferFormat::YUV_420_BIPLANAR:
|
| + case BufferFormat::UYVY_422:
|
| + return TextureFormat(format);
|
| + }
|
| +
|
| + NOTREACHED();
|
| + return 0;
|
| }
|
|
|
| GLenum DataType(BufferFormat format) {
|
| switch (format) {
|
| case BufferFormat::RGBA_4444:
|
| return GL_UNSIGNED_SHORT_4_4_4_4;
|
| + case BufferFormat::RGBX_8888:
|
| case BufferFormat::RGBA_8888:
|
| + case BufferFormat::BGRX_8888:
|
| case BufferFormat::BGRA_8888:
|
| case BufferFormat::R_8:
|
| return GL_UNSIGNED_BYTE;
|
| @@ -121,7 +152,6 @@ GLenum DataType(BufferFormat format) {
|
| case BufferFormat::DXT1:
|
| case BufferFormat::DXT5:
|
| case BufferFormat::ETC1:
|
| - case BufferFormat::BGRX_8888:
|
| case BufferFormat::YUV_420:
|
| case BufferFormat::YUV_420_BIPLANAR:
|
| case BufferFormat::UYVY_422:
|
| @@ -133,71 +163,85 @@ GLenum DataType(BufferFormat format) {
|
| return 0;
|
| }
|
|
|
| -GLsizei SizeInBytes(const Size& size, BufferFormat 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 Size& size, unsigned internalformat)
|
| - : size_(size),
|
| - internalformat_(internalformat),
|
| - memory_(nullptr),
|
| - format_(BufferFormat::RGBA_8888) {}
|
| +template <typename F>
|
| +scoped_ptr<uint8_t[]> GLES2RGBData(const Size& size,
|
| + BufferFormat format,
|
| + const uint8_t* data,
|
| + F const& data_to_rgb,
|
| + GLenum* data_format,
|
| + GLenum* data_type) {
|
| + TRACE_EVENT2("gpu", "GLES2RGBData", "width", size.width(), "height",
|
| + size.height());
|
| +
|
| + // Four-byte row alignment as specified by glPixelStorei with argument
|
| + // GL_UNPACK_ALIGNMENT set to 4.
|
| + size_t gles2_rgb_data_stride = (size.width() * 3 + 3) & ~3;
|
| + scoped_ptr<uint8_t[]> gles2_rgb_data(
|
| + new uint8_t[gles2_rgb_data_stride * size.height()]);
|
| + size_t data_stride = RowSizeForBufferFormat(size.width(), format, 0);
|
| +
|
| + for (int y = 0; y < size.height(); ++y) {
|
| + for (int x = 0; x < size.width(); ++x) {
|
| + data_to_rgb(&data[y * data_stride + x * 4],
|
| + &gles2_rgb_data[y * gles2_rgb_data_stride + x * 3]);
|
| + }
|
| + }
|
|
|
| -GLImageMemory::~GLImageMemory() {
|
| - DCHECK(!memory_);
|
| + *data_format = GL_RGB;
|
| + *data_type = GL_UNSIGNED_BYTE;
|
| + return gles2_rgb_data.Pass();
|
| }
|
|
|
| -// static
|
| -bool GLImageMemory::StrideInBytes(size_t width,
|
| - BufferFormat format,
|
| - size_t* stride_in_bytes) {
|
| - base::CheckedNumeric<size_t> checked_stride = width;
|
| +scoped_ptr<uint8_t[]> GLES2Data(const Size& size,
|
| + BufferFormat format,
|
| + const uint8_t* data,
|
| + GLenum* data_format,
|
| + GLenum* data_type) {
|
| switch (format) {
|
| - case BufferFormat::ATCIA:
|
| - case BufferFormat::DXT5:
|
| - *stride_in_bytes = width;
|
| - return true;
|
| - case BufferFormat::ATC:
|
| - case BufferFormat::DXT1:
|
| - case BufferFormat::ETC1:
|
| - DCHECK_EQ(width % 2, 0u);
|
| - *stride_in_bytes = width / 2;
|
| - return true;
|
| - case BufferFormat::R_8:
|
| - checked_stride += 3;
|
| - if (!checked_stride.IsValid())
|
| - return false;
|
| - *stride_in_bytes = checked_stride.ValueOrDie() & ~0x3;
|
| - return true;
|
| + case BufferFormat::RGBX_8888:
|
| + return GLES2RGBData(size, format,
|
| + data, [](const uint8_t* src, uint8_t* dst) {
|
| + dst[0] = src[0];
|
| + dst[1] = src[1];
|
| + dst[2] = src[2];
|
| + }, data_format, data_type);
|
| + case BufferFormat::BGRX_8888:
|
| + return GLES2RGBData(size, format,
|
| + data, [](const uint8_t* src, uint8_t* dst) {
|
| + dst[0] = src[2];
|
| + dst[1] = src[1];
|
| + dst[2] = src[0];
|
| + }, data_format, data_type);
|
| case BufferFormat::RGBA_4444:
|
| - checked_stride *= 2;
|
| - if (!checked_stride.IsValid())
|
| - return false;
|
| - *stride_in_bytes = checked_stride.ValueOrDie();
|
| - return true;
|
| case BufferFormat::RGBA_8888:
|
| case BufferFormat::BGRA_8888:
|
| - checked_stride *= 4;
|
| - if (!checked_stride.IsValid())
|
| - return false;
|
| - *stride_in_bytes = checked_stride.ValueOrDie();
|
| - return true;
|
| - case BufferFormat::BGRX_8888:
|
| + case BufferFormat::R_8:
|
| + case BufferFormat::ATC:
|
| + case BufferFormat::ATCIA:
|
| + case BufferFormat::DXT1:
|
| + case BufferFormat::DXT5:
|
| + case BufferFormat::ETC1:
|
| case BufferFormat::YUV_420:
|
| case BufferFormat::YUV_420_BIPLANAR:
|
| case BufferFormat::UYVY_422:
|
| - NOTREACHED();
|
| - return false;
|
| + // No data conversion needed.
|
| + return nullptr;
|
| }
|
|
|
| NOTREACHED();
|
| - return false;
|
| + return 0;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +GLImageMemory::GLImageMemory(const Size& size, unsigned internalformat)
|
| + : size_(size),
|
| + internalformat_(internalformat),
|
| + memory_(nullptr),
|
| + format_(BufferFormat::RGBA_8888) {}
|
| +
|
| +GLImageMemory::~GLImageMemory() {
|
| + DCHECK(!memory_);
|
| }
|
|
|
| bool GLImageMemory::Initialize(const unsigned char* memory,
|
| @@ -246,13 +290,21 @@ bool GLImageMemory::CopyTexImage(unsigned target) {
|
| return false;
|
|
|
| if (IsCompressedFormat(format_)) {
|
| - glCompressedTexImage2D(target, 0, TextureFormat(format_), size_.width(),
|
| - size_.height(), 0, SizeInBytes(size_, format_),
|
| - memory_);
|
| + glCompressedTexImage2D(
|
| + target, 0, TextureFormat(format_), size_.width(), size_.height(), 0,
|
| + static_cast<GLsizei>(BufferSizeForBufferFormat(size_, format_)),
|
| + memory_);
|
| } else {
|
| + scoped_ptr<uint8_t[]> gles2_data;
|
| + GLenum data_format = DataFormat(format_);
|
| + GLenum data_type = DataType(format_);
|
| +
|
| + if (GLContext::GetCurrent()->GetVersionInfo()->is_es)
|
| + gles2_data = GLES2Data(size_, format_, memory_, &data_format, &data_type);
|
| +
|
| glTexImage2D(target, 0, TextureFormat(format_), size_.width(),
|
| - size_.height(), 0, DataFormat(format_), DataType(format_),
|
| - memory_);
|
| + size_.height(), 0, data_format, data_type,
|
| + gles2_data ? gles2_data.get() : memory_);
|
| }
|
|
|
| return true;
|
| @@ -276,19 +328,27 @@ bool GLImageMemory::CopyTexSubImage(unsigned target,
|
| if (IsCompressedFormat(format_) && rect.height() % 4)
|
| return false;
|
|
|
| - size_t stride_in_bytes = 0;
|
| - bool rv = StrideInBytes(size_.width(), format_, &stride_in_bytes);
|
| - DCHECK(rv);
|
| - DCHECK(memory_);
|
| - const unsigned char* data = memory_ + rect.y() * stride_in_bytes;
|
| + const uint8_t* data =
|
| + memory_ + rect.y() * RowSizeForBufferFormat(size_.width(), format_, 0);
|
| if (IsCompressedFormat(format_)) {
|
| - glCompressedTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(),
|
| - rect.height(), DataFormat(format_),
|
| - SizeInBytes(rect.size(), format_), data);
|
| + glCompressedTexSubImage2D(
|
| + target, 0, offset.x(), offset.y(), rect.width(), rect.height(),
|
| + DataFormat(format_),
|
| + static_cast<GLsizei>(BufferSizeForBufferFormat(rect.size(), format_)),
|
| + data);
|
| } else {
|
| + GLenum data_format = DataFormat(format_);
|
| + GLenum data_type = DataType(format_);
|
| + scoped_ptr<uint8_t[]> gles2_data;
|
| +
|
| + if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
|
| + gles2_data =
|
| + GLES2Data(rect.size(), format_, data, &data_format, &data_type);
|
| + }
|
| +
|
| glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(),
|
| - rect.height(), DataFormat(format_), DataType(format_),
|
| - data);
|
| + rect.height(), data_format, data_type,
|
| + gles2_data ? gles2_data.get() : data);
|
| }
|
|
|
| return true;
|
| @@ -302,4 +362,10 @@ bool GLImageMemory::ScheduleOverlayPlane(AcceleratedWidget widget,
|
| return false;
|
| }
|
|
|
| +// static
|
| +unsigned GLImageMemory::GetInternalFormatForTesting(BufferFormat format) {
|
| + DCHECK(ValidFormat(format));
|
| + return TextureFormat(format);
|
| +}
|
| +
|
| } // namespace gfx
|
|
|