WEAK void halide_do_par_for(void (*f)(int, uint8_t *), int min, int size, uint8_t *closure) { halide_gcd_job job; job.f = f; job.closure = closure; job.min = min; dispatch_apply_f(size, dispatch_get_global_queue(0, 0), &job, &halide_do_gcd_task); }
void queue::apply( size_t times, iteration_operation *op ) { iteration_wrap wrap( op, times ); dispatch_apply_f( times, d->native, &wrap, _xdispatch_run_iter_wrap ); }
static VALUE rb_queue_apply(VALUE self, SEL sel, VALUE n) { rb_vm_block_t *block = get_prepared_block(); dispatch_apply_f(NUM2SIZET(n), RQueue(self)->queue, (void *)block, rb_block_applier); GC_RELEASE(block); return Qnil; }
WEAK int default_do_par_for(void *user_context, halide_task_t f, int min, int size, uint8_t *closure) { halide_gcd_job job; job.f = f; job.user_context = user_context; job.closure = closure; job.min = min; job.exit_status = 0; dispatch_apply_f(size, dispatch_get_global_queue(0, 0), &job, &halide_do_gcd_task); return job.exit_status; }
int main(void) { test_start("Dispatch Reader/Writer Queues"); dq = dispatch_queue_create("com.apple.libdispatch.test_readsync", NULL); assert(dq); dispatch_queue_set_width(dq, LONG_MAX); dispatch_apply_f(LAPS, dispatch_get_global_queue(0, 0), NULL, apply_fn); dispatch_release(as_do(dq)); dispatch_main(); }
void parallel_for_(const Range& range, const ParallelLoopBody& body) { #ifdef HAVE_TBB tbb::parallel_for(tbb::blocked_range<int>(range.start, range.end), TbbProxyLoopBody(body)); #elif defined HAVE_CONCURRENCY class ConcurrencyProxyLoopBody { public: ConcurrencyProxyLoopBody(const ParallelLoopBody& body) : _body(body) {} void operator ()(int i) const { _body(Range(i, i + 1)); } private: const ParallelLoopBody& _body; ConcurrencyProxyLoopBody& operator=(const ConcurrencyProxyLoopBody&) {return *this;} } proxy(body); Concurrency::parallel_for(range.start, range.end, proxy); #elif defined HAVE_OPENMP #pragma omp parallel for schedule(dynamic) for (int i = range.start; i < range.end; ++i) body(Range(i, i + 1)); #elif defined (HAVE_GCD) dispatch_queue_t concurrent_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_apply_f(range.end - range.start, concurrent_queue, &const_cast<ParallelLoopBody&>(body), block_function); #else body(range); #endif // end HAVE_TBB }
void Event_test::simultaneousThreadUnsafeTwoEvents() { ThreadSafeCounter count("gov.fnal.counter"); bool wasChanged=false; AccessTestingProd* at(new AccessTestingProd("access","",demo::kThreadUnsafe,count,wasChanged)); demo::Event event1; event1.setIndex(3); event1.addProducer(at); std::unique_ptr<demo::Event> event2(event1.clone()); event2->setIndex(4); const demo::Event* events[2]={&event1,event2.get()}; const demo::Event** pEvents=events; dispatch_apply_f(2, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), const_cast<demo::Event**>(pEvents),get_task); CPPUNIT_ASSERT(count.value()==2); CPPUNIT_ASSERT(wasChanged==false); }
void ImageBufferData::putData(Uint8ClampedArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originx = sourceRect.x(); int destx = (destPoint.x() + sourceRect.x()) * resolutionScale; ASSERT(destx >= 0); ASSERT(destx < size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = (destPoint.x() + sourceRect.maxX()) * resolutionScale; ASSERT(endx <= size.width()); int width = sourceRect.width(); int destw = endx - destx; int originy = sourceRect.y(); int desty = (destPoint.y() + sourceRect.y()) * resolutionScale; ASSERT(desty >= 0); ASSERT(desty < size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = (destPoint.y() + sourceRect.maxY()) * resolutionScale; ASSERT(endy <= size.height()); int height = sourceRect.height(); int desth = endy - desty; if (width <= 0 || height <= 0) return; unsigned srcBytesPerRow = 4 * sourceSize.width(); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; unsigned destBytesPerRow; unsigned char* destRows; if (!accelerateRendering) { destBytesPerRow = 4 * size.width(); destRows = reinterpret_cast<unsigned char*>(m_data) + desty * destBytesPerRow + destx * 4; #if USE(ACCELERATE) if (haveVImageRoundingErrorFix() && unmultiplied) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dst; dst.height = desth; dst.width = destw; dst.rowBytes = destBytesPerRow; dst.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The premultiplying will be done in-place. src = dst; } vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); return; } #endif if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. if (!unmultiplied) return; srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (unmultiplied && alpha != 255) { destRows[basex] = (srcRows[basex] * alpha + 254) / 255; destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255; destRows[basex + 3] = alpha; } else reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; } destRows += destBytesPerRow; srcRows += srcBytesPerRow; } } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) IOSurfaceRef surface = m_surface.get(); IOSurfaceLock(surface, 0, 0); destBytesPerRow = IOSurfaceGetBytesPerRow(surface); destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4; #if USE(ACCELERATE) vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dest; dest.height = desth; dest.width = destw; dest.rowBytes = destBytesPerRow; dest.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The unpremultiplying and channel-swapping will be done in-place. if (unmultiplied) { srcRows = destRows; width = destw; height = desth; srcBytesPerRow = destBytesPerRow; } else src = dest; } if (unmultiplied) { ScanlineData scanlineData; scanlineData.scanlineWidth = width; scanlineData.srcData = srcRows; scanlineData.srcRowBytes = srcBytesPerRow; scanlineData.destData = destRows; scanlineData.destRowBytes = destBytesPerRow; dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline); } else { // Swap pixel channels from RGBA to BGRA. const uint8_t map[4] = { 2, 1, 0, 3 }; vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); } #else if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char b = srcRows[basex]; unsigned char alpha = srcRows[basex + 3]; if (unmultiplied && alpha != 255) { destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255; destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; destRows[basex + 2] = (b * alpha + 254) / 255; destRows[basex + 3] = alpha; } else { destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = b; destRows[basex + 3] = alpha; } } destRows += destBytesPerRow; srcRows += srcBytesPerRow; } #endif // USE(ACCELERATE) IOSurfaceUnlock(surface, 0, 0); #else ASSERT_NOT_REACHED(); #endif // USE(IOSURFACE_CANVAS_BACKING_STORE) } }
PassRefPtr<Uint8ClampedArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) const { float area = 4.0f * rect.width() * rect.height(); if (area > static_cast<float>(std::numeric_limits<int>::max())) return 0; RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); unsigned char* data = result->data(); int endx = ceilf(rect.maxX() * resolutionScale); int endy = ceilf(rect.maxY() * resolutionScale); if (rect.x() < 0 || rect.y() < 0 || endx > size.width() || endy > size.height()) result->zeroFill(); int originx = rect.x(); int destx = 0; int destw = rect.width(); if (originx < 0) { destw += originx; destx = -originx; originx = 0; } destw = min<int>(destw, ceilf(size.width() / resolutionScale) - originx); originx *= resolutionScale; if (endx > size.width()) endx = size.width(); int width = endx - originx; int originy = rect.y(); int desty = 0; int desth = rect.height(); if (originy < 0) { desth += originy; desty = -originy; originy = 0; } desth = min<int>(desth, ceilf(size.height() / resolutionScale) - originy); originy *= resolutionScale; if (endy > size.height()) endy = size.height(); int height = endy - originy; if (width <= 0 || height <= 0) return result.release(); unsigned destBytesPerRow = 4 * rect.width(); unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; unsigned srcBytesPerRow; unsigned char* srcRows; if (!accelerateRendering) { srcBytesPerRow = 4 * size.width(); srcRows = reinterpret_cast<unsigned char*>(m_data) + originy * srcBytesPerRow + originx * 4; #if USE(ACCELERATE) if (unmultiplied && haveVImageRoundingErrorFix()) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dst; dst.height = desth; dst.width = destw; dst.rowBytes = destBytesPerRow; dst.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The unpremultiplying will be done in-place. src = dst; } vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); return result.release(); } #endif if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. if (!unmultiplied) return result.release(); srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } if (unmultiplied) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (alpha) { destRows[basex] = (srcRows[basex] * 255) / alpha; destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha; destRows[basex + 3] = alpha; } else reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } else { for (int y = 0; y < height; ++y) { for (int x = 0; x < width * 4; x += 4) reinterpret_cast<uint32_t*>(destRows + x)[0] = reinterpret_cast<uint32_t*>(srcRows + x)[0]; srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) IOSurfaceRef surface = m_surface.get(); IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0); srcBytesPerRow = IOSurfaceGetBytesPerRow(surface); srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4; #if USE(ACCELERATE) vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dest; dest.height = desth; dest.width = destw; dest.rowBytes = destBytesPerRow; dest.data = destRows; if (resolutionScale != 1) { vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. Pixel_8888 backgroundColor; vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); // The unpremultiplying and channel-swapping will be done in-place. if (unmultiplied) { srcRows = destRows; width = destw; height = desth; srcBytesPerRow = destBytesPerRow; } else src = dest; } if (unmultiplied) { ScanlineData scanlineData; scanlineData.scanlineWidth = width; scanlineData.srcData = srcRows; scanlineData.srcRowBytes = srcBytesPerRow; scanlineData.destData = destRows; scanlineData.destRowBytes = destBytesPerRow; dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline); } else { // Swap pixel channels from BGRA to RGBA. const uint8_t map[4] = { 2, 1, 0, 3 }; vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); } #else if (resolutionScale != 1) { RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. srcRows = destRows; srcBytesPerRow = destBytesPerRow; width = destw; height = desth; } if (unmultiplied) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char b = srcRows[basex]; unsigned char alpha = srcRows[basex + 3]; if (alpha) { destRows[basex] = (srcRows[basex + 2] * 255) / alpha; destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; destRows[basex + 2] = (b * 255) / alpha; destRows[basex + 3] = alpha; } else { destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = b; destRows[basex + 3] = srcRows[basex + 3]; } } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } else { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char b = srcRows[basex]; destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = b; destRows[basex + 3] = srcRows[basex + 3]; } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } #endif // USE(ACCELERATE) IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0); #else ASSERT_NOT_REACHED(); #endif // USE(IOSURFACE_CANVAS_BACKING_STORE) } return result.release(); }
void ImageBufferData::putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originx = sourceRect.x(); int destx = destPoint.x() + sourceRect.x(); ASSERT(destx >= 0); ASSERT(destx < size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); ASSERT(endx <= size.width()); int width = endx - destx; int originy = sourceRect.y(); int desty = destPoint.y() + sourceRect.y(); ASSERT(desty >= 0); ASSERT(desty < size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); ASSERT(endy <= size.height()); int height = endy - desty; if (width <= 0 || height <= 0) return; unsigned srcBytesPerRow = 4 * sourceSize.width(); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; unsigned destBytesPerRow; unsigned char* destRows; if (!accelerateRendering) { destBytesPerRow = 4 * size.width(); destRows = reinterpret_cast<unsigned char*>(m_data) + desty * destBytesPerRow + destx * 4; #if USE(ACCELERATE) if (haveVImageRoundingErrorFix() && unmultiplied) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dst; dst.height = height; dst.width = width; dst.rowBytes = destBytesPerRow; dst.data = destRows; vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); return; } #endif for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (unmultiplied && alpha != 255) { destRows[basex] = (srcRows[basex] * alpha + 254) / 255; destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255; destRows[basex + 3] = alpha; } else reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; } destRows += destBytesPerRow; srcRows += srcBytesPerRow; } } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) IOSurfaceRef surface = m_surface.get(); IOSurfaceLock(surface, 0, 0); destBytesPerRow = IOSurfaceGetBytesPerRow(surface); destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4; #if USE(ACCELERATE) if (unmultiplied) { ScanlineData scanlineData; scanlineData.scanlineWidth = width; scanlineData.srcData = srcRows; scanlineData.srcRowBytes = srcBytesPerRow; scanlineData.destData = destRows; scanlineData.destRowBytes = destBytesPerRow; dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline); } else { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dest; dest.height = height; dest.width = width; dest.rowBytes = destBytesPerRow; dest.data = destRows; // Swap pixel channels from RGBA to BGRA. const uint8_t map[4] = { 2, 1, 0, 3 }; vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); } #else for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (unmultiplied && alpha != 255) { destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255; destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; destRows[basex + 2] = (srcRows[basex] * alpha + 254) / 255; destRows[basex + 3] = alpha; } else { destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = srcRows[basex]; destRows[basex + 3] = alpha; } } destRows += destBytesPerRow; srcRows += srcBytesPerRow; } #endif // USE(ACCELERATE) IOSurfaceUnlock(surface, 0, 0); #else ASSERT_NOT_REACHED(); #endif // USE(IOSURFACE_CANVAS_BACKING_STORE) } }
PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied) const { float area = 4.0f * rect.width() * rect.height(); if (area > static_cast<float>(std::numeric_limits<int>::max())) return 0; RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4); unsigned char* data = result->data(); if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height()) memset(data, 0, result->length()); int originx = rect.x(); int destx = 0; if (originx < 0) { destx = -originx; originx = 0; } int endx = rect.maxX(); if (endx > size.width()) endx = size.width(); int width = endx - originx; int originy = rect.y(); int desty = 0; if (originy < 0) { desty = -originy; originy = 0; } int endy = rect.maxY(); if (endy > size.height()) endy = size.height(); int height = endy - originy; if (width <= 0 || height <= 0) return result.release(); unsigned destBytesPerRow = 4 * rect.width(); unsigned char* destRows = data + desty * destBytesPerRow + destx * 4; unsigned srcBytesPerRow; unsigned char* srcRows; if (!accelerateRendering) { srcBytesPerRow = 4 * size.width(); srcRows = reinterpret_cast<unsigned char*>(m_data) + originy * srcBytesPerRow + originx * 4; #if USE(ACCELERATE) if (unmultiplied && haveVImageRoundingErrorFix()) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dst; dst.height = height; dst.width = width; dst.rowBytes = destBytesPerRow; dst.data = destRows; vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); return result.release(); } #endif if (unmultiplied) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (alpha) { destRows[basex] = (srcRows[basex] * 255) / alpha; destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha; destRows[basex + 3] = alpha; } else reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0]; } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } else { for (int y = 0; y < height; ++y) { for (int x = 0; x < width * 4; x += 4) reinterpret_cast<uint32_t*>(destRows + x)[0] = reinterpret_cast<uint32_t*>(srcRows + x)[0]; srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) IOSurfaceRef surface = m_surface.get(); IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0); srcBytesPerRow = IOSurfaceGetBytesPerRow(surface); srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4; #if USE(ACCELERATE) if (unmultiplied) { ScanlineData scanlineData; scanlineData.scanlineWidth = width; scanlineData.srcData = srcRows; scanlineData.srcRowBytes = srcBytesPerRow; scanlineData.destData = destRows; scanlineData.destRowBytes = destBytesPerRow; dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline); } else { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = srcBytesPerRow; src.data = srcRows; vImage_Buffer dest; dest.height = height; dest.width = width; dest.rowBytes = destBytesPerRow; dest.data = destRows; // Swap pixel channels from BGRA to RGBA. const uint8_t map[4] = { 2, 1, 0, 3 }; vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); } #else if (unmultiplied) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; unsigned char alpha = srcRows[basex + 3]; if (alpha) { destRows[basex] = (srcRows[basex + 2] * 255) / alpha; destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; destRows[basex + 2] = (srcRows[basex] * 255) / alpha; destRows[basex + 3] = alpha; } else { destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = srcRows[basex]; destRows[basex + 3] = srcRows[basex + 3]; } } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } else { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; x++) { int basex = x * 4; destRows[basex] = srcRows[basex + 2]; destRows[basex + 1] = srcRows[basex + 1]; destRows[basex + 2] = srcRows[basex]; destRows[basex + 3] = srcRows[basex + 3]; } srcRows += srcBytesPerRow; destRows += destBytesPerRow; } } #endif // USE(ACCELERATE) IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0); #else ASSERT_NOT_REACHED(); #endif // USE(IOSURFACE_CANVAS_BACKING_STORE) } return result.release(); }