Index: cc/resources/resource_provider.cc |
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc |
index 017c2e9cacebe3501bf24af8e4552d7086f12a97..e1cbba56053bdb6b3ddfd43bad47cbebda23d31e 100644 |
--- a/cc/resources/resource_provider.cc |
+++ b/cc/resources/resource_provider.cc |
@@ -12,6 +12,7 @@ |
#include "base/stl_util.h" |
#include "base/strings/string_split.h" |
#include "base/strings/string_util.h" |
+#include "cc/base/util.h" |
#include "cc/output/gl_renderer.h" // For the GLC() macro. |
#include "cc/resources/platform_color.h" |
#include "cc/resources/returned_resource.h" |
@@ -34,24 +35,31 @@ namespace { |
const double kSoftwareUploadTickRate = 0.000250; |
const double kTextureUploadTickRate = 0.004; |
-GLenum TextureToStorageFormat(GLenum texture_format) { |
+GLenum TextureToStorageFormat(ResourceFormat format) { |
GLenum storage_format = GL_RGBA8_OES; |
- switch (texture_format) { |
- case GL_RGBA: |
+ switch (format) { |
+ case RGBA_8888: |
+ case RGBA_4444: |
+ case LUMINANCE_8: |
break; |
- case GL_BGRA_EXT: |
+ case BGRA_8888: |
storage_format = GL_BGRA8_EXT; |
break; |
- default: |
- NOTREACHED(); |
- break; |
} |
return storage_format; |
} |
-bool IsTextureFormatSupportedForStorage(GLenum format) { |
- return (format == GL_RGBA || format == GL_BGRA_EXT); |
+bool IsFormatSupportedForStorage(ResourceFormat format) { |
+ switch (format) { |
+ case RGBA_8888: |
+ case BGRA_8888: |
+ return true; |
+ case RGBA_4444: |
+ case LUMINANCE_8: |
+ return false; |
+ } |
+ return false; |
} |
class ScopedSetActiveTexture { |
@@ -95,7 +103,6 @@ ResourceProvider::Resource::Resource() |
enable_read_lock_fences(false), |
read_lock_fence(NULL), |
size(), |
- format(0), |
original_filter(0), |
filter(0), |
target(0), |
@@ -103,18 +110,19 @@ ResourceProvider::Resource::Resource() |
texture_pool(0), |
wrap_mode(0), |
hint(TextureUsageAny), |
- type(static_cast<ResourceType>(0)) {} |
+ type(static_cast<ResourceType>(0)), |
+ format(RGBA_8888) {} |
ResourceProvider::Resource::~Resource() {} |
ResourceProvider::Resource::Resource( |
unsigned texture_id, |
gfx::Size size, |
- GLenum format, |
GLenum filter, |
GLenum texture_pool, |
GLint wrap_mode, |
- TextureUsageHint hint) |
+ TextureUsageHint hint, |
+ ResourceFormat format) |
: gl_id(texture_id), |
gl_pixel_buffer_id(0), |
gl_upload_query_id(0), |
@@ -132,7 +140,6 @@ ResourceProvider::Resource::Resource( |
enable_read_lock_fences(false), |
read_lock_fence(NULL), |
size(size), |
- format(format), |
original_filter(filter), |
filter(filter), |
target(0), |
@@ -140,14 +147,14 @@ ResourceProvider::Resource::Resource( |
texture_pool(texture_pool), |
wrap_mode(wrap_mode), |
hint(hint), |
- type(GLTexture) { |
+ type(GLTexture), |
+ format(format) { |
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); |
} |
ResourceProvider::Resource::Resource( |
uint8_t* pixels, |
gfx::Size size, |
- GLenum format, |
GLenum filter, |
GLint wrap_mode) |
: gl_id(0), |
@@ -167,7 +174,6 @@ ResourceProvider::Resource::Resource( |
enable_read_lock_fences(false), |
read_lock_fence(NULL), |
size(size), |
- format(format), |
original_filter(filter), |
filter(filter), |
target(0), |
@@ -175,7 +181,8 @@ ResourceProvider::Resource::Resource( |
texture_pool(0), |
wrap_mode(wrap_mode), |
hint(TextureUsageAny), |
- type(Bitmap) { |
+ type(Bitmap), |
+ format(RGBA_8888) { |
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT); |
} |
@@ -185,9 +192,12 @@ ResourceProvider::Child::~Child() {} |
scoped_ptr<ResourceProvider> ResourceProvider::Create( |
OutputSurface* output_surface, |
- int highp_threshold_min) { |
+ int highp_threshold_min, |
+ bool use_rgba_4444_texture_format) { |
scoped_ptr<ResourceProvider> resource_provider( |
- new ResourceProvider(output_surface, highp_threshold_min)); |
+ new ResourceProvider(output_surface, |
+ highp_threshold_min, |
+ use_rgba_4444_texture_format)); |
bool success = false; |
if (resource_provider->Context3d()) { |
@@ -217,17 +227,20 @@ bool ResourceProvider::InUseByConsumer(ResourceId id) { |
} |
ResourceProvider::ResourceId ResourceProvider::CreateResource( |
- gfx::Size size, GLenum format, GLint wrap_mode, TextureUsageHint hint) { |
+ gfx::Size size, |
+ GLint wrap_mode, |
+ TextureUsageHint hint, |
+ ResourceFormat format) { |
DCHECK(!size.IsEmpty()); |
switch (default_resource_type_) { |
case GLTexture: |
- return CreateGLTexture(size, format, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, |
- wrap_mode, hint); |
+ return CreateGLTexture(size, |
+ GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, |
+ wrap_mode, |
+ hint, |
+ format); |
case Bitmap: |
- // The only wrap_mode currently implemented in software mode is |
- // GL_CLAMP_TO_EDGE. |
- // http://crbug.com/284796 |
- DCHECK(format == GL_RGBA); |
+ DCHECK_EQ(RGBA_8888, format); |
return CreateBitmap(size); |
case InvalidType: |
break; |
@@ -238,14 +251,20 @@ ResourceProvider::ResourceId ResourceProvider::CreateResource( |
} |
ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( |
- gfx::Size size, GLenum format, GLint wrap_mode, TextureUsageHint hint) { |
+ gfx::Size size, |
+ GLint wrap_mode, |
+ TextureUsageHint hint, |
+ ResourceFormat format) { |
DCHECK(!size.IsEmpty()); |
switch (default_resource_type_) { |
case GLTexture: |
- return CreateGLTexture(size, format, GL_TEXTURE_POOL_MANAGED_CHROMIUM, |
- wrap_mode, hint); |
+ return CreateGLTexture(size, |
+ GL_TEXTURE_POOL_MANAGED_CHROMIUM, |
+ wrap_mode, |
+ hint, |
+ format); |
case Bitmap: |
- DCHECK(format == GL_RGBA); |
+ DCHECK_EQ(RGBA_8888, format); |
return CreateBitmap(size); |
case InvalidType: |
break; |
@@ -257,16 +276,16 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource( |
ResourceProvider::ResourceId ResourceProvider::CreateGLTexture( |
gfx::Size size, |
- GLenum format, |
GLenum texture_pool, |
GLint wrap_mode, |
- TextureUsageHint hint) { |
+ TextureUsageHint hint, |
+ ResourceFormat format) { |
DCHECK_LE(size.width(), max_texture_size_); |
DCHECK_LE(size.height(), max_texture_size_); |
DCHECK(thread_checker_.CalledOnValidThread()); |
ResourceId id = next_id_++; |
- Resource resource(0, size, format, GL_LINEAR, texture_pool, wrap_mode, hint); |
+ Resource resource(0, size, GL_LINEAR, texture_pool, wrap_mode, hint, format); |
resource.allocated = false; |
resources_[id] = resource; |
return id; |
@@ -278,7 +297,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) { |
uint8_t* pixels = new uint8_t[4 * size.GetArea()]; |
ResourceId id = next_id_++; |
- Resource resource(pixels, size, GL_RGBA, GL_LINEAR, GL_CLAMP_TO_EDGE); |
+ Resource resource(pixels, size, GL_LINEAR, GL_CLAMP_TO_EDGE); |
resource.allocated = true; |
resources_[id] = resource; |
return id; |
@@ -303,8 +322,13 @@ ResourceProvider::CreateResourceFromExternalTexture( |
texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); |
ResourceId id = next_id_++; |
- Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR, 0, GL_CLAMP_TO_EDGE, |
- TextureUsageAny); |
+ Resource resource(texture_id, |
+ gfx::Size(), |
+ GL_LINEAR, |
+ 0, |
+ GL_CLAMP_TO_EDGE, |
+ TextureUsageAny, |
+ RGBA_8888); |
resource.external = true; |
resource.allocated = true; |
resources_[id] = resource; |
@@ -320,15 +344,20 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox( |
DCHECK(mailbox.IsValid()); |
Resource& resource = resources_[id]; |
if (mailbox.IsTexture()) { |
- resource = Resource(0, gfx::Size(), 0, GL_LINEAR, 0, GL_CLAMP_TO_EDGE, |
- TextureUsageAny); |
+ resource = Resource(0, |
+ gfx::Size(), |
+ GL_LINEAR, |
+ 0, |
+ GL_CLAMP_TO_EDGE, |
+ TextureUsageAny, |
+ RGBA_8888); |
} else { |
DCHECK(mailbox.IsSharedMemory()); |
base::SharedMemory* shared_memory = mailbox.shared_memory(); |
DCHECK(shared_memory->memory()); |
uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory()); |
- resource = Resource(pixels, mailbox.shared_memory_size(), |
- GL_RGBA, GL_LINEAR, GL_CLAMP_TO_EDGE); |
+ resource = Resource( |
+ pixels, mailbox.shared_memory_size(), GL_LINEAR, GL_CLAMP_TO_EDGE); |
} |
resource.external = true; |
resource.allocated = true; |
@@ -448,7 +477,7 @@ void ResourceProvider::SetPixels(ResourceId id, |
if (resource->pixels) { |
DCHECK(resource->allocated); |
- DCHECK(resource->format == GL_RGBA); |
+ DCHECK_EQ(RGBA_8888, resource->format); |
SkBitmap src_full; |
src_full.setConfig( |
SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height()); |
@@ -672,7 +701,7 @@ ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { |
void ResourceProvider::PopulateSkBitmapWithResource( |
SkBitmap* sk_bitmap, const Resource* resource) { |
DCHECK(resource->pixels); |
- DCHECK(resource->format == GL_RGBA); |
+ DCHECK_EQ(RGBA_8888, resource->format); |
sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
resource->size.width(), |
resource->size.height()); |
@@ -707,7 +736,8 @@ ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { |
} |
ResourceProvider::ResourceProvider(OutputSurface* output_surface, |
- int highp_threshold_min) |
+ int highp_threshold_min, |
+ bool use_rgba_4444_texture_format) |
: output_surface_(output_surface), |
lost_output_surface_(false), |
highp_threshold_min_(highp_threshold_min), |
@@ -718,7 +748,8 @@ ResourceProvider::ResourceProvider(OutputSurface* output_surface, |
use_texture_usage_hint_(false), |
use_shallow_flush_(false), |
max_texture_size_(0), |
- best_texture_format_(0) { |
+ best_texture_format_(RGBA_8888), |
+ use_rgba_4444_texture_format_(use_rgba_4444_texture_format) { |
DCHECK(output_surface_->HasClient()); |
} |
@@ -730,7 +761,7 @@ void ResourceProvider::InitializeSoftware() { |
default_resource_type_ = Bitmap; |
max_texture_size_ = INT_MAX / 2; |
- best_texture_format_ = GL_RGBA; |
+ best_texture_format_ = RGBA_8888; |
} |
bool ResourceProvider::InitializeGL() { |
@@ -931,10 +962,16 @@ void ResourceProvider::ReceiveFromChild( |
GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); |
GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, |
it->mailbox.name)); |
+ |
ResourceId id = next_id_++; |
Resource resource( |
- texture_id, it->size, it->format, it->filter, 0, GL_CLAMP_TO_EDGE, |
- TextureUsageAny); |
+ texture_id, |
+ it->size, |
+ it->filter, |
+ 0, |
+ GL_CLAMP_TO_EDGE, |
+ TextureUsageAny, |
+ it->format); |
resource.mailbox.SetName(it->mailbox); |
// Don't allocate a texture for a child. |
resource.allocated = true; |
@@ -1023,9 +1060,11 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) { |
context3d->bindBuffer( |
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
resource->gl_pixel_buffer_id); |
+ unsigned bytes_per_pixel = BytesPerPixel(resource->format); |
context3d->bufferData( |
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, |
- 4 * resource->size.GetArea(), |
+ resource->size.height() * RoundUp(bytes_per_pixel |
+ * resource->size.width(), 4u), |
NULL, |
GL_DYNAMIC_DRAW); |
context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); |
@@ -1201,25 +1240,27 @@ void ResourceProvider::BeginSetPixels(ResourceId id) { |
GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, |
resource->gl_upload_query_id); |
if (allocate) { |
- context3d->asyncTexImage2DCHROMIUM(GL_TEXTURE_2D, |
- 0, /* level */ |
- resource->format, |
- resource->size.width(), |
- resource->size.height(), |
- 0, /* border */ |
- resource->format, |
- GL_UNSIGNED_BYTE, |
- NULL); |
+ context3d->asyncTexImage2DCHROMIUM( |
+ GL_TEXTURE_2D, |
+ 0, /* level */ |
+ GetGLInternalFormat(resource->format), |
+ resource->size.width(), |
+ resource->size.height(), |
+ 0, /* border */ |
+ GetGLDataFormat(resource->format), |
+ GetGLDataType(resource->format), |
+ NULL); |
} else { |
- context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D, |
- 0, /* level */ |
- 0, /* x */ |
- 0, /* y */ |
- resource->size.width(), |
- resource->size.height(), |
- resource->format, |
- GL_UNSIGNED_BYTE, |
- NULL); |
+ context3d->asyncTexSubImage2DCHROMIUM( |
+ GL_TEXTURE_2D, |
+ 0, /* level */ |
+ 0, /* x */ |
+ 0, /* y */ |
+ resource->size.width(), |
+ resource->size.height(), |
+ GetGLDataFormat(resource->format), |
+ GetGLDataType(resource->format), |
+ NULL); |
} |
context3d->endQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM); |
context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0); |
@@ -1228,7 +1269,7 @@ void ResourceProvider::BeginSetPixels(ResourceId id) { |
if (resource->pixels) { |
DCHECK(!resource->mailbox.IsValid()); |
DCHECK(resource->pixel_buffer); |
- DCHECK(resource->format == GL_RGBA); |
+ DCHECK_EQ(RGBA_8888, resource->format); |
std::swap(resource->pixels, resource->pixel_buffer); |
delete[] resource->pixel_buffer; |
@@ -1334,9 +1375,9 @@ void ResourceProvider::LazyAllocate(Resource* resource) { |
resource->allocated = true; |
WebGraphicsContext3D* context3d = Context3d(); |
gfx::Size& size = resource->size; |
- GLenum format = resource->format; |
+ ResourceFormat format = resource->format; |
GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id)); |
- if (use_texture_storage_ext_ && IsTextureFormatSupportedForStorage(format)) { |
+ if (use_texture_storage_ext_ && IsFormatSupportedForStorage(format)) { |
GLenum storage_format = TextureToStorageFormat(format); |
GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, |
1, |
@@ -1346,12 +1387,12 @@ void ResourceProvider::LazyAllocate(Resource* resource) { |
} else { |
GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, |
0, |
- format, |
+ GetGLInternalFormat(format), |
size.width(), |
size.height(), |
0, |
- format, |
- GL_UNSIGNED_BYTE, |
+ GetGLDataFormat(format), |
+ GetGLDataType(format), |
NULL)); |
} |
} |
@@ -1376,7 +1417,7 @@ void ResourceProvider::AcquireImage(ResourceId id) { |
resource->allocated = true; |
WebGraphicsContext3D* context3d = Context3d(); |
DCHECK(context3d); |
- DCHECK_EQ(static_cast<GLenum>(GL_RGBA), resource->format); |
+ DCHECK_EQ(RGBA_8888, resource->format); |
resource->image_id = context3d->createImageCHROMIUM( |
resource->size.width(), resource->size.height(), GL_RGBA8_OES); |
DCHECK(resource->image_id); |
@@ -1456,4 +1497,62 @@ WebKit::WebGraphicsContext3D* ResourceProvider::Context3d() const { |
return context_provider ? context_provider->Context3d() : NULL; |
} |
+size_t ResourceProvider::BytesPerPixel(ResourceFormat format) { |
+ size_t components_per_pixel = 0; |
+ switch (format) { |
+ case RGBA_8888: |
+ case RGBA_4444: |
+ case BGRA_8888: |
+ components_per_pixel = 4; |
+ break; |
+ case LUMINANCE_8: |
+ components_per_pixel = 1; |
+ break; |
+ } |
+ size_t bits_per_component = 0; |
+ switch (format) { |
+ case RGBA_8888: |
+ case BGRA_8888: |
+ case LUMINANCE_8: |
+ bits_per_component = 8; |
+ break; |
+ case RGBA_4444: |
+ bits_per_component = 4; |
+ break; |
+ } |
+ const size_t kBitsPerByte = 8; |
+ return (components_per_pixel * bits_per_component) / kBitsPerByte; |
+} |
+ |
+GLenum ResourceProvider::GetGLDataType(ResourceFormat format) { |
+ switch (format) { |
+ case RGBA_4444: |
+ return GL_UNSIGNED_SHORT_4_4_4_4; |
+ case RGBA_8888: |
+ case BGRA_8888: |
+ case LUMINANCE_8: |
+ return GL_UNSIGNED_BYTE; |
+ } |
+ NOTREACHED(); |
+ return GL_UNSIGNED_BYTE; |
+} |
+ |
+GLenum ResourceProvider::GetGLDataFormat(ResourceFormat format) { |
+ switch (format) { |
+ case RGBA_8888: |
+ case RGBA_4444: |
+ return GL_RGBA; |
+ case BGRA_8888: |
+ return GL_BGRA_EXT; |
+ case LUMINANCE_8: |
+ return GL_LUMINANCE; |
+ } |
+ NOTREACHED(); |
+ return GL_RGBA; |
+} |
+ |
+GLenum ResourceProvider::GetGLInternalFormat(ResourceFormat format) { |
+ return GetGLDataFormat(format); |
+} |
+ |
} // namespace cc |