Sources/CGImageCopy.mm
| /* | 
| Copyright (C) 2015 Apple Inc. All Rights Reserved. | 
| See LICENSE.txt for this sample’s licensing information | 
| Abstract: | 
| Utility methods for "fast-string" memory copy. | 
| */ | 
| #pragma mark - | 
| #pragma mark Private - Headers | 
| #import <iostream> | 
| #import "CGImageCopy.h" | 
| #pragma mark - | 
| #pragma mark Public - Utilities | 
| // "Fast string" memory copy better suited for image copy | 
| uint8_t* CG::memcpy(const size_t& rSize, | 
| const uint8_t* pSrc, | 
| uint8_t* pDst) | 
| { | 
|     asm volatile("mov %[d], %%rdi\n" | 
| "mov %[s], %%rsi\n" | 
| "mov %[c], %%rcx\n" | 
| "rep/movsb\n" | 
| : | 
| : [d] "r" (pDst), | 
| [s] "r" (pSrc), | 
| [c] "r" (rSize) | 
| : "%rdi", "%rsi", "%rcx", "memory"); | 
| return pDst; | 
| } // Mem::Copy | 
| // "Fast string" memory copy better suited for image copy | 
| void* CG::memcpy(const size_t& rSize, | 
| const void* pIn, | 
| void* pOut) | 
| { | 
| const uint8_t* pSrc = static_cast<const uint8_t *>(pIn); | 
| uint8_t* pDst = static_cast<uint8_t *>(pOut); | 
| return CG::memcpy(rSize, pSrc, pDst); | 
| } // memcpy | 
| // I/O surface errors that could potentially occur when | 
| // copying from a source to destination surface | 
| #define kMacroIOReturnCpyErrSrcRef iokit_common_err(0x3b1) // Null source i/o reference | 
| #define kMacroIOReturnCpyErrDstRef iokit_common_err(0x3b2) // Null destination i/o reference | 
| #define kMacroIOReturnCpyErrHeight iokit_common_err(0x3b3) // Invalid height | 
| #define kMacroIOReturnCpyErrRowBytes iokit_common_err(0x3b4) // Invalid row bytes | 
| #define kMacroIOReturnCpyErrSize iokit_common_err(0x3b5) // Plane size is zero | 
| #define kMacroIOReturnCpyErrSrcPtr iokit_common_err(0x3b6) // Null pointer for source surface base address | 
| #define kMacroIOReturnCpyErrDstPtr iokit_common_err(0x3b7) // Null pointer for destination surface base address | 
| IOReturn CG::kIOReturnCpySuccess = kIOReturnSuccess; | 
| IOReturn CG::kIOReturnCpyErrSrcRef = kMacroIOReturnCpyErrSrcRef; | 
| IOReturn CG::kIOReturnCpyErrDstRef = kMacroIOReturnCpyErrDstRef; | 
| IOReturn CG::kIOReturnCpyErrHeight = kMacroIOReturnCpyErrHeight; | 
| IOReturn CG::kIOReturnCpyErrRowBytes = kMacroIOReturnCpyErrRowBytes; | 
| IOReturn CG::kIOReturnCpyErrSize = kMacroIOReturnCpyErrSize; | 
| IOReturn CG::kIOReturnCpyErrSrcPtr = kMacroIOReturnCpyErrSrcPtr; | 
| IOReturn CG::kIOReturnCpyErrDstPtr = kMacroIOReturnCpyErrDstPtr; | 
| // Copy from a source to destination i/o surface at a plane given by a source | 
| // index to a destination i/o surface at a plane given by a destination index | 
| IOSurfaceRef CG::s2dcpy(const size_t& nSrcIdx, | 
| const IOSurfaceRef pSrc, | 
| const size_t& nDstIdx, | 
| IOSurfaceRef pDst, | 
| IOReturn& nResult) | 
| { | 
| nResult = (pSrc != nullptr) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrSrcRef; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|     { | 
| nResult = (pDst != nullptr) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrDstRef; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|         { | 
| uint32_t nSrcSeed = 0; | 
| nResult = IOSurfaceLock(pSrc, kIOSurfaceLockReadOnly, &nSrcSeed); | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|             { | 
| uint32_t nDstSeed = 0; | 
| nResult = IOSurfaceLock(pDst, 0, &nDstSeed); | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|                 { | 
| const size_t nSrcHeight = IOSurfaceGetHeightOfPlane(pSrc, nSrcIdx); | 
| const size_t nDstHeight = IOSurfaceGetHeightOfPlane(pDst, nDstIdx); | 
| nResult = (nSrcHeight == nDstHeight) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrHeight; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|                     { | 
| const size_t nSrcRowBytes = IOSurfaceGetBytesPerRowOfPlane(pSrc, nSrcIdx); | 
| const size_t nDstRowBytes = IOSurfaceGetBytesPerRowOfPlane(pDst, nDstIdx); | 
| nResult = (nSrcRowBytes == nDstRowBytes) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrRowBytes; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|                         { | 
| const size_t nDstSize = nDstHeight * nDstRowBytes; | 
| nResult = (nDstSize > 0) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrSize; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|                             { | 
| const void* pSrcAddr = IOSurfaceGetBaseAddressOfPlane(pSrc, nSrcIdx); | 
| nResult = (pSrcAddr != nullptr) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrSrcPtr; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|                                 { | 
| void* pDstAddr = IOSurfaceGetBaseAddressOfPlane(pDst, nDstIdx); | 
| nResult = (pDstAddr != nullptr) ? CG::kIOReturnCpySuccess : CG::kIOReturnCpyErrDstPtr; | 
| if(nResult == CG::kIOReturnCpySuccess) | 
|                                     { | 
| CG::memcpy(nDstSize, pSrcAddr, pDstAddr); | 
| } // if | 
| } // if | 
| } // if | 
| } // if | 
| } // if | 
| IOSurfaceUnlock(pDst, 0, &nDstSeed); | 
| } // if | 
| IOSurfaceUnlock(pSrc, 0, &nSrcSeed); | 
| } // if | 
| } // if | 
| } // if | 
| return pDst; | 
| } // s2dcpy | 
| // Copy from a source to destination i/o surface at plane 0 | 
| IOSurfaceRef CG::s2dcpy(const IOSurfaceRef pSrc, | 
| IOSurfaceRef pDst, | 
| IOReturn& nResult) | 
| { | 
| return CG::s2dcpy(0, pSrc, 0, pDst, nResult); | 
| } // s2dcpy | 
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-12-10