Title: [136745] trunk/Source/WebCore
Revision
136745
Author
[email protected]
Date
2012-12-05 13:03:01 -0800 (Wed, 05 Dec 2012)

Log Message

WebGL: use pointer to the source data for Image directly in texImage2D and texSubImage2D to avoid memory copy if no conversion is needed
https://bugs.webkit.org/show_bug.cgi?id=103885

Patch by Jun Jiang <[email protected]> on 2012-12-05
Reviewed by Kenneth Russell.

In texImage2D() and texSubImage2D(), there is a redundant memory copy from Image data to the intermediate vector when no conversion is needed. If the Image resource can be locked properly, it is better to use the pointer to the image source directly and hence avoid the memory copy and improve the performance.

Already covered by current tests.

* html/canvas/WebGLRenderingContext.cpp:
(WebCore):
(WebCore::WebGLRenderingContext::texImage2DBase):
(WebCore::WebGLRenderingContext::texImage2DImpl):
(WebCore::WebGLRenderingContext::texSubImage2DBase):
(WebCore::WebGLRenderingContext::texSubImage2DImpl):
* html/canvas/WebGLRenderingContext.h:
(WebGLRenderingContext):
* platform/graphics/GraphicsContext3D.h:
(ImageExtractor):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (136744 => 136745)


--- trunk/Source/WebCore/ChangeLog	2012-12-05 21:00:54 UTC (rev 136744)
+++ trunk/Source/WebCore/ChangeLog	2012-12-05 21:03:01 UTC (rev 136745)
@@ -1,3 +1,25 @@
+2012-12-05  Jun Jiang  <[email protected]>
+
+        WebGL: use pointer to the source data for Image directly in texImage2D and texSubImage2D to avoid memory copy if no conversion is needed
+        https://bugs.webkit.org/show_bug.cgi?id=103885
+
+        Reviewed by Kenneth Russell.
+
+        In texImage2D() and texSubImage2D(), there is a redundant memory copy from Image data to the intermediate vector when no conversion is needed. If the Image resource can be locked properly, it is better to use the pointer to the image source directly and hence avoid the memory copy and improve the performance. 
+
+        Already covered by current tests.
+
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore):
+        (WebCore::WebGLRenderingContext::texImage2DBase):
+        (WebCore::WebGLRenderingContext::texImage2DImpl):
+        (WebCore::WebGLRenderingContext::texSubImage2DBase):
+        (WebCore::WebGLRenderingContext::texSubImage2DImpl):
+        * html/canvas/WebGLRenderingContext.h:
+        (WebGLRenderingContext):
+        * platform/graphics/GraphicsContext3D.h:
+        (ImageExtractor):
+
 2012-12-05  Elliott Sprehn  <[email protected]>
 
         Add infrastructure for :before and :after in DOM

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp (136744 => 136745)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp	2012-12-05 21:00:54 UTC (rev 136744)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp	2012-12-05 21:03:01 UTC (rev 136745)
@@ -3571,9 +3571,7 @@
     cleanupAfterGraphicsCall(false);
 }
 
-void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
-                                           GC3Dsizei width, GC3Dsizei height, GC3Dint border,
-                                           GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
+void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
 {
     // FIXME: For now we ignore any errors returned
     ec = 0;
@@ -3624,16 +3622,23 @@
         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
         return;
     }
+    GraphicsContext3D::SourceDataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
+    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
+    const void* imagePixelData = imageExtractor.imagePixelData();
 
-    if (!m_context->packImageData(image, imageExtractor.imagePixelData(), format, type, flipY, imageExtractor.imageAlphaOp(), imageExtractor.imageSourceFormat(), imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImageData error");
-        return;
+    bool needConversion = true;
+    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::SourceFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
+        needConversion = false;
+    else {
+        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error");
+            return;
+        }
     }
 
     if (m_unpackAlignment != 1)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-    texImage2DBase(target, level, internalformat, image->width(), image->height(), 0,
-                   format, type, data.data(), ec);
+    texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, ec);
     if (m_unpackAlignment != 1)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 }
@@ -3825,9 +3830,7 @@
     texParameter(target, pname, 0, param, false);
 }
 
-void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                                              GC3Dsizei width, GC3Dsizei height,
-                                              GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
+void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
 {
     // FIXME: For now we ignore any errors returned
     ec = 0;
@@ -3867,16 +3870,23 @@
         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
         return;
     }
+    GraphicsContext3D::SourceDataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
+    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
+    const void* imagePixelData = imageExtractor.imagePixelData();
 
-    if (!m_context->packImageData(image, imageExtractor.imagePixelData(), format, type, flipY, imageExtractor.imageAlphaOp(), imageExtractor.imageSourceFormat(), imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImageData error");
-        return;
+    bool needConversion = true;
+    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::SourceFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
+        needConversion = false;
+    else {
+        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
+            return;
+        }
     }
 
     if (m_unpackAlignment != 1)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
-                      format, type, data.data(), ec);
+    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type,  needConversion ? data.data() : imagePixelData, ec);
     if (m_unpackAlignment != 1)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 }

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h (136744 => 136745)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h	2012-12-05 21:00:54 UTC (rev 136744)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h	2012-12-05 21:03:01 UTC (rev 136745)
@@ -530,15 +530,11 @@
     // Helper to restore state that clearing the framebuffer may destroy.
     void restoreStateAfterClear();
 
-    void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat,
-                        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
-                        GC3Denum format, GC3Denum type, void* pixels, ExceptionCode&);
+    void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
     void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat,
                         GC3Denum format, GC3Denum type, Image*,
                         bool flipY, bool premultiplyAlpha, ExceptionCode&);
-    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                           GC3Dsizei width, GC3Dsizei height,
-                           GC3Denum format, GC3Denum type, void* pixels, ExceptionCode&);
+    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
     void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
                            GC3Denum format, GC3Denum type,
                            Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode&);

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h (136744 => 136745)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h	2012-12-05 21:00:54 UTC (rev 136744)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h	2012-12-05 21:03:01 UTC (rev 136745)
@@ -874,7 +874,7 @@
     };
 
     // Packs the contents of the given Image which is passed in |pixels| into the passed Vector
-    // according to the given format and type, and obeying the flipY and premultiplyAlpha flags.
+    // according to the given format and type, and obeying the flipY and AlphaOp flags.
     // Returns true upon success.
     static bool packImageData(Image*, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp, SourceDataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data);
 
@@ -895,9 +895,8 @@
         unsigned imageSourceUnpackAlignment() { return m_imageSourceUnpackAlignment; } 
     private:
         // Each platform must provide an implementation of this method.
-        // Extracts the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc
-        // needs to lock the resources or relevant data if needed
-        // Return true upon success
+        // Extracts the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc,
+        // needs to lock the resources or relevant data if needed and returns true upon success
         bool extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
 
 #if USE(SKIA)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to