12daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch/* 22daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved. 32daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Copyright (C) 2010 Google Inc. All rights reserved. 42daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Copyright (C) 2011 Igalia S.L. 52daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 62daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Redistribution and use in source and binary forms, with or without 72daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * modification, are permitted provided that the following conditions 82daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * are met: 92daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 1. Redistributions of source code must retain the above copyright 102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * notice, this list of conditions and the following disclaimer. 112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright 122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * notice, this list of conditions and the following disclaimer in the 132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * documentation and/or other materials provided with the distribution. 142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch */ 272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "config.h" 292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "GraphicsContext3D.h" 302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "PlatformContextCairo.h" 312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if ENABLE(WEBGL) 332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "Image.h" 352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "RefPtrCairo.h" 362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <cairo.h> 372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <wtf/PassOwnPtr.h> 382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochnamespace WebCore { 402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) 422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!image) 442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // We need this to stay in scope because the native image is just a shallow copy of the data. 462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ImageSource decoder(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, 472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); 482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch AlphaOp alphaOp = AlphaDoNothing; 492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch RefPtr<cairo_surface_t> imageSurface; 502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (image->data()) { 512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch decoder.setData(image->data(), true); 522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) 532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch imageSurface = decoder.createFrameAtIndex(0); 552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } else { 562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch imageSurface = image->nativeImageForCurrentFrame(); 572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!premultiplyAlpha) 582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch alphaOp = AlphaDoUnmultiply; 592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!imageSurface) 622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch int width = cairo_image_surface_get_width(imageSurface.get()); 652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch int height = cairo_image_surface_get_height(imageSurface.get()); 662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!width || !height) 672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (cairo_image_surface_get_format(imageSurface.get()) != CAIRO_FORMAT_ARGB32) 702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return false; 712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch unsigned int srcUnpackAlignment = 1; 732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch size_t bytesPerRow = cairo_image_surface_get_stride(imageSurface.get()); 742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch size_t bitsPerPixel = 32; 752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch unsigned int padding = bytesPerRow - bitsPerPixel / 8 * width; 762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (padding) { 772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch srcUnpackAlignment = padding + 1; 782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch while (bytesPerRow % srcUnpackAlignment) 792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch ++srcUnpackAlignment; 802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch outputVector.resize(width * height * 4); 832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return packPixels(cairo_image_surface_get_data(imageSurface.get()), SourceFormatBGRA8, 842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch width, height, srcUnpackAlignment, format, type, alphaOp, outputVector.data()); 852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context) 882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context) 902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return; 912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_t *cr = context->cr(); 932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch context->save(); 942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight); 962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); 972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_paint(cr); 982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data( 1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4)); 1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // OpenGL keeps the pixels stored bottom up, so we need to flip the image here. 1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_translate(cr, 0, imageHeight); 1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_scale(cr, 1, -1); 1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_set_operator(cr, CAIRO_OPERATOR_OVER); 1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_set_source_surface(cr, imageSurface.get(), 0, 0); 1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_rectangle(cr, 0, 0, canvasWidth, -canvasHeight); 1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch cairo_fill(cr); 1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch context->restore(); 1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) 1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} // namespace WebCore 1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif // ENABLE(WEBGL) 121