[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

zmo at google.com zmo at google.com
Wed Dec 22 12:35:48 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit cf7ab46108d3461485715a01c660cd0f7209c4a0
Author: zmo at google.com <zmo at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Aug 25 20:28:59 2010 +0000

    2010-08-24  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Kenneth Russell.
    
            Passing premultiplyAlpha=false to tex{Sub}Image2D loses information (skia)
            https://bugs.webkit.org/show_bug.cgi?id=38282
    
            * src/WebImageDecoder.cpp:
            (WebKit::WebImageDecoder::init): Add premultiplyAlpha flag.
    2010-08-24  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Kenneth Russell.
    
            Passing premultiplyAlpha=false to tex{Sub}Image2D loses information (skia)
            https://bugs.webkit.org/show_bug.cgi?id=38282
    
            Test: fast/canvas/webgl/gl-teximage.html
    
            * platform/graphics/GraphicsContext3D.cpp: Fix a bug where alpha channel is ignored.
            * platform/graphics/ImageSource.cpp: Add premultiplyAlpha flag.
            (WebCore::ImageSource::ImageSource):
            (WebCore::ImageSource::setData):
            * platform/graphics/ImageSource.h: Ditto.
            * platform/graphics/cg/ImageSourceCG.cpp: Ditto.
            (WebCore::ImageSource::ImageSource):
            * platform/graphics/qt/ImageDecoderQt.cpp: Ditto.
            (WebCore::ImageDecoder::create):
            (WebCore::ImageDecoderQt::ImageDecoderQt):
            (WebCore::ImageDecoderQt::frameCount):
            (WebCore::ImageDecoderQt::forceLoadEverything):
            * platform/graphics/qt/ImageDecoderQt.h: Ditto.
            * platform/graphics/skia/GraphicsContext3DSkia.cpp: Fix the premultiplyAlpha data loss issue in skia.
            (WebCore::GraphicsContext3D::getImageData):
            * platform/image-decoders/ImageDecoder.cpp: Add premultiplyAlpha flag.
            (WebCore::ImageDecoder::create):
            (WebCore::RGBA32Buffer::RGBA32Buffer):
            (WebCore::RGBA32Buffer::operator=):
            * platform/image-decoders/ImageDecoder.h: Ditto.
            (WebCore::RGBA32Buffer::premultiplyAlpha):
            (WebCore::RGBA32Buffer::setPremultiplyAlpha):
            (WebCore::RGBA32Buffer::setRGBA):
            (WebCore::ImageDecoder::ImageDecoder):
            * platform/image-decoders/bmp/BMPImageDecoder.cpp: Ditto.
            (WebCore::BMPImageDecoder::BMPImageDecoder):
            (WebCore::BMPImageDecoder::frameBufferAtIndex):
            * platform/image-decoders/bmp/BMPImageDecoder.h: Ditto.
            * platform/image-decoders/gif/GIFImageDecoder.cpp: Ditto.
            (WebCore::GIFImageDecoder::GIFImageDecoder):
            (WebCore::GIFImageDecoder::frameCount):
            * platform/image-decoders/gif/GIFImageDecoder.h: Ditto.
            * platform/image-decoders/ico/ICOImageDecoder.cpp: Ditto.
            (WebCore::ICOImageDecoder::ICOImageDecoder):
            (WebCore::ICOImageDecoder::frameCount):
            (WebCore::ICOImageDecoder::decodeAtIndex):
            * platform/image-decoders/ico/ICOImageDecoder.h: Ditto.
            * platform/image-decoders/jpeg/JPEGImageDecoder.cpp: Ditto.
            (WebCore::JPEGImageDecoder::JPEGImageDecoder):
            (WebCore::JPEGImageDecoder::frameBufferAtIndex):
            * platform/image-decoders/jpeg/JPEGImageDecoder.h: Ditto.
            * platform/image-decoders/png/PNGImageDecoder.cpp: Ditto.
            (WebCore::PNGImageDecoder::PNGImageDecoder):
            (WebCore::PNGImageDecoder::frameBufferAtIndex):
            * platform/image-decoders/png/PNGImageDecoder.h: Ditto.
            * platform/image-decoders/skia/ImageDecoderSkia.cpp: Ditto.
            (WebCore::RGBA32Buffer::RGBA32Buffer):
            (WebCore::RGBA32Buffer::operator=):
    2010-08-24  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Kenneth Russell.
    
            Passing premultiplyAlpha=false to tex{Sub}Image2D loses information (skia)
            https://bugs.webkit.org/show_bug.cgi?id=38282
    
            * fast/canvas/webgl/gl-teximage-expected.txt: Added.
            * fast/canvas/webgl/gl-teximage.html: Added.
            * fast/canvas/webgl/resources/3x3.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-256-with-128-alpha.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-256.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-default-gamma.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-gamma0.1.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-gamma1.0.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-gamma2.0.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-gamma4.0.png: Added.
            * fast/canvas/webgl/resources/gray-ramp-gamma9.0.png: Added.
            * fast/canvas/webgl/resources/gray-ramp.png: Added.
            * fast/canvas/webgl/resources/webgl-test-utils.js: Sync with khronos.
            (WebGLTestUtils):
            * fast/canvas/webgl/resources/zero-alpha.png: Added.
            * platform/chromium/test_expectations.txt: Don't run gl-teximage.html for mac.
            * platform/mac/Skipped: Don't run gl-teximage.html for mac.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66039 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index c565a4f..2aeb1ce 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,28 @@
+2010-08-24  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Passing premultiplyAlpha=false to tex{Sub}Image2D loses information (skia)
+        https://bugs.webkit.org/show_bug.cgi?id=38282
+
+        * fast/canvas/webgl/gl-teximage-expected.txt: Added.
+        * fast/canvas/webgl/gl-teximage.html: Added.
+        * fast/canvas/webgl/resources/3x3.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-256-with-128-alpha.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-256.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-default-gamma.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-gamma0.1.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-gamma1.0.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-gamma2.0.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-gamma4.0.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp-gamma9.0.png: Added.
+        * fast/canvas/webgl/resources/gray-ramp.png: Added.
+        * fast/canvas/webgl/resources/webgl-test-utils.js: Sync with khronos.
+        (WebGLTestUtils):
+        * fast/canvas/webgl/resources/zero-alpha.png: Added.
+        * platform/chromium/test_expectations.txt: Don't run gl-teximage.html for mac.
+        * platform/mac/Skipped: Don't run gl-teximage.html for mac.
+
 2010-08-25  Andreas Kling  <andreas.kling at nokia.com>
 
         Reviewed by Ariya Hidayat.
diff --git a/LayoutTests/fast/canvas/webgl/gl-teximage-expected.txt b/LayoutTests/fast/canvas/webgl/gl-teximage-expected.txt
new file mode 100644
index 0000000..727b9ee
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/gl-teximage-expected.txt
@@ -0,0 +1,61 @@
+Test texImage2D conversions.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+
+check pixels are NOT pre-multiplied
+PASS getError was expected value: NO_ERROR : Should be no errors from setup
+PASS pixel 0, 15 should be 0, 0, 0, 255 was 0, 0, 0, 255
+PASS pixel 128, 15 should be 255, 0, 255, 255 was 255, 0, 0, 255
+PASS pixel 255, 15 should be 0, 0, 255, 255 was 0, 0, 255, 255
+PASS pixel 0, 8 should be 128, 128, 128, 255 was 128, 128, 128, 255
+PASS pixel 128, 8 should be 255, 255, 255, 255 was 255, 255, 255, 255
+PASS pixel 255, 8 should be 0, 255, 255, 255 was 0, 255, 255, 255
+PASS pixel 0, 0 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 128, 0 should be 255, 255, 0, 255 was 255, 255, 0, 255
+PASS pixel 255, 0 should be 0, 255, 0, 255 was 0, 255, 0, 255
+
+check quantization
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS There should be 256 unique values in channel 0. Found 256
+PASS There should be 256 unique values in channel 1. Found 256
+PASS There should be 256 unique values in channel 2. Found 256
+PASS There should be 256 unique values in channel 3. Found 256
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS There should be 16 unique values in channel 0. Found 16
+PASS There should be 16 unique values in channel 1. Found 16
+PASS There should be 16 unique values in channel 2. Found 16
+PASS There should be 16 unique values in channel 3. Found 16
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS There should be 32 unique values in channel 0. Found 32
+PASS There should be 64 unique values in channel 1. Found 64
+PASS There should be 32 unique values in channel 2. Found 32
+PASS There should be 1 unique values in channel 3. Found 1
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS There should be 32 unique values in channel 0. Found 32
+PASS There should be 32 unique values in channel 1. Found 32
+PASS There should be 32 unique values in channel 2. Found 32
+PASS There should be 2 unique values in channel 3. Found 2
+
+check pixels are pre-multiplied
+PASS getError was expected value: NO_ERROR : Should be no errors from setup
+PASS pixels should all be 0.
+
+check pixels are flipped
+PASS getError was expected value: NO_ERROR : Should be no errors from setup
+PASS pixel 0, 15 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 128, 15 should be 255, 255, 0, 255 was 255, 255, 0, 255
+PASS pixel 255, 15 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 0, 8 should be 255, 0, 255, 255 was 255, 0, 255, 255
+PASS pixel 128, 8 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 255, 8 should be 0, 255, 0, 255 was 0, 255, 0, 255
+PASS pixel 0, 0 should be 0, 0, 0, 255 was 0, 0, 0, 255
+PASS pixel 128, 0 should be 0, 0, 255, 255 was 0, 0, 255, 255
+PASS pixel 255, 0 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS getError was expected value: NO_ERROR : Should be no errors
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/gl-teximage.html b/LayoutTests/fast/canvas/webgl/gl-teximage.html
new file mode 100644
index 0000000..016a5f6
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/gl-teximage.html
@@ -0,0 +1,266 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL texImage2D conformance test.</title>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="256" height="16" style="width: 256px; height: 48px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("Test texImage2D conversions.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+var imgURLs = [
+  'resources/gray-ramp-256-with-128-alpha.png',
+  'resources/gray-ramp-256.png',
+  'resources/gray-ramp-default-gamma.png',
+  'resources/gray-ramp-gamma0.1.png',
+  'resources/gray-ramp-gamma1.0.png',
+  'resources/gray-ramp-gamma2.0.png',
+  'resources/gray-ramp-gamma4.0.png',
+  'resources/gray-ramp-gamma9.0.png',
+  'resources/gray-ramp.png',
+  'resources/zero-alpha.png',
+  'resources/3x3.png'];
+
+wtu.loadImagesAsync(imgURLs, runTests);
+
+function runTests(imgs) {
+
+  var loc = gl.getUniformLocation(program, "tex");
+  gl.uniform1i(loc, 0);
+
+  gl.disable(gl.BLEND);
+  gl.disable(gl.DEPTH_TEST);
+
+  var width = canvas.width;
+  var height = canvas.height;
+
+  function checkPixel(buf, x, y, color) {
+    var off = (y * width + x) * 4;
+    var msg = "pixel " + x + ", " + y + " should be " +
+              color[0] + ", " +
+              color[1] + ", " +
+              color[2] + ", " +
+              color[3] + " was " +
+              buf[off + 0] + ", " +
+              buf[off + 1] + ", " +
+              buf[off + 2] + ", " +
+              buf[off + 3];
+
+    for (var ii = 0; ii < 4; ++ii) {
+      if (buf[off + ii] != color[ii]) {
+        testFailed(msg);
+        return;
+      }
+    }
+    testPassed(msg);
+  }
+
+  var tex = gl.createTexture();
+  gl.bindTexture(gl.TEXTURE_2D, tex);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+  var buf = new Uint8Array(width * height * 4);
+
+  debug("");
+  debug("check pixels are NOT pre-multiplied");
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                imgs['resources/zero-alpha.png']);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+  var left = 0;
+  var middle = Math.floor(width / 2);
+  var right = width - 1;
+  var bottom = 0;
+  var center = Math.floor(height / 2);
+  var top = height - 1;
+  checkPixel(buf, left,   top,    [  0,   0,   0, 255]);
+  checkPixel(buf, middle, top,    [255,   0, 255, 255]);
+  checkPixel(buf, right,  top,    [  0,   0, 255, 255]);
+  checkPixel(buf, left,   center, [128, 128, 128, 255]);
+  checkPixel(buf, middle, center, [255, 255, 255, 255]);
+  checkPixel(buf, right,  center, [  0, 255, 255, 255]);
+  checkPixel(buf, left,   bottom, [255,   0,   0, 255]);
+  checkPixel(buf, middle, bottom, [255, 255,   0, 255]);
+  checkPixel(buf, right,  bottom, [  0, 255,   0, 255]);
+
+  debug("");
+  debug("check quantization");
+  var quantInfo = [
+    {format: gl.RGBA, type: gl.UNSIGNED_BYTE,          counts: [256, 256, 256, 256]},
+    {format: gl.RGBA, type: gl.UNSIGNED_SHORT_4_4_4_4, counts: [ 16,  16,  16,  16]},
+    {format: gl.RGB,  type: gl.UNSIGNED_SHORT_5_6_5,   counts: [ 32,  64,  32,   1]},
+    {format: gl.RGBA, type: gl.UNSIGNED_SHORT_5_5_5_1, counts: [ 32,  32,  32,   2]}];
+  for (var qq = 0; qq < quantInfo.length; ++qq) {
+    var info = quantInfo[qq];
+    gl.texImage2D(
+        gl.TEXTURE_2D, 0, info.format, info.format, info.type,
+        imgs['resources/gray-ramp-256.png']);
+    glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+    wtu.drawQuad(gl);
+    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    var counts = [{ }, { }, { }, { }];
+    var numUniqueValues = [0, 0, 0, 0];
+    // Count the number of unique values in each channel.
+    for (var ii = 0; ii < width * height * 4; ii += 4) {
+      for (var jj = 0; jj < 4; ++jj) {
+        var v = buf[ii + jj];
+        if (!counts[jj][v]) {
+          counts[jj][v] = 1;
+          ++numUniqueValues[jj];
+        } else {
+          ++counts[jj][v];
+        }
+      }
+    }
+    for (var ii = 0; ii < 4; ++ii) {
+      assertMsg(numUniqueValues[ii] == info.counts[ii],
+                "There should be " + info.counts[ii] +
+                " unique values in channel " + ii + ". Found " +
+                numUniqueValues[ii]);
+    }
+  }
+
+// FIXME(zmo): fix the gamma correction and add back the commented out tests below.
+/*
+  debug("");
+  debug("Check that gamma settings don't effect 8bit pngs");
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                imgs['resources/gray-ramp-default-gamma.png']);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+  wtu.drawQuad(gl);
+  var ref = new Uint8Array(width * height * 4);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
+
+  var gammaImages = [
+    'resources/gray-ramp-gamma0.1.png',
+    'resources/gray-ramp-gamma1.0.png',
+    'resources/gray-ramp-gamma2.0.png',
+    'resources/gray-ramp-gamma4.0.png',
+    'resources/gray-ramp-gamma9.0.png'];
+  for (var ii = 0; ii < gammaImages.length; ++ii) {
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                  imgs[gammaImages[ii]]);
+    wtu.drawQuad(gl);
+    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    var same = true;
+    for (var jj = 0; jj < width * height * 4; ++jj) {
+      if (buf[jj] != ref[jj]) {
+        same = false;
+        break;
+      }
+    }
+    assertMsg(same, "pixels should be same regardless of gamma settings.");
+  }
+
+  debug("");
+  debug("check pixels are UN pre-multiplied");
+  var canvas2d = document.createElement("canvas");
+  canvas2d.width = 256;
+  canvas2d.height = 1;
+  //canvas2d.style.height = "40px";
+  //var description = document.getElementById("description");
+  //description.appendChild(canvas2d);
+  var ctx = canvas2d.getContext("2d");
+  ctx.fillRect(0, 0, 256, 1);
+  ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+  wtu.drawQuad(gl);
+  var ref = new Uint8Array(width * height * 4);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
+  var lt128Count = [0, 0, 0];
+  var ge128Count = [0, 0, 0];
+  for (var jj = 0; jj < width; ++jj) {
+    var off = jj * 4;
+    for (var cc = 0; cc < 3; ++cc) {
+      if (buf[off + cc] < 128) {
+        ++lt128Count[cc];
+      } else {
+        ++ge128Count[cc];
+      }
+    }
+  }
+  // Not sure the exact count here because gamma does effect drawing into the
+  // canvas but it should be close to 50% so I'll pass 45%
+  for (var jj = 0; jj < 3; ++jj) {
+    assertMsg(ge128Count[jj] > 256 * 0.45,
+              "Half the pixels in channel " + jj +
+              " should be >= 128,128,128. found " +
+              ((ge128Count[jj] / 256) * 100).toFixed() + "%");
+    assertMsg(lt128Count[jj] > 256 * 0.45,
+              "Half the pixels in channel " + jj +
+              " should be < 128,128,128. found " +
+              ((lt128Count[jj] / 256) * 100).toFixed() + "%");
+  }
+*/
+
+  debug("");
+  debug("check pixels are pre-multiplied");
+  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+  // TODO(gman): use different texture that won't pass on failure
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
+                imgs['resources/zero-alpha.png']);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+  var same = true;
+  for (var jj = 0; jj < width * height * 4; ++jj) {
+    if (buf[jj] != 0) {
+      same = false;
+      break;
+    }
+  }
+  assertMsg(same, "pixels should all be 0.");
+
+  debug("");
+  debug("check pixels are flipped");
+  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
+  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                imgs['resources/3x3.png']);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+  checkPixel(buf, left,   top,    [255,   0,   0, 255]);
+  checkPixel(buf, middle, top,    [255, 255,   0, 255]);
+  checkPixel(buf, right,  top,    [255,   0,   0, 255]);
+  checkPixel(buf, left,   center, [255,   0, 255, 255]);
+  checkPixel(buf, middle, center, [255,   0,   0, 255]);
+  checkPixel(buf, right,  center, [  0, 255,   0, 255]);
+  checkPixel(buf, left,   bottom, [  0,   0,   0, 255]);
+  checkPixel(buf, middle, bottom, [  0,   0, 255, 255]);
+  checkPixel(buf, right,  bottom, [255,   0,   0, 255]);
+
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
+
+  debug("");
+  successfullyParsed = true;
+  shouldBeTrue("successfullyParsed");
+  debug('<br /><span class="pass">TEST COMPLETE</span>');
+  if (window.layoutTestController)
+    layoutTestController.notifyDone();
+}
+</script>
+</body>
+</html>
+
diff --git a/LayoutTests/fast/canvas/webgl/resources/3x3.png b/LayoutTests/fast/canvas/webgl/resources/3x3.png
new file mode 100644
index 0000000..6cf1e74
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/3x3.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-256-with-128-alpha.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-256-with-128-alpha.png
new file mode 100644
index 0000000..183e55d
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-256-with-128-alpha.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-256.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-256.png
new file mode 100644
index 0000000..01e486b
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-256.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-default-gamma.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-default-gamma.png
new file mode 100755
index 0000000..a5a89be
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-default-gamma.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma0.1.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma0.1.png
new file mode 100755
index 0000000..637c792
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma0.1.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma1.0.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma1.0.png
new file mode 100755
index 0000000..40ceeb0
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma1.0.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma2.0.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma2.0.png
new file mode 100755
index 0000000..73fcf7b
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma2.0.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma4.0.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma4.0.png
new file mode 100755
index 0000000..d878f1e
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma4.0.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma9.0.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma9.0.png
new file mode 100755
index 0000000..8a69ed1
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp-gamma9.0.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/gray-ramp.png b/LayoutTests/fast/canvas/webgl/resources/gray-ramp.png
new file mode 100755
index 0000000..a5a89be
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/gray-ramp.png differ
diff --git a/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils.js b/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils.js
index 455b63b..bcb9647 100644
--- a/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils.js
+++ b/LayoutTests/fast/canvas/webgl/resources/webgl-test-utils.js
@@ -29,6 +29,20 @@ var error = function(msg) {
   }
 };
 
+/**
+ * Converts a WebGL enum to a string
+ * @param {!WebGLContext} gl The WebGLContext to use.
+ * @param {number} value The enum value.
+ * @return {string} The enum as a string.
+ */
+var glEnumToString = function(gl, value) {
+  for (var p in gl) {
+    if (gl[p] == value) {
+      return p;
+    }
+  }
+  return "0x" + value.toString(16);
+};
 
 var lastError = "";
 
@@ -110,19 +124,21 @@ var setupSimpleTextureFragmentShader = function(gl) {
  * Creates a program, attaches shaders, binds attrib locations, links the
  * program and calls useProgram.
  * @param {!Array.<!WebGLShader>} shaders The shaders to attach .
- * @param {!Array.<string>} attribs The attribs names.
+ * @param {!Array.<string>} opt_attribs The attribs names.
  * @param {!Array.<number>} opt_locations The locations for the attribs.
  */
-var setupProgram = function(gl, shaders, attribs, opt_locations) {
+var setupProgram = function(gl, shaders, opt_attribs, opt_locations) {
   var program = gl.createProgram();
   for (var ii = 0; ii < shaders.length; ++ii) {
     gl.attachShader(program, shaders[ii]);
   }
-  for (var ii = 0; ii < attribs.length; ++ii) {
-    gl.bindAttribLocation(
-        program,
-        opt_locations ? opt_locations[ii] : ii,
-        attribs[ii]);
+  if (opt_attribs) {
+    for (var ii = 0; ii < opt_attribs.length; ++ii) {
+      gl.bindAttribLocation(
+          program,
+          opt_locations ? opt_locations[ii] : ii,
+          opt_attribs[ii]);
+    }
   }
   gl.linkProgram(program);
 
@@ -813,6 +829,7 @@ return {
   drawQuad: drawQuad,
   endsWith: endsWith,
   getLastError: getLastError,
+  glEnumToString: glEnumToString,
   glErrorShouldBe: glErrorShouldBe,
   fillTexture: fillTexture,
   loadImageAsync: loadImageAsync,
diff --git a/LayoutTests/fast/canvas/webgl/resources/zero-alpha.png b/LayoutTests/fast/canvas/webgl/resources/zero-alpha.png
new file mode 100755
index 0000000..e55630c
Binary files /dev/null and b/LayoutTests/fast/canvas/webgl/resources/zero-alpha.png differ
diff --git a/LayoutTests/platform/chromium/test_expectations.txt b/LayoutTests/platform/chromium/test_expectations.txt
index fb3ffde..0bcd58d 100644
--- a/LayoutTests/platform/chromium/test_expectations.txt
+++ b/LayoutTests/platform/chromium/test_expectations.txt
@@ -2565,6 +2565,9 @@ BUGWK37297 : fast/history/sibling-visited-test.html = TEXT
 BUGWK36983 MAC : fast/canvas/webgl/null-object-behaviour.html = TEXT
 BUGWK36983 MAC : fast/canvas/webgl/uniform-location.html = TEXT
 
+// Caused by premultiplying alphas in CG image decoding.
+BUG44566 MAC : fast/canvas/webgl/gl-teximage.html = TEXT
+
 // Added in http://trac.webkit.org/changeset/57476. Fails in Chromium because
 // LayoutTestController::computedStyleWithVisitedInfo() is missing.
 BUG41206 : fast/history/multiple-classes-visited.html = TEXT TIMEOUT
diff --git a/LayoutTests/platform/mac/Skipped b/LayoutTests/platform/mac/Skipped
index 05261aa..4fa474a 100644
--- a/LayoutTests/platform/mac/Skipped
+++ b/LayoutTests/platform/mac/Skipped
@@ -292,3 +292,6 @@ animations/play-state.html
 
 # https://bugs.webkit.org/show_bug.cgi?id=43332
 inspector/dom-breakpoints.html
+
+# https://bugs.webkit.org/show_bug.cgi?id=44566
+fast/canvas/webgl/gl-teximage.html
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 6cdde62..aac132e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,61 @@
+2010-08-24  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Passing premultiplyAlpha=false to tex{Sub}Image2D loses information (skia)
+        https://bugs.webkit.org/show_bug.cgi?id=38282
+
+        Test: fast/canvas/webgl/gl-teximage.html
+
+        * platform/graphics/GraphicsContext3D.cpp: Fix a bug where alpha channel is ignored.
+        * platform/graphics/ImageSource.cpp: Add premultiplyAlpha flag.
+        (WebCore::ImageSource::ImageSource):
+        (WebCore::ImageSource::setData):
+        * platform/graphics/ImageSource.h: Ditto.
+        * platform/graphics/cg/ImageSourceCG.cpp: Ditto.
+        (WebCore::ImageSource::ImageSource):
+        * platform/graphics/qt/ImageDecoderQt.cpp: Ditto.
+        (WebCore::ImageDecoder::create):
+        (WebCore::ImageDecoderQt::ImageDecoderQt):
+        (WebCore::ImageDecoderQt::frameCount):
+        (WebCore::ImageDecoderQt::forceLoadEverything):
+        * platform/graphics/qt/ImageDecoderQt.h: Ditto.
+        * platform/graphics/skia/GraphicsContext3DSkia.cpp: Fix the premultiplyAlpha data loss issue in skia.
+        (WebCore::GraphicsContext3D::getImageData):
+        * platform/image-decoders/ImageDecoder.cpp: Add premultiplyAlpha flag.
+        (WebCore::ImageDecoder::create):
+        (WebCore::RGBA32Buffer::RGBA32Buffer):
+        (WebCore::RGBA32Buffer::operator=):
+        * platform/image-decoders/ImageDecoder.h: Ditto.
+        (WebCore::RGBA32Buffer::premultiplyAlpha):
+        (WebCore::RGBA32Buffer::setPremultiplyAlpha):
+        (WebCore::RGBA32Buffer::setRGBA):
+        (WebCore::ImageDecoder::ImageDecoder):
+        * platform/image-decoders/bmp/BMPImageDecoder.cpp: Ditto.
+        (WebCore::BMPImageDecoder::BMPImageDecoder):
+        (WebCore::BMPImageDecoder::frameBufferAtIndex):
+        * platform/image-decoders/bmp/BMPImageDecoder.h: Ditto.
+        * platform/image-decoders/gif/GIFImageDecoder.cpp: Ditto.
+        (WebCore::GIFImageDecoder::GIFImageDecoder):
+        (WebCore::GIFImageDecoder::frameCount):
+        * platform/image-decoders/gif/GIFImageDecoder.h: Ditto.
+        * platform/image-decoders/ico/ICOImageDecoder.cpp: Ditto.
+        (WebCore::ICOImageDecoder::ICOImageDecoder):
+        (WebCore::ICOImageDecoder::frameCount):
+        (WebCore::ICOImageDecoder::decodeAtIndex):
+        * platform/image-decoders/ico/ICOImageDecoder.h: Ditto.
+        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp: Ditto.
+        (WebCore::JPEGImageDecoder::JPEGImageDecoder):
+        (WebCore::JPEGImageDecoder::frameBufferAtIndex):
+        * platform/image-decoders/jpeg/JPEGImageDecoder.h: Ditto.
+        * platform/image-decoders/png/PNGImageDecoder.cpp: Ditto.
+        (WebCore::PNGImageDecoder::PNGImageDecoder):
+        (WebCore::PNGImageDecoder::frameBufferAtIndex):
+        * platform/image-decoders/png/PNGImageDecoder.h: Ditto.
+        * platform/image-decoders/skia/ImageDecoderSkia.cpp: Ditto.
+        (WebCore::RGBA32Buffer::RGBA32Buffer):
+        (WebCore::RGBA32Buffer::operator=):
+
 2010-08-25  Adam Barth  <abarth at webkit.org>
 
         Reviewed by Eric Seidel.
diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp
index 377be1c..170bb84 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -424,6 +424,7 @@ void packRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination)
     destination[0] = sourceR;
     destination[1] = sourceG;
     destination[2] = sourceB;
+    destination[3] = source[3];
 }
 
 // FIXME: this routine is lossy and must be removed.
diff --git a/WebCore/platform/graphics/ImageSource.cpp b/WebCore/platform/graphics/ImageSource.cpp
index 7f6d323..c6d97fe 100644
--- a/WebCore/platform/graphics/ImageSource.cpp
+++ b/WebCore/platform/graphics/ImageSource.cpp
@@ -41,8 +41,9 @@ namespace WebCore {
 unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024;
 #endif
 
-ImageSource::ImageSource()
+ImageSource::ImageSource(bool premultiplyAlpha)
     : m_decoder(0)
+    , m_premultiplyAlpha(premultiplyAlpha)
 {
 }
 
@@ -77,7 +78,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
     // If insufficient bytes are available to determine the image type, no decoder plugin will be
     // made.
     if (!m_decoder) {
-        m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data));
+        m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_premultiplyAlpha));
 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
         if (m_decoder && s_maxPixelsPerDecodedImage)
             m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage);
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index b7efb99..19952b1 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -114,7 +114,7 @@ const int cAnimationNone = -2;
 
 class ImageSource : public Noncopyable {
 public:
-    ImageSource();
+    ImageSource(bool premultiplyAlpha = true);
     ~ImageSource();
 
     // Tells the ImageSource that the Image no longer cares about decoded frame
@@ -172,6 +172,7 @@ public:
 
 private:
     NativeImageSourcePtr m_decoder;
+    bool m_premultiplyAlpha;
 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
     static unsigned s_maxPixelsPerDecodedImage;
 #endif
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 4a7aecc..5fa4896 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -63,8 +63,10 @@ void sharedBufferRelease(void* info)
 }
 #endif
 
-ImageSource::ImageSource()
+ImageSource::ImageSource(bool premultiplyAlpha)
     : m_decoder(0)
+    // FIXME: m_premultiplyAlpha is ignored in cg at the moment.
+    , m_premultiplyAlpha(premultiplyAlpha)
 {
 }
 
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 858cc44..02bb110 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -37,17 +37,18 @@
 
 namespace WebCore {
 
-ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha)
 {
     // We need at least 4 bytes to figure out what kind of image we're dealing with.
     if (data.size() < 4)
         return 0;
 
-    return new ImageDecoderQt;
+    return new ImageDecoderQt(premultiplyAlpha);
 }
 
-ImageDecoderQt::ImageDecoderQt()
-    : m_repetitionCount(cAnimationNone)
+ImageDecoderQt::ImageDecoderQt(bool premultiplyAlpha)
+    : ImageDecoder(premultiplyAlpha)
+    , m_repetitionCount(cAnimationNone)
 {
 }
 
@@ -104,10 +105,15 @@ size_t ImageDecoderQt::frameCount()
             // we will have to parse everything...
             if (!imageCount)
                 forceLoadEverything();
-            else
+            else {
                 m_frameBufferCache.resize(imageCount);
-        } else
+                for (size_t i = 0; i < m_frameBufferCache.size(); ++i)
+                    m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
+            }
+        } else {
             m_frameBufferCache.resize(1);
+            m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
+        }
     }
 
     return m_frameBufferCache.size();
@@ -236,6 +242,8 @@ void ImageDecoderQt::forceLoadEverything()
     // Otherwise, we want to forget about
     // the last attempt to decode a image.
     m_frameBufferCache.resize(imageCount - 1);
+    for (size_t i = 0; i < m_frameBufferCache.size(); ++i)
+        m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
     if (imageCount == 1)
       setFailed();
 }
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index ceef884..5014d53 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -41,7 +41,7 @@ namespace WebCore {
 class ImageDecoderQt : public ImageDecoder
 {
 public:
-    ImageDecoderQt();
+    ImageDecoderQt(bool premultiplyAlpha);
     ~ImageDecoderQt();
 
     virtual void setData(SharedBuffer* data, bool allDataReceived);
diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
index ee0a874..61039f2 100644
--- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
@@ -31,6 +31,7 @@
 #include "GraphicsContext3D.h"
 
 #include "Image.h"
+#include "ImageSource.h"
 #include "NativeImageSkia.h"
 
 #include <algorithm>
@@ -43,27 +44,28 @@ bool GraphicsContext3D::getImageData(Image* image,
                                      bool premultiplyAlpha,
                                      Vector<uint8_t>& outputVector)
 {
-    if (!image)
+    if (!image || !image->data())
         return false;
-    NativeImageSkia* skiaImage = image->nativeImageForCurrentFrame();
-    if (!skiaImage)
+    ImageSource decoder(false);
+    decoder.setData(image->data(), true);
+    if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
         return false;
-    SkBitmap::Config skiaConfig = skiaImage->config();
-    // FIXME: must support more image configurations.
+    bool hasAlpha = decoder.frameHasAlphaAtIndex(0);
+    OwnPtr<NativeImageSkia> pixels(decoder.createFrameAtIndex(0));
+    if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height())
+        return false;
+    SkBitmap::Config skiaConfig = pixels->config();
     if (skiaConfig != SkBitmap::kARGB_8888_Config)
         return false;
-    SkBitmap& skiaImageRef = *skiaImage;
+    SkBitmap& skiaImageRef = *pixels;
     SkAutoLockPixels lock(skiaImageRef);
-    int height = skiaImage->height();
-    int rowBytes = skiaImage->rowBytes();
-    ASSERT(rowBytes == skiaImage->width() * 4);
-    uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels());
-    outputVector.resize(rowBytes * height);
+    ASSERT(pixels->rowBytes() == pixels->width() * 4);
+    outputVector.resize(pixels->rowBytes() * pixels->height());
     AlphaOp neededAlphaOp = kAlphaDoNothing;
-    if (!premultiplyAlpha)
-        // FIXME: must fetch the image data before the premultiplication step
-        neededAlphaOp = kAlphaDoUnmultiply;
-    return packPixels(pixels, kSourceFormatBGRA8, skiaImage->width(), height, 0,
+    if (hasAlpha && premultiplyAlpha)
+        neededAlphaOp = kAlphaDoPremultiply;
+    return packPixels(reinterpret_cast<const uint8_t*>(pixels->getPixels()),
+                      kSourceFormatBGRA8, pixels->width(), pixels->height(), 0,
                       format, type, neededAlphaOp, outputVector.data());
 }
 
diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp
index fadb9e3..c1e19d8 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -52,7 +52,7 @@ static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const
     return bytesExtracted;
 }
 
-ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha)
 {
     // We need at least 4 bytes to figure out what kind of image we're dealing
     // with.
@@ -64,24 +64,24 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
 
     // GIFs begin with GIF8(7 or 9).
     if (strncmp(contents, "GIF8", 4) == 0)
-        return new GIFImageDecoder();
+        return new GIFImageDecoder(premultiplyAlpha);
 
     // Test for PNG.
     if (!memcmp(contents, "\x89\x50\x4E\x47", 4))
-        return new PNGImageDecoder();
+        return new PNGImageDecoder(premultiplyAlpha);
 
     // JPEG
     if (!memcmp(contents, "\xFF\xD8\xFF", 3))
-        return new JPEGImageDecoder();
+        return new JPEGImageDecoder(premultiplyAlpha);
 
     // BMP
     if (strncmp(contents, "BM", 2) == 0)
-        return new BMPImageDecoder();
+        return new BMPImageDecoder(premultiplyAlpha);
 
     // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
     // CURs begin with 2-byte 0 followed by 2-byte 2.
     if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4))
-        return new ICOImageDecoder();
+        return new ICOImageDecoder(premultiplyAlpha);
 
     // Give up. We don't know what the heck this is.
     return 0;
@@ -94,6 +94,7 @@ RGBA32Buffer::RGBA32Buffer()
     , m_status(FrameEmpty)
     , m_duration(0)
     , m_disposalMethod(DisposeNotSpecified)
+    , m_premultiplyAlpha(true)
 {
 } 
 
@@ -107,6 +108,7 @@ RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other)
     setStatus(other.status());
     setDuration(other.duration());
     setDisposalMethod(other.disposalMethod());
+    setPremultiplyAlpha(other.premultiplyAlpha());
     return *this;
 }
 
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 4b71ce7..38160ec 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -118,12 +118,14 @@ namespace WebCore {
         FrameStatus status() const { return m_status; }
         unsigned duration() const { return m_duration; }
         FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
+        bool premultiplyAlpha() const { return m_premultiplyAlpha; }
 
         void setHasAlpha(bool alpha);
         void setRect(const IntRect& r) { m_rect = r; }
         void setStatus(FrameStatus status);
         void setDuration(unsigned duration) { m_duration = duration; }
         void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
+        void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
 
         inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
         {
@@ -153,11 +155,10 @@ namespace WebCore {
 
         inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
         {
-            // We store this data pre-multiplied.
-            if (a == 0)
+            if (m_premultiplyAlpha && !a)
                 *dest = 0;
             else {
-                if (a < 255) {
+                if (m_premultiplyAlpha && a < 255) {
                     float alphaPercent = a / 255.0f;
                     r = static_cast<unsigned>(r * alphaPercent);
                     g = static_cast<unsigned>(g * alphaPercent);
@@ -192,6 +193,9 @@ namespace WebCore {
         FrameDisposalMethod m_disposalMethod;
                               // What to do with this frame's data when
                               // initializing the next frame.
+        bool m_premultiplyAlpha;
+                              // Whether to premultiply alpha into R, G, B
+                              // channels; by default it's true.
     };
 
     // The ImageDecoder class represents a base class for specific image format
@@ -205,8 +209,9 @@ namespace WebCore {
     // m_maxNumPixels. (Not supported by all image decoders yet)
     class ImageDecoder : public Noncopyable {
     public:
-        ImageDecoder()
+        ImageDecoder(bool premultiplyAlpha)
             : m_scaled(false)
+            , m_premultiplyAlpha(premultiplyAlpha)
             , m_sizeAvailable(false)
             , m_maxNumPixels(-1)
             , m_isAllDataReceived(false)
@@ -219,7 +224,7 @@ namespace WebCore {
         // Factory function to create an ImageDecoder.  Ports that subclass
         // ImageDecoder can provide their own implementation of this to avoid
         // needing to write a dedicated setData() implementation.
-        static ImageDecoder* create(const SharedBuffer& data);
+        static ImageDecoder* create(const SharedBuffer& data, bool premultiplyAlpha);
 
         // The the filename extension usually associated with an undecoded image
         // of this type.
@@ -333,6 +338,7 @@ namespace WebCore {
         bool m_scaled;
         Vector<int> m_scaledColumns;
         Vector<int> m_scaledRows;
+        bool m_premultiplyAlpha;
 
     private:
         // Some code paths compute the size of the image as "width * height * 4"
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
index 901f60d..1c117a8 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -40,8 +40,9 @@ namespace WebCore {
 // don't pack).
 static const size_t sizeOfFileHeader = 14;
 
-BMPImageDecoder::BMPImageDecoder()
-    : m_decodedOffset(0)
+BMPImageDecoder::BMPImageDecoder(bool premultiplyAlpha)
+    : ImageDecoder(premultiplyAlpha)
+    , m_decodedOffset(0)
 {
 }
 
@@ -68,8 +69,10 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index)
     if (index)
         return 0;
 
-    if (m_frameBufferCache.isEmpty())
+    if (m_frameBufferCache.isEmpty()) {
         m_frameBufferCache.resize(1);
+        m_frameBufferCache.first().setPremultiplyAlpha(m_premultiplyAlpha);
+    }
 
     RGBA32Buffer* buffer = &m_frameBufferCache.first();
     if (buffer->status() != RGBA32Buffer::FrameComplete)
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
index b08b32b..3996bf9 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
@@ -39,7 +39,7 @@ namespace WebCore {
     // This class decodes the BMP image format.
     class BMPImageDecoder : public ImageDecoder {
     public:
-        BMPImageDecoder();
+        BMPImageDecoder(bool premultiplyAlpha);
 
         // ImageDecoder
         virtual String filenameExtension() const { return "bmp"; }
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index ec16da7..a2397ee 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -29,8 +29,9 @@
 
 namespace WebCore {
 
-GIFImageDecoder::GIFImageDecoder()
-    : m_alreadyScannedThisDataForFrameCount(true)
+GIFImageDecoder::GIFImageDecoder(bool premultiplyAlpha)
+    : ImageDecoder(premultiplyAlpha)
+    , m_alreadyScannedThisDataForFrameCount(true)
     , m_repetitionCount(cAnimationLoopOnce)
     , m_readOffset(0)
 {
@@ -83,6 +84,8 @@ size_t GIFImageDecoder::frameCount()
         reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1));
         m_alreadyScannedThisDataForFrameCount = true;
         m_frameBufferCache.resize(reader.images_count);
+        for (int i = 0; i < reader.images_count; ++i)
+            m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
     }
 
     return m_frameBufferCache.size();
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index e0f8173..21c1c57 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -36,7 +36,7 @@ namespace WebCore {
     // This class decodes the GIF image format.
     class GIFImageDecoder : public ImageDecoder {
     public:
-        GIFImageDecoder();
+        GIFImageDecoder(bool premultiplyAlpha);
         virtual ~GIFImageDecoder();
 
         enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
index d667795..453efd2 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
@@ -44,8 +44,9 @@ namespace WebCore {
 static const size_t sizeOfDirectory = 6;
 static const size_t sizeOfDirEntry = 16;
 
-ICOImageDecoder::ICOImageDecoder()
-    : m_decodedOffset(0)
+ICOImageDecoder::ICOImageDecoder(bool premultiplyAlpha)
+    : ImageDecoder(premultiplyAlpha)
+    , m_decodedOffset(0)
 {
 }
 
@@ -96,8 +97,11 @@ bool ICOImageDecoder::setSize(unsigned width, unsigned height)
 size_t ICOImageDecoder::frameCount()
 {
     decode(0, true);
-    if (m_frameBufferCache.isEmpty())
+    if (m_frameBufferCache.isEmpty()) {
         m_frameBufferCache.resize(m_dirEntries.size());
+        for (size_t i = 0; i < m_dirEntries.size(); ++i)
+            m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
+    }
     // CAUTION: We must not resize m_frameBufferCache again after this, as
     // decodeAtIndex() may give a BMPImageReader a pointer to one of the
     // entries.
@@ -197,7 +201,7 @@ bool ICOImageDecoder::decodeAtIndex(size_t index)
     }
 
     if (!m_pngDecoders[index]) {
-        m_pngDecoders[index].set(new PNGImageDecoder());
+        m_pngDecoders[index].set(new PNGImageDecoder(m_premultiplyAlpha));
         setDataForPNGDecoderAtIndex(index);
     }
     // Fail if the size the PNGImageDecoder calculated does not match the size
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
index 48024a2..e2ee9e3 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
@@ -40,7 +40,7 @@ namespace WebCore {
     // This class decodes the ICO and CUR image formats.
     class ICOImageDecoder : public ImageDecoder {
     public:
-        ICOImageDecoder();
+        ICOImageDecoder(bool premultiplyAlpha);
         virtual ~ICOImageDecoder();
 
         // ImageDecoder
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 4911bc9..6c6c782 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -361,7 +361,8 @@ void term_source(j_decompress_ptr jd)
     src->decoder->decoder()->jpegComplete();
 }
 
-JPEGImageDecoder::JPEGImageDecoder()
+JPEGImageDecoder::JPEGImageDecoder(bool premultiplyAlpha)
+    : ImageDecoder(premultiplyAlpha)
 {
 }
 
@@ -391,8 +392,10 @@ RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index)
     if (index)
         return 0;
 
-    if (m_frameBufferCache.isEmpty())
+    if (m_frameBufferCache.isEmpty()) {
         m_frameBufferCache.resize(1);
+        m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
+    }
 
     RGBA32Buffer& frame = m_frameBufferCache[0];
     if (frame.status() != RGBA32Buffer::FrameComplete)
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 43b35fd..5047019 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -37,7 +37,7 @@ namespace WebCore {
     // This class decodes the JPEG image format.
     class JPEGImageDecoder : public ImageDecoder {
     public:
-        JPEGImageDecoder();
+        JPEGImageDecoder(bool premultiplyAlpha);
         virtual ~JPEGImageDecoder();
 
         // ImageDecoder
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 8186f33..940e4c4 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -169,8 +169,9 @@ private:
     unsigned m_currentBufferSize;
 };
 
-PNGImageDecoder::PNGImageDecoder()
-    : m_doNothingOnFailure(false)
+PNGImageDecoder::PNGImageDecoder(bool premultiplyAlpha)
+    : ImageDecoder(premultiplyAlpha)
+    , m_doNothingOnFailure(false)
 {
 }
 
@@ -200,8 +201,10 @@ RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index)
     if (index)
         return 0;
 
-    if (m_frameBufferCache.isEmpty())
+    if (m_frameBufferCache.isEmpty()) {
         m_frameBufferCache.resize(1);
+        m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha);
+    }
 
     RGBA32Buffer& frame = m_frameBufferCache[0];
     if (frame.status() != RGBA32Buffer::FrameComplete)
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index 145fc4d..763b88f 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -36,7 +36,7 @@ namespace WebCore {
     // This class decodes the PNG image format.
     class PNGImageDecoder : public ImageDecoder {
     public:
-        PNGImageDecoder();
+        PNGImageDecoder(bool premultiplyAlpha);
         virtual ~PNGImageDecoder();
 
         // ImageDecoder
diff --git a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
index f763a15..149937e 100644
--- a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
+++ b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp
@@ -33,6 +33,7 @@ RGBA32Buffer::RGBA32Buffer()
     : m_status(FrameEmpty)
     , m_duration(0)
     , m_disposalMethod(DisposeNotSpecified)
+    , m_premultiplyAlpha(true)
 {
 }
 
@@ -49,6 +50,7 @@ RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other)
     setStatus(other.status());
     setDuration(other.duration());
     setDisposalMethod(other.disposalMethod());
+    setPremultiplyAlpha(other.premultiplyAlpha());
     return *this;
 }
 
diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog
index 5d860ed..2824511 100644
--- a/WebKit/chromium/ChangeLog
+++ b/WebKit/chromium/ChangeLog
@@ -1,3 +1,13 @@
+2010-08-24  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Passing premultiplyAlpha=false to tex{Sub}Image2D loses information (skia)
+        https://bugs.webkit.org/show_bug.cgi?id=38282
+
+        * src/WebImageDecoder.cpp:
+        (WebKit::WebImageDecoder::init): Add premultiplyAlpha flag.
+
 2010-08-25  Satish Sampath  <satish at chromium.org>
 
         Reviewed by Jeremy Orlow.
diff --git a/WebKit/chromium/src/WebImageDecoder.cpp b/WebKit/chromium/src/WebImageDecoder.cpp
index 9e1d1f4..160deee 100644
--- a/WebKit/chromium/src/WebImageDecoder.cpp
+++ b/WebKit/chromium/src/WebImageDecoder.cpp
@@ -56,10 +56,10 @@ void WebImageDecoder::init(Type type)
 {
     switch (type) {
     case TypeBMP:
-        m_private = new BMPImageDecoder();
+        m_private = new BMPImageDecoder(true);
         break;
     case TypeICO:
-        m_private = new ICOImageDecoder();
+        m_private = new ICOImageDecoder(true);
         break;
     }
 }

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list