summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc')
-rw-r--r--cc/heads_up_display_layer_impl.cc8
-rw-r--r--cc/layer_tree_host_impl_unittest.cc15
-rw-r--r--cc/resource_provider.cc86
-rw-r--r--cc/resource_provider.h6
-rw-r--r--cc/resource_provider_unittest.cc74
5 files changed, 169 insertions, 20 deletions
diff --git a/cc/heads_up_display_layer_impl.cc b/cc/heads_up_display_layer_impl.cc
index 73f99d0..dd8f413 100644
--- a/cc/heads_up_display_layer_impl.cc
+++ b/cc/heads_up_display_layer_impl.cc
@@ -76,8 +76,14 @@ void HeadsUpDisplayLayerImpl::willDraw(ResourceProvider* resourceProvider)
if (m_hudTexture->size() != bounds())
m_hudTexture->Free();
- if (!m_hudTexture->id())
+ if (!m_hudTexture->id()) {
m_hudTexture->Allocate(bounds(), GL_RGBA, ResourceProvider::TextureUsageAny);
+ // TODO(epenner): This texture was being used before setPixels was called,
+ // which is now not allowed (it's an uninitialized read). This should be fixed
+ // and this allocateForTesting() removed.
+ // http://crbug.com/166784
+ resourceProvider->allocateForTesting(m_hudTexture->id());
+ }
}
void HeadsUpDisplayLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuadsData)
diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc
index 992ae71..876847b 100644
--- a/cc/layer_tree_host_impl_unittest.cc
+++ b/cc/layer_tree_host_impl_unittest.cc
@@ -1055,6 +1055,7 @@ private:
setSkipsDraw(skipsDraw);
if (!tileMissing) {
ResourceProvider::ResourceId resource = resourceProvider->createResource(gfx::Size(), GL_RGBA, ResourceProvider::TextureUsageAny);
+ resourceProvider->allocateForTesting(resource);
pushTileProperties(0, 0, resource, gfx::Rect(), false);
}
if (animating)
@@ -1680,6 +1681,7 @@ private:
, m_quadVisibleRect(5, 5, 5, 5)
, m_resourceId(resourceProvider->createResource(gfx::Size(1, 1), GL_RGBA, ResourceProvider::TextureUsageAny))
{
+ resourceProvider->allocateForTesting(m_resourceId);
setAnchorPoint(gfx::PointF(0, 0));
setBounds(gfx::Size(10, 10));
setContentBounds(gfx::Size(10, 10));
@@ -2754,9 +2756,15 @@ public:
ResourceProvider::TextureUsageHint hint = ResourceProvider::TextureUsageAny;
setScrollbarGeometry(ScrollbarGeometryFixedThumb::create(FakeWebScrollbarThemeGeometryNonEmpty::create()));
- setBackTrackResourceId(provider->createResource(size, format, hint));
- setForeTrackResourceId(provider->createResource(size, format, hint));
- setThumbResourceId(provider->createResource(size, format, hint));
+ ResourceProvider::ResourceId backId = provider->createResource(size, format, hint);
+ ResourceProvider::ResourceId foreId = provider->createResource(size, format, hint);
+ ResourceProvider::ResourceId thumbId = provider->createResource(size, format, hint);
+ provider->allocateForTesting(backId);
+ provider->allocateForTesting(foreId);
+ provider->allocateForTesting(thumbId);
+ setBackTrackResourceId(backId);
+ setForeTrackResourceId(foreId);
+ setThumbResourceId(thumbId);
}
protected:
@@ -2769,6 +2777,7 @@ protected:
static inline scoped_ptr<RenderPass> createRenderPassWithResource(ResourceProvider* provider)
{
ResourceProvider::ResourceId resourceId = provider->createResource(gfx::Size(1, 1), GL_RGBA, ResourceProvider::TextureUsageAny);
+ provider->allocateForTesting(resourceId);
scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
pass->SetNew(RenderPass::Id(1, 1), gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1), gfx::Transform());
diff --git a/cc/resource_provider.cc b/cc/resource_provider.cc
index 2cbafae..8b7081c 100644
--- a/cc/resource_provider.cc
+++ b/cc/resource_provider.cc
@@ -59,6 +59,7 @@ ResourceProvider::Resource::Resource()
, exported(false)
, markedForDeletion(false)
, pendingSetPixels(false)
+ , allocated(false)
, size()
, format(0)
, filter(0)
@@ -78,6 +79,7 @@ ResourceProvider::Resource::Resource(unsigned textureId, const gfx::Size& size,
, exported(false)
, markedForDeletion(false)
, pendingSetPixels(false)
+ , allocated(false)
, size(size)
, format(format)
, filter(filter)
@@ -97,6 +99,7 @@ ResourceProvider::Resource::Resource(uint8_t* pixels, const gfx::Size& size, GLe
, exported(false)
, markedForDeletion(false)
, pendingSetPixels(false)
+ , allocated(false)
, size(size)
, format(format)
, filter(filter)
@@ -183,22 +186,19 @@ ResourceProvider::ResourceId ResourceProvider::createGLTexture(const gfx::Size&
DCHECK(context3d);
GLC(context3d, textureId = context3d->createTexture());
GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, textureId));
+
+ // Set texture properties. Allocation is delayed until needed.
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));
GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_POOL_CHROMIUM, texturePool));
-
if (m_useTextureUsageHint && hint == TextureUsageFramebuffer)
GLC(context3d, context3d->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
- if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) {
- GLenum storageFormat = textureToStorageFormat(format);
- GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height()));
- } else
- GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, 0));
ResourceId id = m_nextId++;
Resource resource(textureId, size, format, GL_LINEAR);
+ resource.allocated = false;
m_resources[id] = resource;
return id;
}
@@ -211,6 +211,7 @@ ResourceProvider::ResourceId ResourceProvider::createBitmap(const gfx::Size& siz
ResourceId id = m_nextId++;
Resource resource(pixels, size, GL_RGBA, GL_LINEAR);
+ resource.allocated = true;
m_resources[id] = resource;
return id;
}
@@ -230,6 +231,7 @@ ResourceProvider::ResourceId ResourceProvider::createResourceFromExternalTexture
ResourceId id = m_nextId++;
Resource resource(textureId, gfx::Size(), 0, GL_LINEAR);
resource.external = true;
+ resource.allocated = true;
m_resources[id] = resource;
return id;
}
@@ -240,9 +242,9 @@ void ResourceProvider::deleteResource(ResourceId id)
ResourceMap::iterator it = m_resources.find(id);
CHECK(it != m_resources.end());
Resource* resource = &it->second;
- DCHECK(!resource->lockedForWrite);
DCHECK(!resource->lockForReadCount);
DCHECK(!resource->markedForDeletion);
+ DCHECK(resource->pendingSetPixels || !resource->lockedForWrite);
if (resource->exported) {
resource->markedForDeletion = true;
@@ -295,8 +297,10 @@ void ResourceProvider::setPixels(ResourceId id, const uint8_t* image, const gfx:
DCHECK(!resource->lockForReadCount);
DCHECK(!resource->external);
DCHECK(!resource->exported);
+ lazyAllocate(resource);
if (resource->glId) {
+ DCHECK(!resource->pendingSetPixels);
WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
DCHECK(context3d);
DCHECK(m_textureUploader.get());
@@ -310,6 +314,7 @@ void ResourceProvider::setPixels(ResourceId id, const uint8_t* image, const gfx:
}
if (resource->pixels) {
+ DCHECK(resource->allocated);
DCHECK(resource->format == GL_RGBA);
SkBitmap srcFull;
srcFull.setConfig(SkBitmap::kARGB_8888_Config, imageRect.width(), imageRect.height());
@@ -384,6 +389,8 @@ const ResourceProvider::Resource* ResourceProvider::lockForRead(ResourceId id)
Resource* resource = &it->second;
DCHECK(!resource->lockedForWrite);
DCHECK(!resource->exported);
+ DCHECK(resource->allocated); // Uninitialized! Call setPixels or lockForWrite first.
+
resource->lockForReadCount++;
return resource;
}
@@ -409,6 +416,8 @@ const ResourceProvider::Resource* ResourceProvider::lockForWrite(ResourceId id)
DCHECK(!resource->lockForReadCount);
DCHECK(!resource->exported);
DCHECK(!resource->external);
+ lazyAllocate(resource);
+
resource->lockedForWrite = true;
return resource;
}
@@ -645,6 +654,8 @@ void ResourceProvider::receiveFromChild(int child, const TransferableResourceLis
ResourceId id = m_nextId++;
Resource resource(textureId, it->size, it->format, it->filter);
resource.mailbox.setName(it->mailbox.name);
+ // Don't allocate a texture for a child.
+ resource.allocated = true;
m_resources[id] = resource;
childInfo.parentToChildMap[id] = it->id;
childInfo.childToParentMap[it->id] = id;
@@ -685,6 +696,7 @@ bool ResourceProvider::transferResource(WebGraphicsContext3D* context, ResourceI
DCHECK(!source->lockedForWrite);
DCHECK(!source->lockForReadCount);
DCHECK(!source->external);
+ DCHECK(source->allocated);
if (source->exported)
return false;
resource->id = id;
@@ -832,6 +844,7 @@ void ResourceProvider::setPixelsFromBuffer(ResourceId id)
DCHECK(!resource->lockForReadCount);
DCHECK(!resource->external);
DCHECK(!resource->exported);
+ lazyAllocate(resource);
if (resource->glId) {
WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
@@ -893,7 +906,10 @@ void ResourceProvider::beginSetPixels(ResourceId id)
CHECK(it != m_resources.end());
Resource* resource = &it->second;
DCHECK(!resource->pendingSetPixels);
+ DCHECK(resource->glId || resource->allocated);
+ bool allocate = !resource->allocated;
+ resource->allocated = true;
lockForWrite(id);
if (resource->glId) {
@@ -909,15 +925,27 @@ void ResourceProvider::beginSetPixels(ResourceId id)
context3d->beginQueryEXT(
GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM,
resource->glUploadQueryId);
- context3d->asyncTexSubImage2DCHROMIUM(GL_TEXTURE_2D,
- 0, /* level */
- 0, /* x */
- 0, /* y */
- resource->size.width(),
- resource->size.height(),
- resource->format,
- GL_UNSIGNED_BYTE,
- NULL);
+ 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);
+ } 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->endQueryEXT(GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM);
context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
}
@@ -955,4 +983,30 @@ bool ResourceProvider::didSetPixelsComplete(ResourceId id) {
return true;
}
+void ResourceProvider::allocateForTesting(ResourceId id) {
+ ResourceMap::iterator it = m_resources.find(id);
+ CHECK(it != m_resources.end());
+ Resource* resource = &it->second;
+ lazyAllocate(resource);
+}
+
+void ResourceProvider::lazyAllocate(Resource* resource) {
+ DCHECK(resource);
+ DCHECK(resource->glId || resource->allocated);
+
+ if (resource->allocated || !resource->glId)
+ return;
+
+ resource->allocated = true;
+ WebGraphicsContext3D* context3d = m_outputSurface->Context3D();
+ gfx::Size& size = resource->size;
+ GLenum format = resource->format;
+ if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) {
+ GLenum storageFormat = textureToStorageFormat(format);
+ GLC(context3d, context3d->texStorage2DEXT(GL_TEXTURE_2D, 1, storageFormat, size.width(), size.height()));
+ } else
+ GLC(context3d, context3d->texImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, 0));
+}
+
+
} // namespace cc
diff --git a/cc/resource_provider.h b/cc/resource_provider.h
index d90d224..9b5b54b 100644
--- a/cc/resource_provider.h
+++ b/cc/resource_provider.h
@@ -230,6 +230,10 @@ public:
void beginSetPixels(ResourceId id);
bool didSetPixelsComplete(ResourceId id);
+ // For tests only! This prevents detecting uninitialized reads.
+ // Use setPixels or lockForWrite to allocate implicitly.
+ void allocateForTesting(ResourceId id);
+
private:
struct Resource {
Resource();
@@ -250,6 +254,7 @@ private:
bool exported;
bool markedForDeletion;
bool pendingSetPixels;
+ bool allocated;
gfx::Size size;
GLenum format;
// TODO(skyostil): Use a separate sampler object for filter state.
@@ -277,6 +282,7 @@ private:
bool transferResource(WebKit::WebGraphicsContext3D*, ResourceId, TransferableResource*);
void deleteResourceInternal(ResourceMap::iterator it);
+ void lazyAllocate(Resource*);
OutputSurface* m_outputSurface;
ResourceId m_nextId;
diff --git a/cc/resource_provider_unittest.cc b/cc/resource_provider_unittest.cc
index 0a737e5..f57061a 100644
--- a/cc/resource_provider_unittest.cc
+++ b/cc/resource_provider_unittest.cc
@@ -20,6 +20,9 @@
using namespace WebKit;
using testing::Mock;
+using testing::StrictMock;
+using testing::NiceMock;
+using testing::_;
namespace cc {
namespace {
@@ -587,6 +590,7 @@ TEST_P(ResourceProviderTest, ScopedSampler)
EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_POOL_CHROMIUM, GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
ResourceProvider::ResourceId id = resourceProvider->createResource(size, format, ResourceProvider::TextureUsageAny);
+ resourceProvider->allocateForTesting(id);
// Creating a sampler with the default filter should not change any texture
// parameters.
@@ -640,6 +644,76 @@ TEST_P(ResourceProviderTest, ManagedResource)
Mock::VerifyAndClearExpectations(context);
}
+class AllocationTrackingContext3D : public FakeWebGraphicsContext3D {
+public:
+ MOCK_METHOD9(texImage2D, void(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat,
+ WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format,
+ WGC3Denum type, const void* pixels));
+ MOCK_METHOD9(texSubImage2D, void(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset,
+ WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format,
+ WGC3Denum type, const void* pixels));
+ MOCK_METHOD9(asyncTexImage2DCHROMIUM, void(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat,
+ WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format,
+ WGC3Denum type, const void* pixels));
+ MOCK_METHOD9(asyncTexSubImage2DCHROMIUM, void(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset,
+ WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format,
+ WGC3Denum type, const void* pixels));
+};
+
+TEST_P(ResourceProviderTest, TextureAllocation)
+{
+ // Only for GL textures.
+ if (GetParam() != ResourceProvider::GLTexture)
+ return;
+ scoped_ptr<WebKit::WebGraphicsContext3D> mock_context(
+ static_cast<WebKit::WebGraphicsContext3D*>(new NiceMock<AllocationTrackingContext3D>));
+ scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(mock_context.Pass()));
+
+ gfx::Size size(2, 2);
+ gfx::Vector2d offset(0, 0);
+ gfx::Rect rect(0, 0, 2, 2);
+ WGC3Denum format = GL_RGBA;
+ ResourceProvider::ResourceId id = 0;
+ uint8_t pixels[16] = {0};
+
+ AllocationTrackingContext3D* context = static_cast<AllocationTrackingContext3D*>(outputSurface->Context3D());
+ scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
+
+ // Lazy allocation. Don't allocate when creating the resource.
+ EXPECT_CALL(*context, texImage2D(_,_,_,_,_,_,_,_,_)).Times(0);
+ EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_,_,_,_,_,_,_,_,_)).Times(0);
+ id = resourceProvider->createResource(size, format, ResourceProvider::TextureUsageAny);
+ resourceProvider->deleteResource(id);
+ Mock::VerifyAndClearExpectations(context);
+
+ // Do allocate when we set the pixels.
+ EXPECT_CALL(*context, texImage2D(_,_,_,2,2,_,_,_,_)).Times(1);
+ EXPECT_CALL(*context, texSubImage2D(_,_,_,_,2,2,_,_,_)).Times(1);
+ id = resourceProvider->createResource(size, format, ResourceProvider::TextureUsageAny);
+ resourceProvider->setPixels(id, pixels, rect, rect, offset);
+ resourceProvider->deleteResource(id);
+ Mock::VerifyAndClearExpectations(context);
+
+ // Same for setPixelsFromBuffer
+ EXPECT_CALL(*context, texImage2D(_,_,_,2,2,_,_,_,_)).Times(1);
+ EXPECT_CALL(*context, texSubImage2D(_,_,_,_,2,2,_,_,_)).Times(1);
+ id = resourceProvider->createResource(size, format, ResourceProvider::TextureUsageAny);
+ resourceProvider->acquirePixelBuffer(id);
+ resourceProvider->setPixelsFromBuffer(id);
+ resourceProvider->releasePixelBuffer(id);
+ resourceProvider->deleteResource(id);
+ Mock::VerifyAndClearExpectations(context);
+
+ // Same for async version.
+ EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_,_,_,2,2,_,_,_,_)).Times(1);
+ id = resourceProvider->createResource(size, format, ResourceProvider::TextureUsageAny);
+ resourceProvider->acquirePixelBuffer(id);
+ resourceProvider->beginSetPixels(id);
+ resourceProvider->releasePixelBuffer(id);
+ resourceProvider->deleteResource(id);
+ Mock::VerifyAndClearExpectations(context);
+}
+
INSTANTIATE_TEST_CASE_P(ResourceProviderTests,
ResourceProviderTest,
::testing::Values(ResourceProvider::GLTexture,