| Index: Source/core/platform/graphics/GraphicsContext3D.cpp
|
| diff --git a/Source/core/platform/graphics/GraphicsContext3D.cpp b/Source/core/platform/graphics/GraphicsContext3D.cpp
|
| index 2ff862ed02a5668a21123dbe66b68a5b73d8ec0e..a5deef4c28c874c3b214dc2e70fac0d9ff7f8a8b 100644
|
| --- a/Source/core/platform/graphics/GraphicsContext3D.cpp
|
| +++ b/Source/core/platform/graphics/GraphicsContext3D.cpp
|
| @@ -87,6 +87,7 @@ GraphicsContext3D::GraphicsContext3D(PassOwnPtr<WebKit::WebGraphicsContext3D> we
|
| , m_initializedAvailableExtensions(false)
|
| , m_layerComposited(false)
|
| , m_preserveDrawingBuffer(preserveDrawingBuffer)
|
| + , m_packAlignment(4)
|
| , m_resourceSafety(ResourceSafetyUnknown)
|
| , m_grContext(0)
|
| {
|
| @@ -98,6 +99,7 @@ GraphicsContext3D::GraphicsContext3D(PassOwnPtr<WebKit::WebGraphicsContext3DProv
|
| , m_initializedAvailableExtensions(false)
|
| , m_layerComposited(false)
|
| , m_preserveDrawingBuffer(preserveDrawingBuffer)
|
| + , m_packAlignment(4)
|
| , m_resourceSafety(ResourceSafetyUnknown)
|
| , m_grContext(m_provider->grContext())
|
| {
|
| @@ -500,7 +502,14 @@ DELEGATE_TO_WEBCONTEXT_1R(isShader, Platform3DObject, GC3Dboolean)
|
| DELEGATE_TO_WEBCONTEXT_1R(isTexture, Platform3DObject, GC3Dboolean)
|
| DELEGATE_TO_WEBCONTEXT_1(lineWidth, GC3Dfloat)
|
| DELEGATE_TO_WEBCONTEXT_1(linkProgram, Platform3DObject)
|
| -DELEGATE_TO_WEBCONTEXT_2(pixelStorei, GC3Denum, GC3Dint)
|
| +
|
| +void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
|
| +{
|
| + if (pname == PACK_ALIGNMENT)
|
| + m_packAlignment = param;
|
| + m_impl->pixelStorei(pname, param);
|
| +}
|
| +
|
| DELEGATE_TO_WEBCONTEXT_2(polygonOffset, GC3Dfloat, GC3Dfloat)
|
|
|
| DELEGATE_TO_WEBCONTEXT_7(readPixels, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, void*)
|
| @@ -604,17 +613,43 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(Drawin
|
|
|
| RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
|
| unsigned char* pixels = imageData->data()->data();
|
| - size_t bufferSize = 4 * width * height;
|
|
|
| - m_impl->readBackFramebuffer(pixels, bufferSize, framebufferId, width, height);
|
| + m_impl->bindFramebuffer(FRAMEBUFFER, framebufferId);
|
| + readBackFramebuffer(pixels, width, height, ReadbackRGBA, AlphaDoNothing);
|
| + flipVertically(pixels, width, height);
|
|
|
| + return imageData.release();
|
| +}
|
| +
|
| +void GraphicsContext3D::readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder readbackOrder, AlphaOp op)
|
| +{
|
| + if (m_packAlignment > 4)
|
| + m_impl->pixelStorei(PACK_ALIGNMENT, 1);
|
| + m_impl->readPixels(0, 0, width, height, RGBA, UNSIGNED_BYTE, pixels);
|
| + if (m_packAlignment > 4)
|
| + m_impl->pixelStorei(PACK_ALIGNMENT, m_packAlignment);
|
| +
|
| + size_t bufferSize = 4 * width * height;
|
| +
|
| + if (readbackOrder == ReadbackSkia) {
|
| #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
|
| - // If the implementation swapped the red and blue channels, un-swap them.
|
| - for (size_t i = 0; i < bufferSize; i += 4)
|
| - std::swap(pixels[i], pixels[i + 2]);
|
| + // Swizzle red and blue channels to match SkBitmap's byte ordering.
|
| + // TODO(kbr): expose GL_BGRA as extension.
|
| + for (size_t i = 0; i < bufferSize; i += 4) {
|
| + std::swap(pixels[i], pixels[i + 2]);
|
| + }
|
| #endif
|
| + }
|
|
|
| - return imageData.release();
|
| + if (op == AlphaDoPremultiply) {
|
| + for (size_t i = 0; i < bufferSize; i += 4) {
|
| + pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
|
| + pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
|
| + pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
|
| + }
|
| + } else if (op != AlphaDoNothing) {
|
| + ASSERT_NOT_REACHED();
|
| + }
|
| }
|
|
|
| DELEGATE_TO_WEBCONTEXT_R(createBuffer, Platform3DObject)
|
| @@ -890,7 +925,6 @@ unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format)
|
| void GraphicsContext3D::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer)
|
| {
|
| unsigned char* pixels = 0;
|
| - size_t bufferSize = 4 * width * height;
|
|
|
| const SkBitmap* canvasBitmap = imageBuffer->context()->bitmap();
|
| const SkBitmap* readbackBitmap = 0;
|
| @@ -916,15 +950,9 @@ void GraphicsContext3D::paintFramebufferToCanvas(int framebuffer, int width, int
|
| SkAutoLockPixels bitmapLock(*readbackBitmap);
|
| pixels = static_cast<unsigned char*>(readbackBitmap->getPixels());
|
|
|
| - m_impl->readBackFramebuffer(pixels, 4 * width * height, framebuffer, width, height);
|
| -
|
| - if (premultiplyAlpha) {
|
| - for (size_t i = 0; i < bufferSize; i += 4) {
|
| - pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
|
| - pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
|
| - pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
|
| - }
|
| - }
|
| + m_impl->bindFramebuffer(FRAMEBUFFER, framebuffer);
|
| + readBackFramebuffer(pixels, width, height, ReadbackSkia, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing);
|
| + flipVertically(pixels, width, height);
|
|
|
| readbackBitmap->notifyPixelsChanged();
|
| if (m_resizingBitmap.readyToDraw()) {
|
| @@ -1009,4 +1037,19 @@ bool GraphicsContext3D::isExtensionEnabled(const String& name)
|
| return m_enabledExtensions.contains(mappedName);
|
| }
|
|
|
| +void GraphicsContext3D::flipVertically(uint8_t* framebuffer, int width, int height)
|
| +{
|
| + m_scanline.resize(width * 4);
|
| + uint8* scanline = &m_scanline[0];
|
| + unsigned rowBytes = width * 4;
|
| + unsigned count = height / 2;
|
| + for (unsigned i = 0; i < count; i++) {
|
| + uint8* rowA = framebuffer + i * rowBytes;
|
| + uint8* rowB = framebuffer + (height - i - 1) * rowBytes;
|
| + memcpy(scanline, rowB, rowBytes);
|
| + memcpy(rowB, rowA, rowBytes);
|
| + memcpy(rowA, scanline, rowBytes);
|
| + }
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|