summaryrefslogtreecommitdiff
path: root/chromium/cc/resources/resource_provider.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/resources/resource_provider.cc')
-rw-r--r--chromium/cc/resources/resource_provider.cc966
1 files changed, 611 insertions, 355 deletions
diff --git a/chromium/cc/resources/resource_provider.cc b/chromium/cc/resources/resource_provider.cc
index 11eaab07a28..ee761d17564 100644
--- a/chromium/cc/resources/resource_provider.cc
+++ b/chromium/cc/resources/resource_provider.cc
@@ -8,12 +8,13 @@
#include <limits>
#include "base/containers/hash_tables.h"
-#include "base/debug/alias.h"
#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"
#include "cc/resources/transferable_resource.h"
#include "cc/scheduler/texture_uploader.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -29,15 +30,21 @@ namespace cc {
namespace {
-GLenum TextureToStorageFormat(GLenum texture_format) {
+// Measured in seconds.
+const double kSoftwareUploadTickRate = 0.000250;
+const double kTextureUploadTickRate = 0.004;
+
+GLenum TextureToStorageFormat(ResourceFormat format) {
GLenum storage_format = GL_RGBA8_OES;
- switch (texture_format) {
- case GL_RGBA:
+ switch (format) {
+ case RGBA_8888:
break;
- case GL_BGRA_EXT:
+ case BGRA_8888:
storage_format = GL_BGRA8_EXT;
break;
- default:
+ case RGBA_4444:
+ case LUMINANCE_8:
+ case RGB_565:
NOTREACHED();
break;
}
@@ -45,37 +52,54 @@ GLenum TextureToStorageFormat(GLenum texture_format) {
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:
+ case RGB_565:
+ return false;
+ }
+ return false;
}
-unsigned CreateTextureId(WebGraphicsContext3D* context3d) {
- unsigned texture_id = 0;
- GLC(context3d, texture_id = context3d->createTexture());
- GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GLC(context3d, context3d->texParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- return texture_id;
-}
+class ScopedSetActiveTexture {
+ public:
+ ScopedSetActiveTexture(WebGraphicsContext3D* context3d, GLenum unit)
+ : context3d_(context3d), unit_(unit) {
+ DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(context3d_));
+
+ if (unit_ != GL_TEXTURE0)
+ GLC(context3d_, context3d_->activeTexture(unit_));
+ }
+
+ ~ScopedSetActiveTexture() {
+ // Active unit being GL_TEXTURE0 is effectively the ground state.
+ if (unit_ != GL_TEXTURE0)
+ GLC(context3d_, context3d_->activeTexture(GL_TEXTURE0));
+ }
+
+ private:
+ WebGraphicsContext3D* context3d_;
+ GLenum unit_;
+};
} // namespace
ResourceProvider::Resource::Resource()
- : gl_id(0),
+ : child_id(0),
+ gl_id(0),
gl_pixel_buffer_id(0),
gl_upload_query_id(0),
pixels(NULL),
pixel_buffer(NULL),
lock_for_read_count(0),
+ imported_count(0),
+ exported_count(0),
locked_for_write(false),
external(false),
- exported(false),
marked_for_deletion(false),
pending_set_pixels(false),
set_pixels_completion_forced(false),
@@ -83,31 +107,37 @@ ResourceProvider::Resource::Resource()
enable_read_lock_fences(false),
read_lock_fence(NULL),
size(),
- format(0),
+ original_filter(0),
filter(0),
+ target(0),
image_id(0),
texture_pool(0),
+ wrap_mode(0),
+ lost(false),
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,
- TextureUsageHint hint)
- : gl_id(texture_id),
+ResourceProvider::Resource::Resource(unsigned texture_id,
+ gfx::Size size,
+ GLenum filter,
+ GLenum texture_pool,
+ GLint wrap_mode,
+ TextureUsageHint hint,
+ ResourceFormat format)
+ : child_id(0),
+ gl_id(texture_id),
gl_pixel_buffer_id(0),
gl_upload_query_id(0),
pixels(NULL),
pixel_buffer(NULL),
lock_for_read_count(0),
+ imported_count(0),
+ exported_count(0),
locked_for_write(false),
external(false),
- exported(false),
marked_for_deletion(false),
pending_set_pixels(false),
set_pixels_completion_forced(false),
@@ -115,24 +145,34 @@ ResourceProvider::Resource::Resource(
enable_read_lock_fences(false),
read_lock_fence(NULL),
size(size),
- format(format),
+ original_filter(filter),
filter(filter),
+ target(0),
image_id(0),
texture_pool(texture_pool),
+ wrap_mode(wrap_mode),
+ lost(false),
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)
- : gl_id(0),
+ResourceProvider::Resource::Resource(uint8_t* pixels,
+ gfx::Size size,
+ GLenum filter,
+ GLint wrap_mode)
+ : child_id(0),
+ gl_id(0),
gl_pixel_buffer_id(0),
gl_upload_query_id(0),
pixels(pixels),
pixel_buffer(NULL),
lock_for_read_count(0),
+ imported_count(0),
+ exported_count(0),
locked_for_write(false),
external(false),
- exported(false),
marked_for_deletion(false),
pending_set_pixels(false),
set_pixels_completion_forced(false),
@@ -140,12 +180,18 @@ ResourceProvider::Resource::Resource(
enable_read_lock_fences(false),
read_lock_fence(NULL),
size(size),
- format(format),
+ original_filter(filter),
filter(filter),
+ target(0),
image_id(0),
texture_pool(0),
+ wrap_mode(wrap_mode),
+ lost(false),
hint(TextureUsageAny),
- type(Bitmap) {}
+ type(Bitmap),
+ format(RGBA_8888) {
+ DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
+}
ResourceProvider::Child::Child() {}
@@ -153,12 +199,15 @@ 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 (output_surface->context3d()) {
+ if (resource_provider->Context3d()) {
success = resource_provider->InitializeGL();
} else {
resource_provider->InitializeSoftware();
@@ -173,34 +222,40 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create(
}
ResourceProvider::~ResourceProvider() {
+ while (!children_.empty())
+ DestroyChild(children_.begin()->first);
while (!resources_.empty())
DeleteResourceInternal(resources_.begin(), ForShutdown);
CleanUpGLIfNeeded();
}
-WebGraphicsContext3D* ResourceProvider::GraphicsContext3D() {
- DCHECK(thread_checker_.CalledOnValidThread());
- return output_surface_->context3d();
+bool ResourceProvider::InUseByConsumer(ResourceId id) {
+ Resource* resource = GetResource(id);
+ return resource->lock_for_read_count > 0 || resource->exported_count > 0 ||
+ resource->lost;
}
-bool ResourceProvider::InUseByConsumer(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
- return !!resource->lock_for_read_count || resource->exported;
+bool ResourceProvider::IsLost(ResourceId id) {
+ Resource* resource = GetResource(id);
+ return resource->lost;
}
ResourceProvider::ResourceId ResourceProvider::CreateResource(
- gfx::Size size, GLenum format, 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, hint);
+ return CreateGLTexture(size,
+ GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
+ wrap_mode,
+ hint,
+ format);
case Bitmap:
- DCHECK(format == GL_RGBA);
+ DCHECK_EQ(RGBA_8888, format);
return CreateBitmap(size);
case InvalidType:
break;
@@ -211,14 +266,20 @@ ResourceProvider::ResourceId ResourceProvider::CreateResource(
}
ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
- gfx::Size size, GLenum format, 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, 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;
@@ -229,13 +290,17 @@ ResourceProvider::ResourceId ResourceProvider::CreateManagedResource(
}
ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
- gfx::Size size, GLenum format, GLenum texture_pool, TextureUsageHint hint) {
+ gfx::Size size,
+ GLenum texture_pool,
+ GLint wrap_mode,
+ 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, hint);
+ Resource resource(0, size, GL_LINEAR, texture_pool, wrap_mode, hint, format);
resource.allocated = false;
resources_[id] = resource;
return id;
@@ -247,7 +312,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);
+ Resource resource(pixels, size, GL_LINEAR, GL_CLAMP_TO_EDGE);
resource.allocated = true;
resources_[id] = resource;
return id;
@@ -259,7 +324,7 @@ ResourceProvider::CreateResourceFromExternalTexture(
unsigned texture_id) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
GLC(context3d, context3d->bindTexture(texture_target, texture_id));
GLC(context3d, context3d->texParameteri(
@@ -272,7 +337,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, 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;
@@ -280,25 +351,35 @@ ResourceProvider::CreateResourceFromExternalTexture(
}
ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
- const TextureMailbox& mailbox) {
+ const TextureMailbox& mailbox,
+ scoped_ptr<SingleReleaseCallback> release_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
// Just store the information. Mailbox will be consumed in LockForRead().
ResourceId id = next_id_++;
DCHECK(mailbox.IsValid());
Resource& resource = resources_[id];
if (mailbox.IsTexture()) {
- resource = Resource(0, gfx::Size(), 0, GL_LINEAR, 0, 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);
+ resource = Resource(
+ pixels, mailbox.shared_memory_size(), GL_LINEAR, GL_CLAMP_TO_EDGE);
}
resource.external = true;
resource.allocated = true;
resource.mailbox = mailbox;
+ resource.release_callback =
+ base::Bind(&SingleReleaseCallback::Run,
+ base::Owned(release_callback.release()));
return id;
}
@@ -309,9 +390,10 @@ void ResourceProvider::DeleteResource(ResourceId id) {
Resource* resource = &it->second;
DCHECK(!resource->lock_for_read_count);
DCHECK(!resource->marked_for_deletion);
+ DCHECK_EQ(resource->imported_count, 0);
DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
- if (resource->exported) {
+ if (resource->exported_count > 0) {
resource->marked_for_deletion = true;
return;
} else {
@@ -322,37 +404,37 @@ void ResourceProvider::DeleteResource(ResourceId id) {
void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
DeleteStyle style) {
Resource* resource = &it->second;
- bool lost_resource = lost_output_surface_;
+ bool lost_resource = lost_output_surface_ || resource->lost;
- DCHECK(!resource->exported || style != Normal);
- if (style == ForShutdown && resource->exported)
+ DCHECK(resource->exported_count == 0 || style != Normal);
+ if (style == ForShutdown && resource->exported_count > 0)
lost_resource = true;
if (resource->image_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
GLC(context3d, context3d->destroyImageCHROMIUM(resource->image_id));
}
if (resource->gl_id && !resource->external) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
GLC(context3d, context3d->deleteTexture(resource->gl_id));
}
if (resource->gl_upload_query_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id));
}
if (resource->gl_pixel_buffer_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id));
}
if (resource->mailbox.IsValid() && resource->external) {
unsigned sync_point = resource->mailbox.sync_point();
if (resource->mailbox.IsTexture()) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
if (resource->gl_id)
GLC(context3d, context3d->deleteTexture(resource->gl_id));
@@ -366,7 +448,7 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
resource->pixels = NULL;
}
}
- resource->mailbox.RunReleaseCallback(sync_point, lost_resource);
+ resource->release_callback.Run(sync_point, lost_resource);
}
if (resource->pixels)
delete[] resource->pixels;
@@ -378,10 +460,7 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
ResourceProvider::ResourceType ResourceProvider::GetResourceType(
ResourceId id) {
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
- return resource->type;
+ return GetResource(id)->type;
}
void ResourceProvider::SetPixels(ResourceId id,
@@ -389,20 +468,17 @@ void ResourceProvider::SetPixels(ResourceId id,
gfx::Rect image_rect,
gfx::Rect source_rect,
gfx::Vector2d dest_offset) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->locked_for_write);
DCHECK(!resource->lock_for_read_count);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(ReadLockFenceHasPassed(resource));
LazyAllocate(resource);
if (resource->gl_id) {
DCHECK(!resource->pending_set_pixels);
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
DCHECK(texture_uploader_.get());
context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
@@ -416,7 +492,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());
@@ -470,23 +546,32 @@ void ResourceProvider::ReleaseCachedData() {
texture_uploader_->ReleaseCachedQueries();
}
+base::TimeDelta ResourceProvider::TextureUpdateTickRate() {
+ // Software resource uploads happen on impl thread, so don't bother batching
+ // them up and trying to wait for them to complete.
+ double rate =
+ texture_uploader_ ? kTextureUploadTickRate : kSoftwareUploadTickRate;
+ return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
+ rate);
+}
+
void ResourceProvider::Flush() {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
if (context3d)
context3d->flush();
}
void ResourceProvider::Finish() {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
if (context3d)
context3d->finish();
}
bool ResourceProvider::ShallowFlushIfSupported() {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
if (!context3d || !use_shallow_flush_)
return false;
@@ -494,16 +579,20 @@ bool ResourceProvider::ShallowFlushIfSupported() {
return true;
}
-const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
+ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) {
DCHECK(thread_checker_.CalledOnValidThread());
ResourceMap::iterator it = resources_.find(id);
CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ return &it->second;
+}
+
+const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
+ Resource* resource = GetResource(id);
DCHECK(!resource->locked_for_write ||
resource->set_pixels_completion_forced) <<
"locked for write: " << resource->locked_for_write <<
" pixels completion forced: " << resource->set_pixels_completion_forced;
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
// Uninitialized! Call SetPixels or LockForWrite first.
DCHECK(resource->allocated);
@@ -511,7 +600,7 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
if (resource->external) {
if (!resource->gl_id && resource->mailbox.IsTexture()) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
if (resource->mailbox.sync_point()) {
GLC(context3d,
@@ -534,25 +623,20 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
}
void ResourceProvider::UnlockForRead(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK_GT(resource->lock_for_read_count, 0);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
resource->lock_for_read_count--;
}
const ResourceProvider::Resource* ResourceProvider::LockForWrite(
ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->locked_for_write);
DCHECK(!resource->lock_for_read_count);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->external);
+ DCHECK(!resource->lost);
DCHECK(ReadLockFenceHasPassed(resource));
LazyAllocate(resource);
@@ -561,24 +645,16 @@ const ResourceProvider::Resource* ResourceProvider::LockForWrite(
}
bool ResourceProvider::CanLockForWrite(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
- return !resource->locked_for_write &&
- !resource->lock_for_read_count &&
- !resource->exported &&
- !resource->external &&
- ReadLockFenceHasPassed(resource);
+ Resource* resource = GetResource(id);
+ return !resource->locked_for_write && !resource->lock_for_read_count &&
+ !resource->exported_count && !resource->external && !resource->lost &&
+ ReadLockFenceHasPassed(resource);
}
void ResourceProvider::UnlockForWrite(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(resource->locked_for_write);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->external);
resource->locked_for_write = false;
}
@@ -639,7 +715,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());
@@ -674,7 +750,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),
@@ -685,7 +762,10 @@ 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());
+}
void ResourceProvider::InitializeSoftware() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -695,7 +775,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() {
@@ -703,7 +783,7 @@ bool ResourceProvider::InitializeGL() {
DCHECK(!texture_uploader_);
DCHECK_NE(GLTexture, default_resource_type_);
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
if (!context3d->makeContextCurrent())
@@ -711,24 +791,14 @@ bool ResourceProvider::InitializeGL() {
default_resource_type_ = GLTexture;
- std::string extensions_string =
- UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
- std::vector<std::string> extensions;
- base::SplitString(extensions_string, ' ', &extensions);
- bool use_map_sub = false;
- bool use_bgra = false;
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (extensions[i] == "GL_EXT_texture_storage")
- use_texture_storage_ext_ = true;
- else if (extensions[i] == "GL_ANGLE_texture_usage")
- use_texture_usage_hint_ = true;
- else if (extensions[i] == "GL_CHROMIUM_map_sub")
- use_map_sub = true;
- else if (extensions[i] == "GL_CHROMIUM_shallow_flush")
- use_shallow_flush_ = true;
- else if (extensions[i] == "GL_EXT_texture_format_BGRA8888")
- use_bgra = true;
- }
+ const ContextProvider::Capabilities& caps =
+ output_surface_->context_provider()->ContextCapabilities();
+
+ bool use_map_sub = caps.map_sub;
+ bool use_bgra = caps.texture_format_bgra8888;
+ use_texture_storage_ext_ = caps.texture_storage;
+ use_shallow_flush_ = caps.shallow_flush;
+ use_texture_usage_hint_ = caps.texture_usage;
texture_uploader_ =
TextureUploader::Create(context3d, use_map_sub, use_shallow_flush_);
@@ -740,7 +810,7 @@ bool ResourceProvider::InitializeGL() {
}
void ResourceProvider::CleanUpGLIfNeeded() {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
if (default_resource_type_ != GLTexture) {
// We are not in GL mode, but double check before returning.
DCHECK(!context3d);
@@ -754,9 +824,12 @@ void ResourceProvider::CleanUpGLIfNeeded() {
Finish();
}
-int ResourceProvider::CreateChild() {
+int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
+
Child child_info;
+ child_info.return_callback = return_callback;
+
int child = next_child_++;
children_[child] = child_info;
return child;
@@ -764,13 +837,26 @@ int ResourceProvider::CreateChild() {
void ResourceProvider::DestroyChild(int child_id) {
DCHECK(thread_checker_.CalledOnValidThread());
+
ChildMap::iterator it = children_.find(child_id);
DCHECK(it != children_.end());
Child& child = it->second;
+
+ ResourceIdArray resources_for_child;
+
for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
child_it != child.child_to_parent_map.end();
- ++child_it)
- DeleteResource(child_it->second);
+ ++child_it) {
+ ResourceId id = child_it->second;
+ resources_for_child.push_back(id);
+ }
+
+ // If the child is going away, don't consider any resources in use.
+ child.in_use_resources.clear();
+
+ DeleteAndReturnUnusedResourcesToChild(
+ &child, ForShutdown, resources_for_child);
+
children_.erase(it);
}
@@ -785,60 +871,21 @@ const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
TransferableResourceArray* list) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
- if (!context3d || !context3d->makeContextCurrent()) {
- // TODO(skaslev): Implement this path for software compositing.
- return;
- }
- bool need_sync_point = false;
- for (ResourceIdArray::const_iterator it = resources.begin();
- it != resources.end();
- ++it) {
- TransferableResource resource;
- if (TransferResource(context3d, *it, &resource)) {
- if (!resource.sync_point)
- need_sync_point = true;
- resources_.find(*it)->second.exported = true;
- list->push_back(resource);
- }
- }
- if (need_sync_point) {
- unsigned int sync_point = context3d->insertSyncPoint();
- for (TransferableResourceArray::iterator it = list->begin();
- it != list->end();
- ++it) {
- if (!it->sync_point)
- it->sync_point = sync_point;
- }
- }
-}
-
-void ResourceProvider::PrepareSendToChild(int child,
- const ResourceIdArray& resources,
- TransferableResourceArray* list) {
- DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
if (!context3d || !context3d->makeContextCurrent()) {
// TODO(skaslev): Implement this path for software compositing.
return;
}
- Child& child_info = children_.find(child)->second;
bool need_sync_point = false;
for (ResourceIdArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
TransferableResource resource;
- if (!TransferResource(context3d, *it, &resource))
- NOTREACHED();
+ TransferResource(context3d, *it, &resource);
if (!resource.sync_point)
need_sync_point = true;
- DCHECK(child_info.parent_to_child_map.find(*it) !=
- child_info.parent_to_child_map.end());
- resource.id = child_info.parent_to_child_map[*it];
- child_info.parent_to_child_map.erase(*it);
- child_info.child_to_parent_map.erase(resource.id);
+ ++resources_.find(*it)->second.exported_count;
list->push_back(resource);
- DeleteResource(*it);
}
if (need_sync_point) {
unsigned int sync_point = context3d->insertSyncPoint();
@@ -854,7 +901,7 @@ void ResourceProvider::PrepareSendToChild(int child,
void ResourceProvider::ReceiveFromChild(
int child, const TransferableResourceArray& resources) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
if (!context3d || !context3d->makeContextCurrent()) {
// TODO(skaslev): Implement this path for software compositing.
return;
@@ -863,6 +910,12 @@ void ResourceProvider::ReceiveFromChild(
for (TransferableResourceArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
+ ResourceIdMap::iterator resource_in_map_it =
+ child_info.child_to_parent_map.find(it->id);
+ if (resource_in_map_it != child_info.child_to_parent_map.end()) {
+ resources_[resource_in_map_it->second].imported_count++;
+ continue;
+ }
unsigned texture_id;
// NOTE: If the parent is a browser and the child a renderer, the parent
// is not supposed to have its context wait, because that could induce
@@ -876,62 +929,162 @@ 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, TextureUsageAny);
+ ResourceId local_id = next_id_++;
+ Resource resource(texture_id,
+ it->size,
+ it->filter,
+ 0,
+ GL_CLAMP_TO_EDGE,
+ TextureUsageAny,
+ it->format);
resource.mailbox.SetName(it->mailbox);
+ resource.child_id = child;
// Don't allocate a texture for a child.
resource.allocated = true;
- resources_[id] = resource;
- child_info.parent_to_child_map[id] = it->id;
- child_info.child_to_parent_map[it->id] = id;
+ resource.imported_count = 1;
+ resources_[local_id] = resource;
+ child_info.parent_to_child_map[local_id] = it->id;
+ child_info.child_to_parent_map[it->id] = local_id;
}
}
-void ResourceProvider::ReceiveFromParent(
- const TransferableResourceArray& resources) {
+void ResourceProvider::DeclareUsedResourcesFromChild(
+ int child,
+ const ResourceIdArray& resources_from_child) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+
+ Child& child_info = children_.find(child)->second;
+ child_info.in_use_resources.clear();
+
+ for (size_t i = 0; i < resources_from_child.size(); ++i) {
+ ResourceIdMap::iterator it =
+ child_info.child_to_parent_map.find(resources_from_child[i]);
+ DCHECK(it != child_info.child_to_parent_map.end());
+
+ ResourceId local_id = it->second;
+ child_info.in_use_resources.insert(local_id);
+ }
+
+ ResourceIdArray unused;
+ for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
+ it != child_info.child_to_parent_map.end();
+ ++it) {
+ ResourceId local_id = it->second;
+ bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
+ if (!resource_is_in_use)
+ unused.push_back(local_id);
+ }
+ DeleteAndReturnUnusedResourcesToChild(&child_info, Normal, unused);
+}
+
+// static
+bool ResourceProvider::CompareResourceMapIteratorsByChildId(
+ const std::pair<ReturnedResource, ResourceMap::iterator>& a,
+ const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
+ const ResourceMap::iterator& a_it = a.second;
+ const ResourceMap::iterator& b_it = b.second;
+ const Resource& a_resource = a_it->second;
+ const Resource& b_resource = b_it->second;
+ return a_resource.child_id < b_resource.child_id;
+}
+
+void ResourceProvider::ReceiveReturnsFromParent(
+ const ReturnedResourceArray& resources) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ WebGraphicsContext3D* context3d = Context3d();
if (!context3d || !context3d->makeContextCurrent()) {
// TODO(skaslev): Implement this path for software compositing.
return;
}
- for (TransferableResourceArray::const_iterator it = resources.begin();
+
+ int child_id = 0;
+ Child* child_info = NULL;
+ ResourceIdArray resources_for_child;
+
+ std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
+ sorted_resources;
+
+ for (ReturnedResourceArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
- ResourceMap::iterator map_iterator = resources_.find(it->id);
- DCHECK(map_iterator != resources_.end());
+ ResourceId local_id = it->id;
+ ResourceMap::iterator map_iterator = resources_.find(local_id);
+
+ // Resource was already lost (e.g. it belonged to a child that was
+ // destroyed).
+ if (map_iterator == resources_.end())
+ continue;
+
+ sorted_resources.push_back(
+ std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
+ }
+
+ std::sort(sorted_resources.begin(),
+ sorted_resources.end(),
+ CompareResourceMapIteratorsByChildId);
+
+ for (size_t i = 0; i < sorted_resources.size(); ++i) {
+ ReturnedResource& returned = sorted_resources[i].first;
+ ResourceMap::iterator& map_iterator = sorted_resources[i].second;
+ ResourceId local_id = map_iterator->first;
Resource* resource = &map_iterator->second;
- DCHECK(resource->exported);
- resource->exported = false;
- resource->filter = it->filter;
- DCHECK(resource->mailbox.ContainsMailbox(it->mailbox));
+
+ CHECK_GE(resource->exported_count, returned.count);
+ resource->exported_count -= returned.count;
+ resource->lost |= returned.lost;
+ if (resource->exported_count)
+ continue;
+
if (resource->gl_id) {
- if (it->sync_point)
- GLC(context3d, context3d->waitSyncPoint(it->sync_point));
+ if (returned.sync_point)
+ GLC(context3d, context3d->waitSyncPoint(returned.sync_point));
} else {
- resource->mailbox = TextureMailbox(resource->mailbox.name(),
- resource->mailbox.callback(),
- it->sync_point);
+ resource->mailbox =
+ TextureMailbox(resource->mailbox.name(), returned.sync_point);
}
- if (resource->marked_for_deletion)
+
+ if (!resource->marked_for_deletion)
+ continue;
+
+ if (!resource->child_id) {
+ // The resource belongs to this ResourceProvider, so it can be destroyed.
DeleteResourceInternal(map_iterator, Normal);
+ continue;
+ }
+
+ // Delete the resource and return it to the child it came from one.
+ if (resource->child_id != child_id) {
+ ChildMap::iterator child_it = children_.find(resource->child_id);
+ DCHECK(child_it != children_.end());
+
+ if (child_id) {
+ DCHECK_NE(resources_for_child.size(), 0u);
+ DeleteAndReturnUnusedResourcesToChild(
+ child_info, Normal, resources_for_child);
+ resources_for_child.clear();
+ }
+
+ child_info = &child_it->second;
+ child_id = resource->child_id;
+ }
+ resources_for_child.push_back(local_id);
+ }
+
+ if (child_id) {
+ DCHECK_NE(resources_for_child.size(), 0u);
+ DeleteAndReturnUnusedResourcesToChild(
+ child_info, Normal, resources_for_child);
}
}
-bool ResourceProvider::TransferResource(WebGraphicsContext3D* context,
+void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
ResourceId id,
TransferableResource* resource) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* source = &it->second;
+ Resource* source = GetResource(id);
DCHECK(!source->locked_for_write);
DCHECK(!source->lock_for_read_count);
DCHECK(!source->external || (source->external && source->mailbox.IsValid()));
DCHECK(source->allocated);
- if (source->exported)
- return false;
resource->id = id;
resource->format = source->format;
resource->filter = source->filter;
@@ -956,30 +1109,114 @@ bool ResourceProvider::TransferResource(WebGraphicsContext3D* context,
resource->sync_point = source->mailbox.sync_point();
source->mailbox.ResetSyncPoint();
}
+}
- return true;
+void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
+ Child* child_info,
+ DeleteStyle style,
+ const ResourceIdArray& unused) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(child_info);
+
+ if (unused.empty())
+ return;
+
+ WebGraphicsContext3D* context3d = Context3d();
+ if (!context3d || !context3d->makeContextCurrent()) {
+ // TODO(skaslev): Implement this path for software compositing.
+ return;
+ }
+
+ ReturnedResourceArray to_return;
+
+ bool need_sync_point = false;
+ for (size_t i = 0; i < unused.size(); ++i) {
+ ResourceId local_id = unused[i];
+
+ ResourceMap::iterator it = resources_.find(local_id);
+ CHECK(it != resources_.end());
+ Resource& resource = it->second;
+
+ DCHECK(!resource.locked_for_write);
+ DCHECK(!resource.lock_for_read_count);
+ DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
+ DCHECK(child_info->parent_to_child_map.count(local_id));
+
+ ResourceId child_id = child_info->parent_to_child_map[local_id];
+ DCHECK(child_info->child_to_parent_map.count(child_id));
+
+ bool is_lost = resource.lost || lost_output_surface_;
+ if (resource.exported_count > 0) {
+ if (style != ForShutdown) {
+ // Defer this until we receive the resource back from the parent.
+ resource.marked_for_deletion = true;
+ continue;
+ }
+
+ // We still have an exported_count, so we'll have to lose it.
+ is_lost = true;
+ }
+
+ if (resource.filter != resource.original_filter) {
+ DCHECK(resource.target);
+ DCHECK(resource.gl_id);
+
+ GLC(context3d, context3d->bindTexture(resource.target, resource.gl_id));
+ GLC(context3d,
+ context3d->texParameteri(resource.target,
+ GL_TEXTURE_MIN_FILTER,
+ resource.original_filter));
+ GLC(context3d,
+ context3d->texParameteri(resource.target,
+ GL_TEXTURE_MAG_FILTER,
+ resource.original_filter));
+ }
+
+ ReturnedResource returned;
+ returned.id = child_id;
+ returned.sync_point = resource.mailbox.sync_point();
+ if (!returned.sync_point)
+ need_sync_point = true;
+ returned.count = resource.imported_count;
+ returned.lost = is_lost;
+ to_return.push_back(returned);
+
+ child_info->parent_to_child_map.erase(local_id);
+ child_info->child_to_parent_map.erase(child_id);
+ resource.imported_count = 0;
+ DeleteResourceInternal(it, style);
+ }
+ if (need_sync_point) {
+ unsigned int sync_point = context3d->insertSyncPoint();
+ for (size_t i = 0; i < to_return.size(); ++i) {
+ if (!to_return[i].sync_point)
+ to_return[i].sync_point = sync_point;
+ }
+ }
+
+ if (!to_return.empty())
+ child_info->return_callback.Run(to_return);
}
void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
if (resource->type == GLTexture) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
if (!resource->gl_pixel_buffer_id)
resource->gl_pixel_buffer_id = context3d->createBuffer();
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);
@@ -994,12 +1231,9 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
}
void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
// The pixel buffer can be released while there is a pending "set pixels"
@@ -1017,7 +1251,7 @@ void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
if (resource->type == GLTexture) {
if (!resource->gl_pixel_buffer_id)
return;
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
context3d->bindBuffer(
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
@@ -1039,16 +1273,13 @@ void ResourceProvider::ReleasePixelBuffer(ResourceId id) {
}
uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
if (resource->type == GLTexture) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
DCHECK(resource->gl_pixel_buffer_id);
context3d->bindBuffer(
@@ -1070,16 +1301,13 @@ uint8_t* ResourceProvider::MapPixelBuffer(ResourceId id) {
}
void ResourceProvider::UnmapPixelBuffer(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
DCHECK(!resource->image_id);
if (resource->type == GLTexture) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
DCHECK(resource->gl_pixel_buffer_id);
context3d->bindBuffer(
@@ -1095,16 +1323,14 @@ void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id,
GLenum unit,
GLenum filter) {
DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
ResourceMap::iterator it = resources_.find(resource_id);
DCHECK(it != resources_.end());
Resource* resource = &it->second;
DCHECK(resource->lock_for_read_count);
DCHECK(!resource->locked_for_write || resource->set_pixels_completion_forced);
- DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(context3d));
- if (unit != GL_TEXTURE0)
- GLC(context3d, context3d->activeTexture(unit));
+ ScopedSetActiveTexture scoped_active_tex(context3d, unit);
GLC(context3d, context3d->bindTexture(target, resource->gl_id));
if (filter != resource->filter) {
GLC(context3d, context3d->texParameteri(target,
@@ -1114,14 +1340,14 @@ void ResourceProvider::BindForSampling(ResourceProvider::ResourceId resource_id,
GL_TEXTURE_MAG_FILTER,
filter));
resource->filter = filter;
+ if (resource->target == 0)
+ resource->target = target;
+ else
+ DCHECK_EQ(resource->target, target);
}
if (resource->image_id)
context3d->bindTexImage2DCHROMIUM(target, resource->image_id);
-
- // Active unit being GL_TEXTURE0 is effectively the ground state.
- if (unit != GL_TEXTURE0)
- GLC(context3d, context3d->activeTexture(GL_TEXTURE0));
}
void ResourceProvider::UnbindForSampling(
@@ -1134,21 +1360,13 @@ void ResourceProvider::UnbindForSampling(
if (!resource->image_id)
return;
- WebGraphicsContext3D* context3d = output_surface_->context3d();
- DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(context3d));
- if (unit != GL_TEXTURE0)
- GLC(context3d, context3d->activeTexture(unit));
+ WebGraphicsContext3D* context3d = Context3d();
+ ScopedSetActiveTexture scoped_active_tex(context3d, unit);
context3d->releaseTexImage2DCHROMIUM(target, resource->image_id);
- // Active unit being GL_TEXTURE0 is effectively the ground state.
- if (unit != GL_TEXTURE0)
- GLC(context3d, context3d->activeTexture(GL_TEXTURE0));
}
void ResourceProvider::BeginSetPixels(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(!resource->pending_set_pixels);
LazyCreate(resource);
@@ -1161,7 +1379,7 @@ void ResourceProvider::BeginSetPixels(ResourceId id) {
LockForWrite(id);
if (resource->gl_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
DCHECK(resource->gl_pixel_buffer_id);
context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id);
@@ -1171,37 +1389,39 @@ void ResourceProvider::BeginSetPixels(ResourceId id) {
if (!resource->gl_upload_query_id)
resource->gl_upload_query_id = context3d->createQueryEXT();
context3d->beginQueryEXT(
- GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM,
+ 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_TRANSFERS_COMPLETED_CHROMIUM);
+ context3d->endQueryEXT(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM);
context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
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;
@@ -1213,16 +1433,13 @@ void ResourceProvider::BeginSetPixels(ResourceId id) {
}
void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(resource->locked_for_write);
DCHECK(resource->pending_set_pixels);
DCHECK(!resource->set_pixels_completion_forced);
if (resource->gl_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
GLC(context3d, context3d->waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D));
GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, 0));
@@ -1232,15 +1449,12 @@ void ResourceProvider::ForceSetPixelsToComplete(ResourceId id) {
}
bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
DCHECK(resource->locked_for_write);
DCHECK(resource->pending_set_pixels);
if (resource->gl_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
DCHECK(resource->gl_upload_query_id);
unsigned complete = 1;
@@ -1259,10 +1473,12 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
}
void ResourceProvider::CreateForTesting(ResourceId id) {
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
- LazyCreate(resource);
+ LazyCreate(GetResource(id));
+}
+
+GLint ResourceProvider::WrapModeForTesting(ResourceId id) {
+ Resource* resource = GetResource(id);
+ return resource->wrap_mode;
}
void ResourceProvider::LazyCreate(Resource* resource) {
@@ -1273,10 +1489,20 @@ void ResourceProvider::LazyCreate(Resource* resource) {
if (resource->texture_pool == 0)
return;
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
+
// Create and set texture properties. Allocation is delayed until needed.
- resource->gl_id = CreateTextureId(context3d);
+ GLC(context3d, resource->gl_id = context3d->createTexture());
+ GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, resource->gl_id));
+ GLC(context3d, context3d->texParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(context3d, context3d->texParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GLC(context3d, context3d->texParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, resource->wrap_mode));
+ GLC(context3d, context3d->texParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, resource->wrap_mode));
GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D,
GL_TEXTURE_POOL_CHROMIUM,
resource->texture_pool));
@@ -1288,10 +1514,7 @@ void ResourceProvider::LazyCreate(Resource* resource) {
}
void ResourceProvider::AllocateForTesting(ResourceId id) {
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
- LazyAllocate(resource);
+ LazyAllocate(GetResource(id));
}
void ResourceProvider::LazyAllocate(Resource* resource) {
@@ -1302,11 +1525,11 @@ void ResourceProvider::LazyAllocate(Resource* resource) {
if (resource->allocated || !resource->gl_id)
return;
resource->allocated = true;
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ 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,
@@ -1316,33 +1539,26 @@ 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));
}
}
void ResourceProvider::EnableReadLockFences(ResourceProvider::ResourceId id,
bool enable) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
+ Resource* resource = GetResource(id);
resource->enable_read_lock_fences = enable;
}
void ResourceProvider::AcquireImage(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
-
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
if (resource->type != GLTexture)
return;
@@ -1351,26 +1567,23 @@ void ResourceProvider::AcquireImage(ResourceId id) {
return;
resource->allocated = true;
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
+ DCHECK_EQ(RGBA_8888, resource->format);
resource->image_id = context3d->createImageCHROMIUM(
resource->size.width(), resource->size.height(), GL_RGBA8_OES);
DCHECK(resource->image_id);
}
void ResourceProvider::ReleaseImage(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
-
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
if (!resource->image_id)
return;
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
context3d->destroyImageCHROMIUM(resource->image_id);
resource->image_id = 0;
@@ -1378,17 +1591,13 @@ void ResourceProvider::ReleaseImage(ResourceId id) {
}
uint8_t* ResourceProvider::MapImage(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
-
+ Resource* resource = GetResource(id);
DCHECK(ReadLockFenceHasPassed(resource));
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
if (resource->image_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
return static_cast<uint8_t*>(
context3d->mapImageCHROMIUM(resource->image_id, GL_READ_WRITE));
@@ -1401,34 +1610,26 @@ uint8_t* ResourceProvider::MapImage(ResourceId id) {
}
void ResourceProvider::UnmapImage(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
-
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
if (resource->image_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
context3d->unmapImageCHROMIUM(resource->image_id);
}
}
int ResourceProvider::GetImageStride(ResourceId id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- ResourceMap::iterator it = resources_.find(id);
- CHECK(it != resources_.end());
- Resource* resource = &it->second;
-
+ Resource* resource = GetResource(id);
DCHECK(!resource->external);
- DCHECK(!resource->exported);
+ DCHECK_EQ(resource->exported_count, 0);
int stride = 0;
if (resource->image_id) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
+ WebGraphicsContext3D* context3d = Context3d();
DCHECK(context3d);
context3d->getImageParameterivCHROMIUM(
resource->image_id, GL_IMAGE_ROWBYTES_CHROMIUM, &stride);
@@ -1443,4 +1644,59 @@ GLint ResourceProvider::GetActiveTextureUnit(WebGraphicsContext3D* context) {
return active_unit;
}
+WebKit::WebGraphicsContext3D* ResourceProvider::Context3d() const {
+ ContextProvider* context_provider = output_surface_->context_provider();
+ return context_provider ? context_provider->Context3d() : NULL;
+}
+
+size_t ResourceProvider::BytesPerPixel(ResourceFormat format) {
+ switch (format) {
+ case RGBA_8888:
+ case BGRA_8888:
+ return 4;
+ case RGBA_4444:
+ case RGB_565:
+ return 2;
+ case LUMINANCE_8:
+ return 1;
+ }
+ NOTREACHED();
+ return 4;
+}
+
+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;
+ case RGB_565:
+ return GL_UNSIGNED_SHORT_5_6_5;
+ }
+ 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;
+ case RGB_565:
+ return GL_RGB;
+ }
+ NOTREACHED();
+ return GL_RGBA;
+}
+
+GLenum ResourceProvider::GetGLInternalFormat(ResourceFormat format) {
+ return GetGLDataFormat(format);
+}
+
} // namespace cc