【问题标题】:Emulating Apple's drawInRect: for offscreen pixel buffers模拟 Apple 的 drawInRect:用于屏幕外像素缓冲区
【发布时间】:2014-07-13 16:28:11
【问题描述】:

我需要一个能在一个缓冲区的矩形区域到另一个缓冲区之间快速复制原始 32 位像素 malloc-ed 数据的例程。

所以... 下面是我尝试模仿 Apple 的 drawInRect:fromRect:operation:fraction 方法将数据传送到 NSView。这两个例程通常存在于NSImageNSBitmapImageRep 类中。我忽略了operation: 模式或fraction: alpha 混合。

可以假设 x/y/w/h 值已经过测试和截断,以确保源/目标矩形位于提供的两个缓冲区内,并且矩形区域非零且大小相同 (即没有缩放)。

我的测试表明在我的特定硬件上复制全高清 (1920x1080) 区域图像是

  • 案例 1:32 位传输:6.74 毫秒
  • 案例 2:64 位传输:5.30 毫秒
  • 案例 3:memcpy 传输:3.20ms

不幸的是,由于其中一些缓冲区是由外部 API 提供的,因此我无法保证这些缓冲区是 64 位或 128 位对齐的。话虽如此,我有一种预感,他们就是我的情况——memcpy 正在测试缓冲区地址是否已表示对齐,并且正在执行一些 SSE3 内在函数来完成其业务 (_platform_memmove$VARIANT$Ivybridge)。

有什么改进的建议吗?

或者也许 Cocoa API 中有一些神奇的例程已经可以做到这一点?

typedef struct copyRect
{
    u_int32_t   *data;
    u_int32_t   x;
    u_int32_t   y;
    u_int32_t   w;
    u_int32_t   h;
    u_int32_t   canvasWidth;  // ie. rowBytes/4
} copyRect;

-(void)copyRectFromSrc:(copyRect *)srcImage toTarget:(copyRect *)dstImage
{
    u_int32_t h = srcImage->h;
    u_int32_t w = srcImage->w;

    u_int32_t srcDelta = srcImage->y*srcImage->canvasWidth + srcImage->x;
    u_int32_t dstDelta = dstImage->y*dstImage->canvasWidth + dstImage->x;
    u_int32_t *srcPtr = srcImage->data+srcDelta;
    u_int32_t *dstPtr = dstImage->data+dstDelta;
    u_int32_t w2 = w/2;

    // scan top-to-bottom in buffer
    for (u_int32_t y=0; y<h; y++) {

// case 1: this would work in all cases (single pixel = 32 bits)
//        u_int32_t *srcXptr = srcPtr;
//        u_int32_t *dstXptr = dstPtr;
//        for (u_int32_t x=0; x<w; x++)
//            *dstXptr++ = *srcXptr++;

// case 2: this would work if src/dst image were even-width
//        u_int64_t *srcXptr = (u_int64_t *)srcPtr;
//        u_int64_t *dstXptr = (u_int64_t *)dstPtr;
//        for (u_int32_t x=0; x<w2; x++)
//            *dstXptr++ = *srcXptr++;

// case 3: this seems to have the best performance (all cases)
        memcpy(dstPtr,srcPtr,w*4);

        srcPtr += srcImage->canvasWidth;
        dstPtr += dstImage->canvasWidth;
    }
}

【问题讨论】:

    标签: cocoa nsimage accelerate-framework


    【解决方案1】:
    #include <Accelerate/Accelerate.h>  // see vImage/Conversion.h
    
    vImage_Error vImageCopyBuffer(const vImage_Buffer *src, const vImage_Buffer *dest, size_t pixelSize, vImage_Flags flags ) VIMAGE_NON_NULL(1,2) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0);
    

    关于 Alpha 合成,请参阅 vImage/Alpha.h 中的各种 Alpha 混合例程。

    【讨论】:

    • vImageCopyBufer 特定于 OSX 10.10。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多