Diff
Modified: trunk/Source/WebCore/ChangeLog (98566 => 98567)
--- trunk/Source/WebCore/ChangeLog 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebCore/ChangeLog 2011-10-27 14:23:49 UTC (rev 98567)
@@ -1,3 +1,24 @@
+2011-10-27 Antoine Labour <[email protected]>
+
+ Disable blending when drawing opaque layers
+ https://bugs.webkit.org/show_bug.cgi?id=70085
+
+ Reviewed by James Robinson.
+
+ Covered by compositing/ tests, as well as a new unit test:
+ CCLayerTreeHostImplTest.blendingOffWhenDrawingOpaqueLayers
+
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::LayerChromium):
+ (WebCore::LayerChromium::pushPropertiesTo):
+ * platform/graphics/chromium/LayerRendererChromium.cpp:
+ (WebCore::LayerRendererChromium::drawLayer):
+ * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+ (WebCore::CCLayerImpl::CCLayerImpl):
+ * platform/graphics/chromium/cc/CCLayerImpl.h:
+ (WebCore::CCLayerImpl::setOpaque):
+ (WebCore::CCLayerImpl::opaque):
+
2011-10-27 Joshua Bell <[email protected]>
IndexedDB: Passing empty array to IDBDatabase.transaction should raise exception
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp (98566 => 98567)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp 2011-10-27 14:23:49 UTC (rev 98567)
@@ -288,6 +288,7 @@
layer->setMasksToBounds(m_masksToBounds);
layer->setMaxScrollPosition(m_maxScrollPosition);
layer->setName(m_name);
+ layer->setOpaque(m_opaque);
layer->setOpacity(m_opacity);
layer->setPosition(m_position);
layer->setPreserves3D(preserves3D());
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp (98566 => 98567)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2011-10-27 14:23:49 UTC (rev 98567)
@@ -587,8 +587,15 @@
else
GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ bool opaque = layer->opaque() && layer->drawOpacity() == 1;
+ if (opaque)
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
+
layer->draw(this);
+ if (opaque)
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
+
// Draw the debug border if there is one.
layer->drawDebugBorder(this);
}
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp (98566 => 98567)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp 2011-10-27 14:23:49 UTC (rev 98567)
@@ -44,6 +44,7 @@
, m_anchorPointZ(0)
, m_doubleSided(true)
, m_masksToBounds(false)
+ , m_opaque(false)
, m_opacity(1.0)
, m_preserves3D(false)
, m_usesLayerScissor(false)
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h (98566 => 98567)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h 2011-10-27 14:23:49 UTC (rev 98567)
@@ -92,6 +92,9 @@
void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; }
bool masksToBounds() const { return m_masksToBounds; }
+ void setOpaque(bool opaque) { m_opaque = opaque; }
+ bool opaque() const { return m_opaque; }
+
void setOpacity(float opacity) { m_opacity = opacity; }
float opacity() const { return m_opacity; }
@@ -209,6 +212,7 @@
IntRect m_visibleLayerRect;
bool m_masksToBounds;
+ bool m_opaque;
float m_opacity;
FloatPoint m_position;
bool m_preserves3D;
Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp (98566 => 98567)
--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp 2011-10-27 14:23:49 UTC (rev 98567)
@@ -26,11 +26,15 @@
#include "cc/CCLayerTreeHostImpl.h"
+#include "GraphicsContext3DPrivate.h"
+#include "LayerRendererChromium.h"
+#include "MockWebGraphicsContext3D.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCSingleThreadProxy.h"
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKit;
namespace {
@@ -151,4 +155,139 @@
ASSERT(m_didRequestCommit);
}
+class BlendStateTrackerContext: public MockWebGraphicsContext3D {
+public:
+ BlendStateTrackerContext() : m_blend(false) { }
+
+ virtual bool initialize(Attributes, WebView*, bool renderDirectlyToWebView) { return true; }
+
+ virtual void enable(WGC3Denum cap)
+ {
+ if (cap == GraphicsContext3D::BLEND)
+ m_blend = true;
+ }
+
+ virtual void disable(WGC3Denum cap)
+ {
+ if (cap == GraphicsContext3D::BLEND)
+ m_blend = false;
+ }
+
+ bool blend() const { return m_blend; }
+
+private:
+ bool m_blend;
+};
+
+class BlendStateCheckLayer : public CCLayerImpl {
+public:
+ static PassRefPtr<BlendStateCheckLayer> create(int id) { return adoptRef(new BlendStateCheckLayer(id)); }
+
+ virtual void draw(LayerRendererChromium* renderer)
+ {
+ m_drawn = true;
+ BlendStateTrackerContext* context = static_cast<BlendStateTrackerContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(renderer->context()));
+ EXPECT_EQ(m_blend, context->blend());
+ EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
+ }
+
+ void setExpectation(bool blend, bool hasRenderSurface)
+ {
+ m_blend = blend;
+ m_hasRenderSurface = hasRenderSurface;
+ m_drawn = false;
+ }
+
+ bool drawn() const { return m_drawn; }
+
+private:
+ explicit BlendStateCheckLayer(int id)
+ : CCLayerImpl(id)
+ , m_blend(false)
+ , m_hasRenderSurface(false)
+ , m_drawn(false)
+ {
+ setAnchorPoint(FloatPoint(0, 0));
+ setBounds(IntSize(10, 10));
+ setDrawsContent(true);
+ }
+
+ bool m_blend;
+ bool m_hasRenderSurface;
+ bool m_drawn;
+};
+
+TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
+{
+ GraphicsContext3D::Attributes attrs;
+ RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new BlendStateTrackerContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+ m_hostImpl->initializeLayerRenderer(context);
+ m_hostImpl->setViewport(IntSize(10, 10));
+
+ RefPtr<CCLayerImpl> root = CCLayerImpl::create(0);
+ root->setAnchorPoint(FloatPoint(0, 0));
+ root->setBounds(IntSize(10, 10));
+ root->setDrawsContent(false);
+ m_hostImpl->setRootLayer(root);
+
+ RefPtr<BlendStateCheckLayer> layer1 = BlendStateCheckLayer::create(1);
+ root->addChild(layer1);
+
+ // Opaque layer, drawn without blending.
+ layer1->setOpaque(true);
+ layer1->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->drawn());
+
+ // Layer with translucent content, drawn with blending.
+ layer1->setOpaque(false);
+ layer1->setExpectation(true, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->drawn());
+
+ // Layer with translucent opacity, drawn with blending.
+ layer1->setOpaque(true);
+ layer1->setOpacity(0.5);
+ layer1->setExpectation(true, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->drawn());
+
+ RefPtr<BlendStateCheckLayer> layer2 = BlendStateCheckLayer::create(2);
+ layer1->addChild(layer2);
+
+ // 2 opaque layers, drawn without blending.
+ layer1->setOpaque(true);
+ layer1->setOpacity(1);
+ layer1->setExpectation(false, false);
+ layer2->setOpaque(true);
+ layer2->setOpacity(1);
+ layer2->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->drawn());
+ EXPECT_TRUE(layer2->drawn());
+
+ // Parent layer with translucent content, drawn with blending.
+ // Child layer with opaque content, drawn without blending.
+ layer1->setOpaque(false);
+ layer1->setExpectation(true, false);
+ layer2->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->drawn());
+ EXPECT_TRUE(layer2->drawn());
+
+ // Parent layer with translucent opacity and opaque content. Since it has a
+ // drawing child, it's drawn to a render surface which carries the opacity,
+ // so it's itself drawn without blending.
+ // Child layer with opaque content, drawn without blending (parent surface
+ // carries the inherited opacity).
+ layer1->setOpaque(true);
+ layer1->setOpacity(0.5);
+ layer1->setExpectation(false, true);
+ layer2->setExpectation(false, false);
+ m_hostImpl->drawLayers();
+ EXPECT_TRUE(layer1->drawn());
+ EXPECT_TRUE(layer2->drawn());
+}
+
+
} // namespace
Modified: trunk/Source/WebKit/chromium/tests/MockWebGraphicsContext3D.h (98566 => 98567)
--- trunk/Source/WebKit/chromium/tests/MockWebGraphicsContext3D.h 2011-10-27 14:03:32 UTC (rev 98566)
+++ trunk/Source/WebKit/chromium/tests/MockWebGraphicsContext3D.h 2011-10-27 14:23:49 UTC (rev 98567)
@@ -26,6 +26,7 @@
#ifndef MockWebGraphicsContext3D_h
#define MockWebGraphicsContext3D_h
+#include "GraphicsContext3D.h"
#include "WebGraphicsContext3D.h"
namespace WebKit {
@@ -84,7 +85,11 @@
virtual void bufferData(WGC3Denum target, WGC3Dsizeiptr size, const void* data, WGC3Denum usage) { }
virtual void bufferSubData(WGC3Denum target, WGC3Dintptr offset, WGC3Dsizeiptr size, const void* data) { }
- virtual WGC3Denum checkFramebufferStatus(WGC3Denum target) { return 0; }
+ virtual WGC3Denum checkFramebufferStatus(WGC3Denum target)
+ {
+ return WebCore::GraphicsContext3D::FRAMEBUFFER_COMPLETE;
+ }
+
virtual void clear(WGC3Dbitfield mask) { }
virtual void clearColor(WGC3Dclampf red, WGC3Dclampf green, WGC3Dclampf blue, WGC3Dclampf alpha) { }
virtual void clearDepth(WGC3Dclampf depth) { }
@@ -123,11 +128,28 @@
virtual WGC3Denum getError() { return 0; }
virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { }
virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, WGC3Denum attachment, WGC3Denum pname, WGC3Dint* value) { }
- virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value) { }
- virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) { }
+
+ virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value)
+ {
+ if (pname == WebCore::GraphicsContext3D::MAX_TEXTURE_SIZE)
+ *value = 1024;
+ }
+
+ virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
+ {
+ if (pname == WebCore::GraphicsContext3D::LINK_STATUS)
+ *value = 1;
+ }
+
virtual WebString getProgramInfoLog(WebGLId program) { return WebString(); }
virtual void getRenderbufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { }
- virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) { }
+
+ virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
+ {
+ if (pname == WebCore::GraphicsContext3D::COMPILE_STATUS)
+ *value = 1;
+ }
+
virtual WebString getShaderInfoLog(WebGLId shader) { return WebString(); }
virtual WebString getShaderSource(WebGLId shader) { return WebString(); }
@@ -212,12 +234,12 @@
virtual void viewport(WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { }
- virtual WebGLId createBuffer() { return 0; }
- virtual WebGLId createFramebuffer() { return 0; }
- virtual WebGLId createProgram() { return 0; }
- virtual WebGLId createRenderbuffer() { return 0; }
- virtual WebGLId createShader(WGC3Denum) { return 0; }
- virtual WebGLId createTexture() { return 0; }
+ virtual WebGLId createBuffer() { return 1; }
+ virtual WebGLId createFramebuffer() { return 1; }
+ virtual WebGLId createProgram() { return 1; }
+ virtual WebGLId createRenderbuffer() { return 1; }
+ virtual WebGLId createShader(WGC3Denum) { return 1; }
+ virtual WebGLId createTexture() { return 1; }
virtual void deleteBuffer(WebGLId) { }
virtual void deleteFramebuffer(WebGLId) { }