|
Lines 44-65
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec1
|
| 44 |
#include <wtf/text/Base64.h> |
44 |
#include <wtf/text/Base64.h> |
| 45 |
#include <wtf/text/WTFString.h> |
45 |
#include <wtf/text/WTFString.h> |
| 46 |
|
46 |
|
|
|
47 |
#if ENABLE(ACCELERATED_2D_CANVAS) |
| 48 |
#include "GLContext.h" |
| 49 |
#include "OpenGLShims.h" |
| 50 |
#include "TextureMapperGL.h" |
| 51 |
#include <cairo-gl.h> |
| 52 |
#endif |
| 53 |
|
| 47 |
using namespace std; |
54 |
using namespace std; |
| 48 |
|
55 |
|
| 49 |
namespace WebCore { |
56 |
namespace WebCore { |
| 50 |
|
57 |
|
| 51 |
ImageBufferData::ImageBufferData(const IntSize&) |
58 |
ImageBufferData::ImageBufferData(const IntSize& size) |
| 52 |
: m_platformContext(0) |
59 |
: m_platformContext(0) |
|
|
60 |
, m_size(size) |
| 61 |
#if ENABLE(ACCELERATED_2D_CANVAS) |
| 62 |
, m_texture(0) |
| 63 |
#endif |
| 53 |
{ |
64 |
{ |
| 54 |
} |
65 |
} |
| 55 |
|
66 |
|
| 56 |
ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, bool& success) |
67 |
#if ENABLE(ACCELERATED_2D_CANVAS) |
|
|
68 |
PassRefPtr<cairo_surface_t> createCairoGLSurface(const IntSize& size, uint32_t& texture) |
| 69 |
{ |
| 70 |
GLContext::sharingContext()->makeContextCurrent(); |
| 71 |
|
| 72 |
// We must generate the texture ourselves, because there is no Cairo API for extracting it |
| 73 |
// from a pre-existing surface. |
| 74 |
glGenTextures(1, &texture); |
| 75 |
glBindTexture(GL_TEXTURE_2D, texture); |
| 76 |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); |
| 77 |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); |
| 78 |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 79 |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 80 |
|
| 81 |
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 82 |
|
| 83 |
glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, size.width(), size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| 84 |
|
| 85 |
GLContext* context = GLContext::sharingContext(); |
| 86 |
cairo_device_t* device = context->cairoDevice(); |
| 87 |
|
| 88 |
// Thread-awareness is a huge performance hit on non-Intel drivers. |
| 89 |
cairo_gl_device_set_thread_aware(device, FALSE); |
| 90 |
|
| 91 |
return adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, texture, size.width(), size.height())); |
| 92 |
} |
| 93 |
#endif |
| 94 |
|
| 95 |
ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode renderingMode, bool& success) |
| 57 |
: m_data(size) |
96 |
: m_data(size) |
| 58 |
, m_size(size) |
97 |
, m_size(size) |
| 59 |
, m_logicalSize(size) |
98 |
, m_logicalSize(size) |
| 60 |
{ |
99 |
{ |
| 61 |
success = false; // Make early return mean error. |
100 |
success = false; // Make early return mean error. |
| 62 |
m_data.m_surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height())); |
101 |
|
|
|
102 |
#if ENABLE(ACCELERATED_2D_CANVAS) |
| 103 |
if (renderingMode == Accelerated) |
| 104 |
m_data.m_surface = createCairoGLSurface(size, m_data.m_texture); |
| 105 |
else |
| 106 |
#endif |
| 107 |
m_data.m_surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height())); |
| 108 |
|
| 63 |
if (cairo_surface_status(m_data.m_surface.get()) != CAIRO_STATUS_SUCCESS) |
109 |
if (cairo_surface_status(m_data.m_surface.get()) != CAIRO_STATUS_SUCCESS) |
| 64 |
return; // create will notice we didn't set m_initialized and fail. |
110 |
return; // create will notice we didn't set m_initialized and fail. |
| 65 |
|
111 |
|
|
Lines 114-120
void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec2
|
| 114 |
|
160 |
|
| 115 |
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) |
161 |
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) |
| 116 |
{ |
162 |
{ |
| 117 |
ASSERT(cairo_surface_get_type(m_data.m_surface.get()) == CAIRO_SURFACE_TYPE_IMAGE); |
163 |
// FIXME: Enable color space conversions on accelerated canvases. |
|
|
164 |
if (cairo_surface_get_type(m_data.m_surface.get()) != CAIRO_SURFACE_TYPE_IMAGE) |
| 165 |
return; |
| 118 |
|
166 |
|
| 119 |
unsigned char* dataSrc = cairo_image_surface_get_data(m_data.m_surface.get()); |
167 |
unsigned char* dataSrc = cairo_image_surface_get_data(m_data.m_surface.get()); |
| 120 |
int stride = cairo_image_surface_get_stride(m_data.m_surface.get()); |
168 |
int stride = cairo_image_surface_get_stride(m_data.m_surface.get()); |
|
Lines 133-145
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec3
|
| 133 |
cairo_surface_mark_dirty_rectangle(m_data.m_surface.get(), 0, 0, m_size.width(), m_size.height()); |
181 |
cairo_surface_mark_dirty_rectangle(m_data.m_surface.get(), 0, 0, m_size.width(), m_size.height()); |
| 134 |
} |
182 |
} |
| 135 |
|
183 |
|
|
|
184 |
static cairo_surface_t* mapSurfaceToImage(cairo_surface_t* surface, const IntSize& size) |
| 185 |
{ |
| 186 |
if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) |
| 187 |
return surface; |
| 188 |
|
| 189 |
cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()); |
| 190 |
RefPtr<cairo_t> cr = adoptRef(cairo_create(imageSurface)); |
| 191 |
cairo_set_source_surface(cr.get(), surface, 0, 0); |
| 192 |
cairo_paint(cr.get()); |
| 193 |
return imageSurface; |
| 194 |
} |
| 195 |
|
| 196 |
static void unmapSurfaceFromImage(cairo_surface_t* surface, cairo_surface_t* imageSurface, const IntRect& dirtyRectangle = IntRect()) |
| 197 |
{ |
| 198 |
if (surface == imageSurface && dirtyRectangle.isEmpty()) |
| 199 |
return; |
| 200 |
|
| 201 |
if (dirtyRectangle.isEmpty()) { |
| 202 |
cairo_surface_destroy(imageSurface); |
| 203 |
return; |
| 204 |
} |
| 205 |
|
| 206 |
if (surface == imageSurface) { |
| 207 |
cairo_surface_mark_dirty_rectangle(surface, dirtyRectangle.x(), dirtyRectangle.y(), dirtyRectangle.width(), dirtyRectangle.height()); |
| 208 |
return; |
| 209 |
} |
| 210 |
|
| 211 |
RefPtr<cairo_t> cr = adoptRef(cairo_create(surface)); |
| 212 |
cairo_set_source_surface(cr.get(), imageSurface, 0, 0); |
| 213 |
cairo_rectangle(cr.get(), dirtyRectangle.x(), dirtyRectangle.y(), dirtyRectangle.width(), dirtyRectangle.height()); |
| 214 |
cairo_fill(cr.get()); |
| 215 |
cairo_surface_destroy(imageSurface); |
| 216 |
} |
| 217 |
|
| 136 |
template <Multiply multiplied> |
218 |
template <Multiply multiplied> |
| 137 |
PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size) |
219 |
PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size) |
| 138 |
{ |
220 |
{ |
| 139 |
ASSERT(cairo_surface_get_type(data.m_surface.get()) == CAIRO_SURFACE_TYPE_IMAGE); |
|
|
| 140 |
|
| 141 |
RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); |
221 |
RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); |
| 142 |
unsigned char* dataSrc = cairo_image_surface_get_data(data.m_surface.get()); |
222 |
cairo_surface_t* imageSurface = mapSurfaceToImage(data.m_surface.get(), size); |
|
|
223 |
unsigned char* dataSrc = cairo_image_surface_get_data(imageSurface); |
| 143 |
unsigned char* dataDst = result->data(); |
224 |
unsigned char* dataDst = result->data(); |
| 144 |
|
225 |
|
| 145 |
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height()) |
226 |
if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height()) |
|
Lines 167-173
PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec4
|
| 167 |
endy = size.height(); |
248 |
endy = size.height(); |
| 168 |
int numRows = endy - originy; |
249 |
int numRows = endy - originy; |
| 169 |
|
250 |
|
| 170 |
int stride = cairo_image_surface_get_stride(data.m_surface.get()); |
251 |
int stride = cairo_image_surface_get_stride(imageSurface); |
| 171 |
unsigned destBytesPerRow = 4 * rect.width(); |
252 |
unsigned destBytesPerRow = 4 * rect.width(); |
| 172 |
|
253 |
|
| 173 |
unsigned char* destRows = dataDst + desty * destBytesPerRow + destx * 4; |
254 |
unsigned char* destRows = dataDst + desty * destBytesPerRow + destx * 4; |
|
Lines 200-205
PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec5
|
| 200 |
destRows += destBytesPerRow; |
281 |
destRows += destBytesPerRow; |
| 201 |
} |
282 |
} |
| 202 |
|
283 |
|
|
|
284 |
unmapSurfaceFromImage(data.m_surface.get(), imageSurface); |
| 203 |
return result.release(); |
285 |
return result.release(); |
| 204 |
} |
286 |
} |
| 205 |
|
287 |
|
|
Lines 215-223
PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec6
|
| 215 |
|
297 |
|
| 216 |
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) |
298 |
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) |
| 217 |
{ |
299 |
{ |
| 218 |
ASSERT(cairo_surface_get_type(m_data.m_surface.get()) == CAIRO_SURFACE_TYPE_IMAGE); |
300 |
cairo_surface_t* imageSurface = mapSurfaceToImage(m_data.m_surface.get(), sourceSize); |
| 219 |
|
301 |
unsigned char* dataDst = cairo_image_surface_get_data(imageSurface); |
| 220 |
unsigned char* dataDst = cairo_image_surface_get_data(m_data.m_surface.get()); |
|
|
| 221 |
|
302 |
|
| 222 |
ASSERT(sourceRect.width() > 0); |
303 |
ASSERT(sourceRect.width() > 0); |
| 223 |
ASSERT(sourceRect.height() > 0); |
304 |
ASSERT(sourceRect.height() > 0); |
|
Lines 246-252
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec7
|
| 246 |
int numRows = endy - desty; |
327 |
int numRows = endy - desty; |
| 247 |
|
328 |
|
| 248 |
unsigned srcBytesPerRow = 4 * sourceSize.width(); |
329 |
unsigned srcBytesPerRow = 4 * sourceSize.width(); |
| 249 |
int stride = cairo_image_surface_get_stride(m_data.m_surface.get()); |
330 |
int stride = cairo_image_surface_get_stride(imageSurface); |
| 250 |
|
331 |
|
| 251 |
unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; |
332 |
unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; |
| 252 |
for (int y = 0; y < numRows; ++y) { |
333 |
for (int y = 0; y < numRows; ++y) { |
|
Lines 274-280
void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec8
|
| 274 |
} |
355 |
} |
| 275 |
srcRows += srcBytesPerRow; |
356 |
srcRows += srcBytesPerRow; |
| 276 |
} |
357 |
} |
| 277 |
cairo_surface_mark_dirty_rectangle(m_data.m_surface.get(), destx, desty, numColumns, numRows); |
358 |
|
|
|
359 |
unmapSurfaceFromImage(m_data.m_surface.get(), imageSurface, IntRect(destx, desty, numColumns, numRows)); |
| 278 |
} |
360 |
} |
| 279 |
|
361 |
|
| 280 |
#if !PLATFORM(GTK) |
362 |
#if !PLATFORM(GTK) |
|
Lines 309-312
String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateS
a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp_sec9
|
| 309 |
} |
391 |
} |
| 310 |
#endif |
392 |
#endif |
| 311 |
|
393 |
|
|
|
394 |
#if ENABLE(ACCELERATED_2D_CANVAS) |
| 395 |
void ImageBufferData::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity) |
| 396 |
{ |
| 397 |
if (textureMapper->accelerationMode() != TextureMapper::OpenGLMode) { |
| 398 |
notImplemented(); |
| 399 |
return; |
| 400 |
} |
| 401 |
|
| 402 |
ASSERT(m_texture); |
| 403 |
|
| 404 |
// Cairo may change the active context, so we make sure to change it back after flushing. |
| 405 |
GLContext* previousActiveContext = GLContext::getCurrent(); |
| 406 |
cairo_surface_flush(m_surface.get()); |
| 407 |
previousActiveContext->makeContextCurrent(); |
| 408 |
|
| 409 |
static_cast<TextureMapperGL*>(textureMapper)->drawTexture(m_texture, TextureMapperGL::ShouldBlend, m_size, targetRect, matrix, opacity); |
| 410 |
} |
| 411 |
#endif |
| 412 |
|
| 413 |
PlatformLayer* ImageBuffer::platformLayer() const |
| 414 |
{ |
| 415 |
#if ENABLE(ACCELERATED_2D_CANVAS) |
| 416 |
if (m_data.m_texture) |
| 417 |
return const_cast<ImageBufferData*>(&m_data); |
| 418 |
#endif |
| 419 |
return 0; |
| 420 |
} |
| 421 |
|
| 312 |
} // namespace WebCore |
422 |
} // namespace WebCore |