Title: [128641] trunk/Source/WebCore
Revision
128641
Author
ach...@adobe.com
Date
2012-09-14 12:31:04 -0700 (Fri, 14 Sep 2012)

Log Message

[CSS Shaders] Refactor FECustomFilter to make it usable from platform dependent implementations
https://bugs.webkit.org/show_bug.cgi?id=96801

Reviewed by Dean Jackson.

I've refactored the FECustomFilter to allow FECustomFilterSkia.cpp to use the rendering part
from outside.

Also removed the Texture class as it is not available on some platforms.

The changes for Skia will land in a different patch:
https://bugs.webkit.org/show_bug.cgi?id=96579

No new tests, the existing custom filters tests should already cover this.

* platform/graphics/filters/CustomFilterGlobalContext.cpp:
(WebCore::CustomFilterGlobalContext::prepareContextIfNeeded):
* platform/graphics/filters/FECustomFilter.cpp:
(WebCore::FECustomFilter::FECustomFilter):
(WebCore::FECustomFilter::deleteRenderBuffers):
(WebCore::FECustomFilter::drawFilterMesh):
(WebCore):
(WebCore::FECustomFilter::prepareForDrawing):
(WebCore::FECustomFilter::programNeedsInputTexture):
(WebCore::FECustomFilter::applyShader):
(WebCore::FECustomFilter::initializeContext):
(WebCore::FECustomFilter::ensureInputTexture):
(WebCore::FECustomFilter::uploadInputTexture):
(WebCore::FECustomFilter::ensureFrameBuffer):
(WebCore::FECustomFilter::resizeContextIfNeeded):
(WebCore::FECustomFilter::resizeContext):
(WebCore::FECustomFilter::bindProgramAndBuffers):
* platform/graphics/filters/FECustomFilter.h:
(FECustomFilter):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (128640 => 128641)


--- trunk/Source/WebCore/ChangeLog	2012-09-14 19:22:01 UTC (rev 128640)
+++ trunk/Source/WebCore/ChangeLog	2012-09-14 19:31:04 UTC (rev 128641)
@@ -1,3 +1,40 @@
+2012-09-14  Alexandru Chiculita  <ach...@adobe.com>
+
+        [CSS Shaders] Refactor FECustomFilter to make it usable from platform dependent implementations
+        https://bugs.webkit.org/show_bug.cgi?id=96801
+
+        Reviewed by Dean Jackson.
+
+        I've refactored the FECustomFilter to allow FECustomFilterSkia.cpp to use the rendering part
+        from outside.
+
+        Also removed the Texture class as it is not available on some platforms.
+
+        The changes for Skia will land in a different patch:
+        https://bugs.webkit.org/show_bug.cgi?id=96579
+
+        No new tests, the existing custom filters tests should already cover this.
+
+        * platform/graphics/filters/CustomFilterGlobalContext.cpp:
+        (WebCore::CustomFilterGlobalContext::prepareContextIfNeeded):
+        * platform/graphics/filters/FECustomFilter.cpp:
+        (WebCore::FECustomFilter::FECustomFilter):
+        (WebCore::FECustomFilter::deleteRenderBuffers):
+        (WebCore::FECustomFilter::drawFilterMesh):
+        (WebCore):
+        (WebCore::FECustomFilter::prepareForDrawing):
+        (WebCore::FECustomFilter::programNeedsInputTexture):
+        (WebCore::FECustomFilter::applyShader):
+        (WebCore::FECustomFilter::initializeContext):
+        (WebCore::FECustomFilter::ensureInputTexture):
+        (WebCore::FECustomFilter::uploadInputTexture):
+        (WebCore::FECustomFilter::ensureFrameBuffer):
+        (WebCore::FECustomFilter::resizeContextIfNeeded):
+        (WebCore::FECustomFilter::resizeContext):
+        (WebCore::FECustomFilter::bindProgramAndBuffers):
+        * platform/graphics/filters/FECustomFilter.h:
+        (FECustomFilter):
+
 2012-09-14  Alexey Proskuryakov  <a...@apple.com>
 
         REGRESSION(r126717): It made inspector/styles/media-queries.html fail/flakey

Modified: trunk/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp (128640 => 128641)


--- trunk/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp	2012-09-14 19:22:01 UTC (rev 128640)
+++ trunk/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp	2012-09-14 19:31:04 UTC (rev 128641)
@@ -78,6 +78,8 @@
     GraphicsContext3D::Attributes attributes;
     attributes.preserveDrawingBuffer = true;
     attributes.premultipliedAlpha = false;
+    attributes.shareResources = true;
+    attributes.preferDiscreteGPU = true;
     m_context = GraphicsContext3D::create(attributes, hostWindow, GraphicsContext3D::RenderOffscreen);
     if (!m_context)
         return;

Modified: trunk/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp (128640 => 128641)


--- trunk/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp	2012-09-14 19:22:01 UTC (rev 128640)
+++ trunk/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp	2012-09-14 19:31:04 UTC (rev 128641)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
  * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -84,6 +85,7 @@
     , m_globalContext(customFilterGlobalContext)
     , m_validatedProgram(validatedProgram)
     , m_compiledProgram(0) // Don't compile the program unless we need to paint.
+    , m_inputTexture(0)
     , m_frameBuffer(0)
     , m_depthBuffer(0)
     , m_destTexture(0)
@@ -113,6 +115,10 @@
     if (!m_context)
         return;
     m_context->makeContextCurrent();
+    if (m_inputTexture) {
+        m_context->deleteTexture(m_inputTexture);
+        m_inputTexture = 0;
+    }
     if (m_frameBuffer) {
         // Make sure to unbind any framebuffer from the context first, otherwise
         // some platforms might refuse to bind the same buffer id again.
@@ -149,47 +155,65 @@
     in->copyUnmultipliedImage(dstPixelArray, effectDrawingRect);
 }
 
+void FECustomFilter::drawFilterMesh(Platform3DObject inputTexture)
+{
+    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
+    m_context->viewport(0, 0, m_contextSize.width(), m_contextSize.height());
+    
+    m_context->clearColor(0, 0, 0, 0);
+    m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);
+    
+    bindProgramAndBuffers(inputTexture);
+    m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0);
+    unbindVertexAttributes();
+}
+
+bool FECustomFilter::prepareForDrawing(CustomFilterDrawType filterDrawType)
+{
+    if (!m_context && !initializeContext())
+        return false;
+    m_context->makeContextCurrent();
+
+    // If the shader had compiler errors we cannot draw anything.
+    if (!m_compiledProgram->isInitialized())
+        return false;
+    
+    // Only allocate a texture if the program needs one and the caller doesn't allocate one by itself.
+    if ((programNeedsInputTexture() && (filterDrawType == NEEDS_INPUT_TEXTURE) && !ensureInputTexture())
+        || !ensureFrameBuffer())
+        return false;
+    
+    return true;
+}
+
+bool FECustomFilter::programNeedsInputTexture() const
+{
+    ASSERT(m_compiledProgram.get());
+    return m_compiledProgram->samplerLocation() != -1;
+}
+
 bool FECustomFilter::applyShader()
 {
     Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult();
     if (!dstPixelArray)
         return false;
 
+    if (!prepareForDrawing())
+        return false;
+
     FilterEffect* in = inputEffect(0);
     IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
-    RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
-    
     IntSize newContextSize(effectDrawingRect.size());
-    bool hadContext = m_context;
-    if (!m_context && !initializeContext())
+    if (!resizeContextIfNeeded(newContextSize))
         return false;
-    m_context->makeContextCurrent();
-    
-    if (!hadContext || m_contextSize != newContextSize)
-        resizeContext(newContextSize);
 
-#if !PLATFORM(BLACKBERRY) // BlackBerry defines its own Texture class.
-    // Do not draw the filter if the input image cannot fit inside a single GPU texture.
-    if (m_inputTexture->tiles().numTilesX() != 1 || m_inputTexture->tiles().numTilesY() != 1)
-        return false;
-#endif
-    
-    // The shader had compiler errors. We cannot draw anything.
-    if (!m_compiledProgram->isInitialized())
-        return false;
+    bool needsInputTexture = programNeedsInputTexture();
+    if (needsInputTexture) {
+        RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
+        uploadInputTexture(srcPixelArray.get());
+    }
+    drawFilterMesh(needsInputTexture ? m_inputTexture : 0);
 
-    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
-    m_context->viewport(0, 0, newContextSize.width(), newContextSize.height());
-    
-    m_context->clearColor(0, 0, 0, 0);
-    m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);
-    
-    bindProgramAndBuffers(srcPixelArray.get());
-    
-    m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0);
-    
-    unbindVertexAttributes();
-
     ASSERT(static_cast<size_t>(newContextSize.width() * newContextSize.height() * 4) == dstPixelArray->length());
     m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, dstPixelArray->data());
 
@@ -211,41 +235,73 @@
     m_mesh = CustomFilterMesh::create(m_context.get(), m_meshColumns, m_meshRows, 
                                       FloatRect(0, 0, 1, 1),
                                       m_meshType);
+
     return true;
 }
 
-void FECustomFilter::resizeContext(const IntSize& newContextSize)
+bool FECustomFilter::ensureInputTexture()
 {
-#if !PLATFORM(BLACKBERRY) // BlackBerry defines its own Texture class
-    m_inputTexture = Texture::create(m_context.get(), Texture::RGBA8, newContextSize.width(), newContextSize.height());
-#else
-    m_inputTexture = Texture::create(true);
-#endif
-    
+    if (!m_inputTexture)
+        m_inputTexture = m_context->createTexture();
+    return m_inputTexture;
+}
+
+void FECustomFilter::uploadInputTexture(Uint8ClampedArray* srcPixelArray)
+{
+    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_inputTexture);
+    m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_contextSize.width(), m_contextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, srcPixelArray->data());
+}
+
+bool FECustomFilter::ensureFrameBuffer()
+{
     if (!m_frameBuffer)
         m_frameBuffer = m_context->createFramebuffer();
     if (!m_depthBuffer)
         m_depthBuffer = m_context->createRenderbuffer();
-    if (!m_destTexture) {
+    if (!m_destTexture)
         m_destTexture = m_context->createTexture();
-        m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_destTexture);
-        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
-        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
-        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
-        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
-    }
-    
-    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_destTexture);
-    m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, newContextSize.width(), newContextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
+    return m_frameBuffer && m_depthBuffer && m_destTexture;
+}
 
+bool FECustomFilter::resizeContextIfNeeded(const IntSize& newContextSize)
+{
+    if (newContextSize.isEmpty())
+        return false;
+    if (m_contextSize == newContextSize)
+        return true;
+
+    int maxTextureSize = 0;
+    m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
+    if (newContextSize.height() > maxTextureSize || newContextSize.width() > maxTextureSize)
+        return false;
+
+    return resizeContext(newContextSize);
+}
+
+bool FECustomFilter::resizeContext(const IntSize& newContextSize)
+{
     m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
+    m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_destTexture);
+    // We are going to clear the output buffer anyway, so we can safely initialize the destination texture with garbage data.
+#if PLATFORM(CHROMIUM)
+    // FIXME: GraphicsContext3D::texImage2DDirect is not implemented on Chromium.
+    m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, newContextSize.width(), newContextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+#else
+    m_context->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, newContextSize.width(), newContextSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+#endif
     m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_destTexture, 0);
-    
+ 
     m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
     m_context->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, newContextSize.width(), newContextSize.height());
     m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer);
+
+    if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
+        return false;
+
+    m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0);
     
     m_contextSize = newContextSize;
+    return true;
 }
 
 void FECustomFilter::bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset)
@@ -337,24 +393,24 @@
     }
 }
 
-void FECustomFilter::bindProgramAndBuffers(Uint8ClampedArray* srcPixelArray)
+void FECustomFilter::bindProgramAndBuffers(Platform3DObject inputTexture)
 {
     ASSERT(m_compiledProgram->isInitialized());
 
     m_context->useProgram(m_compiledProgram->program());
     
-    if (m_compiledProgram->samplerLocation() != -1) {
+    if (programNeedsInputTexture()) {
         // We should be binding the DOM element texture sampler only if the author is using the CSS mix function.
         ASSERT(m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE);
+        ASSERT(m_compiledProgram->samplerLocation() != -1);
 
         m_context->activeTexture(GraphicsContext3D::TEXTURE0);
         m_context->uniform1i(m_compiledProgram->samplerLocation(), 0);
-#if !PLATFORM(BLACKBERRY)
-        m_inputTexture->load(srcPixelArray->data());
-        m_inputTexture->bindTile(0);
-#else
-        notImplemented();
-#endif
+        m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, inputTexture);
+        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+        m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
     }
     
     if (m_compiledProgram->projectionMatrixLocation() != -1) {

Modified: trunk/Source/WebCore/platform/graphics/filters/FECustomFilter.h (128640 => 128641)


--- trunk/Source/WebCore/platform/graphics/filters/FECustomFilter.h	2012-09-14 19:22:01 UTC (rev 128640)
+++ trunk/Source/WebCore/platform/graphics/filters/FECustomFilter.h	2012-09-14 19:31:04 UTC (rev 128641)
@@ -78,27 +78,42 @@
     bool applyShader();
     void clearShaderResult();
     bool initializeContext();
+    
+    enum CustomFilterDrawType {
+        NEEDS_INPUT_TEXTURE,
+        NO_INPUT_TEXTURE
+    };
+    bool prepareForDrawing(CustomFilterDrawType = NEEDS_INPUT_TEXTURE);
+
+    void drawFilterMesh(Platform3DObject inputTexture);
+    bool programNeedsInputTexture() const;
+    bool ensureInputTexture();
+    void uploadInputTexture(Uint8ClampedArray* srcPixelArray);
+    bool resizeContextIfNeeded(const IntSize&);
+    bool resizeContext(const IntSize&);
+
+    bool ensureFrameBuffer();
     void deleteRenderBuffers();
-    void resizeContext(const IntSize& newContextSize);
+
     void bindVertexAttribute(int attributeLocation, unsigned size, unsigned offset);
     void unbindVertexAttribute(int attributeLocation);
     void bindProgramArrayParameters(int uniformLocation, CustomFilterArrayParameter*);
     void bindProgramNumberParameters(int uniformLocation, CustomFilterNumberParameter*);
     void bindProgramTransformParameter(int uniformLocation, CustomFilterTransformParameter*);
     void bindProgramParameters();
-    void bindProgramAndBuffers(Uint8ClampedArray* srcPixelArray);
+    void bindProgramAndBuffers(Platform3DObject inputTexture);
     void unbindVertexAttributes();
     
     // No need to keep a reference here. It is owned by the RenderView.
     CustomFilterGlobalContext* m_globalContext;
     
     RefPtr<GraphicsContext3D> m_context;
-    RefPtr<Texture> m_inputTexture;
     RefPtr<CustomFilterValidatedProgram> m_validatedProgram;
     RefPtr<CustomFilterCompiledProgram> m_compiledProgram;
     RefPtr<CustomFilterMesh> m_mesh;
     IntSize m_contextSize;
 
+    Platform3DObject m_inputTexture;
     Platform3DObject m_frameBuffer;
     Platform3DObject m_depthBuffer;
     Platform3DObject m_destTexture;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to