Changeset 83949 in webkit
- Timestamp:
- Apr 14, 2011 10:43:27 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r83948 r83949 1 2011-04-14 Justin Novosad <junov@chromium.org> 2 3 Reviewed by Kenneth Russell. 4 5 [Chromium] Accelerated 2D Canvas is slow to execute putImageData 6 https://bugs.webkit.org/show_bug.cgi?id=57960 7 8 * platform/chromium/test_expectations.txt: 9 added expected failure for test 10 canvas/philip/tests/2d.gradient.interpolate.colouralpha.html 11 Logged as chromium issue: 12 http://code.google.com/p/chromium/issues/detail?id=79477 13 1 14 2011-04-14 Adrienne Walker <enne@google.com> 2 15 -
trunk/LayoutTests/platform/chromium/test_expectations.txt
r83948 r83949 699 699 // selection 700 700 BUGCR10369 LINUX : editing/selection/5354455-2.html = FAIL 701 702 BUGCR79477 LINUX WIN : canvas/philip/tests/2d.gradient.interpolate.colouralpha.html = TEXT 701 703 702 704 // TODO(erg): Attempted to rebaseline these tests as part of the above -
trunk/Source/WebCore/ChangeLog
r83945 r83949 1 2011-04-14 Justin Novosad <junov@chromium.org> 2 3 Reviewed by Kenneth Russell. 4 5 [Chromium] Accelerated 2D Canvas is slow to execute putImageData 6 https://bugs.webkit.org/show_bug.cgi?id=57960 7 8 * platform/graphics/chromium/GLES2Canvas.cpp: 9 (WebCore::GLES2Canvas::drawTexturedRect): 10 Added an option for using the blend ops for alpha multiplication 11 instead of compositing. 12 (WebCore::GLES2Canvas::applyClipping): 13 (WebCore::GLES2Canvas::putImageData): 14 New method for drawing raw pixel data from memory to the canvas 15 (WebCore::GLES2Canvas::putUnmultipliedImageData): 16 Wrapper for putImageData 17 (WebCore::GLES2Canvas::putPremultipliedImageData): 18 Wrapper for putImageData 19 * platform/graphics/chromium/GLES2Canvas.h: 20 * platform/graphics/gpu/Texture.cpp: 21 (WebCore::copySubRect): 22 (WebCore::Texture::load): 23 (WebCore::Texture::updateSubRect): 24 Added an overload of the updateSubRect method that can receive a pixel 25 of a size that is different from texture size. Improved the performance 26 of updateSubrect by avoiding the allocation of a temporary buffer when 27 not required. 28 * platform/graphics/gpu/Texture.h: 29 * platform/graphics/skia/ImageBufferSkia.cpp: 30 (WebCore::getImageData): 31 In the unmultiplied path, division by alpha now performs proper 32 rounding in order to avoid generational degradation with putImageData 33 (WebCore::putImageData): 34 Alpha multiplication now performs proper rounding in order to be 35 consistent with the hardware rendering path: OpenGL always rounds when 36 converting to fixed point representation. 37 (WebCore::ImageBuffer::putUnmultipliedImageData): 38 Now supports a hardware rendering path, which eliminates the need 39 for a readback from the GPU 40 (WebCore::ImageBuffer::putPremultipliedImageData): 41 Now supports a hardware rendering path, which eliminates the need 42 for a readback from the GPU 43 1 44 2011-04-14 Joone Hur <joone.hur@collabora.co.uk> 2 45 -
trunk/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
r82614 r83949 33 33 #include "GLES2Canvas.h" 34 34 35 #include "ByteArray.h" 35 36 #include "DrawingBuffer.h" 36 37 #include "FloatRect.h" … … 58 59 namespace WebCore { 59 60 61 using WTF::ByteArray; 62 60 63 // Number of line segments used to approximate bezier curves. 61 64 const int pathTesselation = 30; … … 407 410 void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) 408 411 { 409 drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->clippingEnabled()); 410 } 411 412 413 void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, bool clip) 412 drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp, m_state->clippingEnabled() ? ApplyClipping : 0); 413 } 414 415 void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp, unsigned drawTextureFlags) 414 416 { 415 417 bindFramebuffer(); 416 m_context->applyCompositeOperator(compositeOp); 417 applyClipping(clip); 418 419 if (drawTextureFlags & MultiplySourceAlpha) { 420 // The multiply option hijacks the blend func, so it can't be combined with a compositing op 421 ASSERT(CompositeCopy == compositeOp); 422 // Custom composite operation that performs alpha multiplication on color components 423 m_context->graphicsContext3D()->enable(GraphicsContext3D::BLEND); 424 m_context->graphicsContext3D()->blendFuncSeparate(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ZERO, GraphicsContext3D::ONE, GraphicsContext3D::ZERO); 425 } else 426 m_context->applyCompositeOperator(compositeOp); 427 applyClipping(drawTextureFlags & ApplyClipping); 418 428 const TilingData& tiles = texture->tiles(); 419 429 IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); … … 904 914 } 905 915 916 void GLES2Canvas::putImageData(void* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, Texture::Format format, float alpha, ColorSpace colorSpace, CompositeOperator op, unsigned drawTextureFlags) 917 { 918 ASSERT(source); 919 IntRect clippedSourceRect(0, 0, sourceSize.width(), sourceSize.height()); 920 clippedSourceRect.intersect(sourceRect); 921 int deltaX = clippedSourceRect.x() - sourceRect.x(); 922 int deltaY = clippedSourceRect.y() - sourceRect.y(); 923 IntPoint adjustedDestPoint(destPoint.x() + deltaX, destPoint.y() + deltaY); 924 IntRect destRect(adjustedDestPoint, clippedSourceRect.size()); 925 IntRect canvasRect(0, 0, m_size.width(), m_size.height()); 926 destRect.intersect(canvasRect); 927 deltaX = destRect.x() - adjustedDestPoint.x(); 928 deltaY = destRect.y() - adjustedDestPoint.y(); 929 clippedSourceRect.move(deltaX, deltaY); 930 clippedSourceRect.setSize(destRect.size()); 931 if (!clippedSourceRect.width() || !clippedSourceRect.height()) 932 return; 933 RefPtr<Texture> uploadTexture = m_context->createTexture(format, clippedSourceRect.width(), clippedSourceRect.height()); 934 IntRect texUpdateRect(0, 0, clippedSourceRect.width(), clippedSourceRect.height()); 935 // To get the row stride right, we still take the width of the full buffer for the source size. 936 IntSize adjustedSourceSize(sourceSize.width(), texUpdateRect.height()); 937 uploadTexture->updateSubRect(((char*)source) + (clippedSourceRect.y() * sourceSize.width() + clippedSourceRect.x()) * 4, adjustedSourceSize, texUpdateRect); 938 AffineTransform identity; 939 drawTexturedRect(uploadTexture.get(), texUpdateRect, destRect, identity, alpha, colorSpace, op, drawTextureFlags); 940 } 941 942 void GLES2Canvas::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 943 { 944 IntPoint newDestPoint(destPoint.x() + sourceRect.x(), destPoint.y() + sourceRect.y()); 945 putImageData(source->data(), sourceSize, sourceRect, newDestPoint, Texture::RGBA8, 1.0f, ColorSpaceDeviceRGB, CompositeCopy, MultiplySourceAlpha); 946 } 947 948 void GLES2Canvas::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 949 { 950 IntPoint newDestPoint(destPoint.x() + sourceRect.x(), destPoint.y() + sourceRect.y()); 951 putImageData(source->data(), sourceSize, sourceRect, newDestPoint, Texture::RGBA8, 1.0f, ColorSpaceDeviceRGB, CompositeCopy, 0); 952 } 953 906 954 void GLES2Canvas::checkGLError(const char* header) 907 955 { -
trunk/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
r82614 r83949 44 44 #include <wtf/Vector.h> 45 45 46 namespace WTF { 47 class ByteArray; 48 } 49 46 50 namespace WebCore { 47 51 … … 56 60 WTF_MAKE_NONCOPYABLE(GLES2Canvas); 57 61 public: 62 enum DrawTextureFlags { 63 ApplyClipping = 1 << 0, 64 MultiplySourceAlpha = 1 << 1 65 }; 66 58 67 GLES2Canvas(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&); 59 68 ~GLES2Canvas(); … … 89 98 // This version is called by BitmapImage::draw(). 90 99 void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator); 91 // This version is called by the above, and by the software->hardware uploads.92 void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator, bool clip);100 // This version is called by the above, by putImageData, and by the software->hardware uploads. 101 void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator, unsigned drawTextureFlags); 93 102 Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height); 94 103 Texture* getTexture(NativeImagePtr); 104 void putImageData(void* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, Texture::Format, float alpha, ColorSpace, CompositeOperator, unsigned drawTextureFlags); 105 void putUnmultipliedImageData(WTF::ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint); 106 void putPremultipliedImageData(WTF::ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint); 95 107 96 108 SharedGraphicsContext3D* context() const { return m_context; } -
trunk/Source/WebCore/platform/graphics/gpu/Texture.cpp
r77785 r83949 121 121 122 122 template <bool swizzle> 123 static uint32_t*copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, int width, int height, int srcStride)123 static void copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, int width, int height, int srcStride) 124 124 { 125 125 uint32_t* srcOffset = src + srcX + srcY * srcStride; 126 127 if (!swizzle && width == srcStride)128 return srcOffset;129 130 126 if (swizzle) { 131 127 uint32_t* dstPixel = dst; … … 142 138 } 143 139 } 144 return dst;145 140 } 146 141 147 142 void Texture::load(void* pixels) 148 143 { 149 updateSubRect(pixels, Int Rect(0, 0, m_tiles.totalSizeX(), m_tiles.totalSizeY()));144 updateSubRect(pixels, IntSize(m_tiles.totalSizeX(), m_tiles.totalSizeY()), IntRect(0, 0, m_tiles.totalSizeX(), m_tiles.totalSizeY())); 150 145 } 151 146 152 147 void Texture::updateSubRect(void* pixels, const IntRect& updateRect) 153 148 { 149 updateSubRect(pixels, IntSize(m_tiles.totalSizeX(), m_tiles.totalSizeY()), updateRect); 150 } 151 152 void Texture::updateSubRect(void* pixels, const IntSize& pixelBufferSize, const IntRect& updateRect) 153 { 154 IntSize updateBounds = pixelBufferSize.shrunkTo(IntSize(m_tiles.totalSizeX(), m_tiles.totalSizeY())); 154 155 IntRect updateRectSanitized(updateRect); 155 updateRectSanitized.intersect(IntRect(0, 0, m_tiles.totalSizeX(), m_tiles.totalSizeY()));156 updateRectSanitized.intersect(IntRect(0, 0, updateBounds.width(), updateBounds.height())); 156 157 157 158 uint32_t* pixels32 = static_cast<uint32_t*>(pixels); … … 164 165 // FIXME: This could use PBO's to save doing an extra copy here. 165 166 } 167 166 168 int tempBuffSize = // Temporary buffer size is the smaller of the max texture size or the updateRectSanitized 167 169 min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.width()) * 168 170 min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.height()); 169 OwnArrayPtr<uint32_t> tempBuff = adoptArrayPtr(new uint32_t[tempBuffSize]); 171 bool needTempBuff = swizzle || updateRect.width() != m_tiles.totalSizeX() || updateRect.width() != pixelBufferSize.width() || m_tiles.numTilesX() > 1; 172 OwnArrayPtr<uint32_t> tempBuff; 173 if (needTempBuff) 174 tempBuff = adoptArrayPtr(new uint32_t[tempBuffSize]); 170 175 171 176 for (int tile = 0; tile < m_tiles.numTiles(); tile++) { … … 182 187 continue; 183 188 184 // Copy sub rectangle out of larger pixel data185 189 uint32_t* uploadBuff = 0; 186 if (swizzle) { 187 uploadBuff = copySubRect<true>( 188 pixels32, updateRectIntersected.x(), updateRectIntersected.y(), 189 tempBuff.get(), updateRectIntersected.width(), updateRectIntersected.height(), m_tiles.totalSizeX()); 190 if (needTempBuff) { 191 uploadBuff = tempBuff.get(); 192 // Copy sub rectangle out of larger pixel data 193 if (swizzle) { 194 copySubRect<true>( 195 pixels32, updateRectIntersected.x(), updateRectIntersected.y(), 196 uploadBuff, updateRectIntersected.width(), updateRectIntersected.height(), pixelBufferSize.width()); 197 } else { 198 copySubRect<false>( 199 pixels32, updateRectIntersected.x(), updateRectIntersected.y(), 200 uploadBuff, updateRectIntersected.width(), updateRectIntersected.height(), pixelBufferSize.width()); 201 } 190 202 } else { 191 uploadBuff = copySubRect<false>( 192 pixels32, updateRectIntersected.x(), updateRectIntersected.y(), 193 tempBuff.get(), updateRectIntersected.width(), updateRectIntersected.height(), m_tiles.totalSizeX()); 203 uploadBuff = pixels32 + updateRectIntersected.x() + updateRectIntersected.y() * pixelBufferSize.width(); 194 204 } 195 205 -
trunk/Source/WebCore/platform/graphics/gpu/Texture.h
r73831 r83949 43 43 44 44 class IntRect; 45 class IntSize; 45 46 46 47 class Texture : public RefCounted<Texture> { … … 52 53 void load(void* pixels); 53 54 void updateSubRect(void* pixels, const IntRect&); 55 void updateSubRect(void* pixels, const IntSize&, const IntRect&); 54 56 Format format() const { return m_format; } 55 57 const TilingData& tiles() const { return m_tiles; } -
trunk/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
r83941 r83949 232 232 if (multiplied == Unmultiplied) { 233 233 unsigned char a = SkGetPackedA32(srcPMColor); 234 destPixel[0] = a ? SkGetPackedR32(srcPMColor) * 255 / a : 0; 235 destPixel[1] = a ? SkGetPackedG32(srcPMColor) * 255 / a : 0; 236 destPixel[2] = a ? SkGetPackedB32(srcPMColor) * 255 / a : 0; 234 unsigned char halfA = a >> 1; 235 destPixel[0] = a ? (SkGetPackedR32(srcPMColor) * 255 + halfA) / a : 0; 236 destPixel[1] = a ? (SkGetPackedG32(srcPMColor) * 255 + halfA) / a : 0; 237 destPixel[2] = a ? (SkGetPackedB32(srcPMColor) * 255 + halfA) / a : 0; 237 238 destPixel[3] = a; 238 239 } else { … … 318 319 if (multiplied == Unmultiplied) { 319 320 unsigned char alpha = srcPixel[3]; 320 unsigned char r = SkMulDiv255 Ceiling(srcPixel[0], alpha);321 unsigned char g = SkMulDiv255 Ceiling(srcPixel[1], alpha);322 unsigned char b = SkMulDiv255 Ceiling(srcPixel[2], alpha);321 unsigned char r = SkMulDiv255Round(srcPixel[0], alpha); 322 unsigned char g = SkMulDiv255Round(srcPixel[1], alpha); 323 unsigned char b = SkMulDiv255Round(srcPixel[2], alpha); 323 324 destRow[x] = SkPackARGB32(alpha, r, g, b); 324 325 } else … … 335 336 void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 336 337 { 337 context()->platformContext()->syncSoftwareCanvas(); 338 putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size); 338 PlatformContextSkia* platformContext = context()->platformContext(); 339 if (platformContext->useGPU()) { 340 platformContext->prepareForHardwareDraw(); 341 platformContext->gpuCanvas()->putUnmultipliedImageData(source, sourceSize, sourceRect, destPoint); 342 return; 343 } 344 putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, platformContext->canvas()->getDevice(), m_size); 339 345 } 340 346 341 347 void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) 342 348 { 343 context()->platformContext()->syncSoftwareCanvas(); 349 PlatformContextSkia* platformContext = context()->platformContext(); 350 if (platformContext->useGPU()) { 351 platformContext->prepareForHardwareDraw(); 352 platformContext->gpuCanvas()->putPremultipliedImageData(source, sourceSize, sourceRect, destPoint); 353 return; 354 } 344 355 putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size); 345 356 }
Note: See TracChangeset
for help on using the changeset viewer.