|
5 | 5 |
|
6 | 6 | #include "GLContextEGL.h" |
7 | 7 | #include "PixelBuffer.h" |
| 8 | +#include "PixelBufferConversion.h" |
8 | 9 | #include "TextureMapperPlatformLayerBuffer.h" |
9 | 10 | #include "TextureMapperPlatformLayerProxyGL.h" |
10 | 11 | #include <cairo-gl.h> |
@@ -246,17 +247,43 @@ RefPtr<PixelBuffer> ImageBufferCairoGLSurfaceBackend::getPixelBuffer(const Pixel |
246 | 247 |
|
247 | 248 | void ImageBufferCairoGLSurfaceBackend::putPixelBuffer(const PixelBuffer& pixelBuffer, const IntRect& srcRect, const IntPoint& destPoint, AlphaPremultiplication destFormat) |
248 | 249 | { |
249 | | - // Create a new image surface and put the data there. Then copy its contents to the original gl surface in the specified rect. |
250 | | - auto surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, cairo_gl_surface_get_width(m_surfaces[0].get()), cairo_gl_surface_get_height(m_surfaces[0].get()))); |
251 | | - IntRect srcRectScaled = toBackendCoordinates(srcRect); |
252 | | - IntPoint destPointScaled = toBackendCoordinates(destPoint); |
253 | | - ImageBufferBackend::putPixelBuffer(pixelBuffer, srcRect, destPoint, destFormat, cairo_image_surface_get_data(surface.get())); |
254 | | - cairo_surface_mark_dirty_rectangle(surface.get(), destPointScaled.x(), destPointScaled.y(), srcRectScaled.width(), srcRectScaled.height()); |
| 250 | + auto sourceRectClipped = intersection({ IntPoint::zero(), pixelBuffer.size() }, srcRect); |
| 251 | + auto destinationRect = sourceRectClipped; |
| 252 | + destinationRect.moveBy(destPoint); |
| 253 | + |
| 254 | + if (srcRect.x() < 0) |
| 255 | + destinationRect.setX(destinationRect.x() - srcRect.x()); |
| 256 | + |
| 257 | + if (srcRect.y() < 0) |
| 258 | + destinationRect.setY(destinationRect.y() - srcRect.y()); |
| 259 | + |
| 260 | + destinationRect.intersect(backendRect()); |
| 261 | + sourceRectClipped.setSize(destinationRect.size()); |
| 262 | + |
| 263 | + // Create an intermediate surface with the size of the rectangle that we need to copy. Then we can use convertImagePixels |
| 264 | + // to properly convert and copy the relevant pixels into this intermediate surface. Once this is done, use cairo to paint the |
| 265 | + // intermediate surface into the buffer surface in the appropriate position. |
| 266 | + auto surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, destinationRect.width(), destinationRect.height())); |
| 267 | + |
| 268 | + ConstPixelBufferConversionView source { |
| 269 | + pixelBuffer.format(), |
| 270 | + static_cast<unsigned>(4 * pixelBuffer.size().width()), |
| 271 | + pixelBuffer.bytes() + sourceRectClipped.y() * source.bytesPerRow + sourceRectClipped.x() * 4 |
| 272 | + }; |
| 273 | + |
| 274 | + PixelBufferConversionView destination { |
| 275 | + { destFormat, pixelFormat(), colorSpace() }, |
| 276 | + static_cast<unsigned>(4 * destinationRect.width()), |
| 277 | + static_cast<uint8_t*>(cairo_image_surface_get_data(surface.get())) |
| 278 | + }; |
| 279 | + |
| 280 | + convertImagePixels(source, destination, destinationRect.size()); |
| 281 | + cairo_surface_mark_dirty_rectangle(surface.get(), 0, 0, destinationRect.width(), destinationRect.height()); |
255 | 282 |
|
256 | 283 | auto cr = adoptRef(cairo_create(m_surfaces[0].get())); |
257 | 284 | cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE); |
258 | | - cairo_set_source_surface(cr.get(), surface.get(), destPointScaled.x(), destPointScaled.y()); |
259 | | - cairo_rectangle(cr.get(), destPointScaled.x(), destPointScaled.y(), srcRectScaled.width(), srcRectScaled.height()); |
| 285 | + cairo_set_source_surface(cr.get(), surface.get(), destinationRect.x(), destinationRect.y()); |
| 286 | + cairo_rectangle(cr.get(), destinationRect.x(), destinationRect.y(), destinationRect.width(), destinationRect.height()); |
260 | 287 | cairo_fill(cr.get()); |
261 | 288 | } |
262 | 289 |
|
|
0 commit comments