1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2/* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20#include <quartz/cgutils.h> 21 22#include <salbmp.hxx> 23#ifdef MACOSX 24#include <osx/saldata.hxx> 25#else 26#include <ios/iosinst.hxx> 27#endif 28 29#ifdef MACOSX 30#include <premac.h> 31#include <Metal/Metal.h> 32#include <postmac.h> 33#endif 34 35static void CFRTLFree(void* /*info*/, const void* data, size_t /*size*/) 36{ 37 std::free( const_cast<void*>(data) ); 38} 39 40CGImageRef CreateWithSalBitmapAndMask( const SalBitmap& rBitmap, const SalBitmap& rMask, int nX, int nY, int nWidth, int nHeight ) 41{ 42 CGImageRef xImage( rBitmap.CreateCroppedImage( nX, nY, nWidth, nHeight ) ); 43 if( !xImage ) 44 return nullptr; 45 46 CGImageRef xMask = rMask.CreateCroppedImage( nX, nY, nWidth, nHeight ); 47 if( !xMask ) 48 return xImage; 49 50 // If xMask is an image (i.e. not a mask), it must be greyscale - a requirement of the 51 // CGImageCreateWithMask() function. 52 if( !CGImageIsMask(xMask) && CGImageGetColorSpace(xMask) != GetSalData()->mxGraySpace ) 53 { 54 CGImageRef xGrayMask = CGImageCreateCopyWithColorSpace(xMask, GetSalData()->mxGraySpace); 55 if (xGrayMask) 56 { 57 CFRelease(xMask); 58 xMask = xGrayMask; 59 } 60 else 61 { 62 // Many gallery images will fail to be converted to a grayscale 63 // colorspace so fall back to old mask creation code 64 const CGRect xImageRect=CGRectMake( 0, 0, nWidth, nHeight );//the rect has no offset 65 66 // create the alpha mask image fitting our image 67 // TODO: is caching the full mask or the subimage mask worth it? 68 int nMaskBytesPerRow = ((nWidth + 3) & ~3); 69 void* pMaskMem = std::malloc( nMaskBytesPerRow * nHeight ); 70 CGContextRef xMaskContext = CGBitmapContextCreate( pMaskMem, 71 nWidth, nHeight, 8, nMaskBytesPerRow, GetSalData()->mxGraySpace, kCGImageAlphaNone ); 72 CGContextDrawImage( xMaskContext, xImageRect, xMask ); 73 CFRelease( xMask ); 74 CGDataProviderRef xDataProvider( CGDataProviderCreateWithData( nullptr, 75 pMaskMem, nHeight * nMaskBytesPerRow, &CFRTLFree ) ); 76 77 static const CGFloat* pDecode = nullptr; 78 xMask = CGImageMaskCreate( nWidth, nHeight, 8, 8, nMaskBytesPerRow, xDataProvider, pDecode, false ); 79 CFRelease( xDataProvider ); 80 CFRelease( xMaskContext ); 81 } 82 } 83 84 if( !xMask ) 85 return xImage; 86 87 // combine image and alpha mask 88 CGImageRef xMaskedImage = CGImageCreateWithMask( xImage, xMask ); 89 CFRelease( xMask ); 90 CFRelease( xImage ); 91 return xMaskedImage; 92} 93 94#ifdef MACOSX 95 96bool DefaultMTLDeviceIsSupported() 97{ 98 id<MTLDevice> pMetalDevice = MTLCreateSystemDefaultDevice(); 99 if (!pMetalDevice || !pMetalDevice.name) 100 { 101 SAL_WARN("vcl.skia", "MTLCreateSystemDefaultDevice() returned nil"); 102 return false; 103 } 104 105 SAL_WARN("vcl.skia", "Default MTLDevice is \"" << [pMetalDevice.name UTF8String] << "\""); 106 107 bool bRet = true; 108 109 // tdf#156881 Disable Metal with AMD Radeon Pro 5XXX GPUs on macOS Catalina 110 // When running macOS Catalina on a 2019 MacBook Pro, unexpected drawing 111 // artifacts are drawn so disable Metal for the AMD Radeon Pro GPUs listed 112 // for that model in https://support.apple.com/kb/SP809. 113 if (@available(macOS 11, *)) 114 { 115 // No known problems with macOS Big Sur or later 116 } 117 else 118 { 119 static NSString* pAMDRadeonPro5300Prefix = @"AMD Radeon Pro 5300M"; 120 static NSString* pAMDRadeonPro5500Prefix = @"AMD Radeon Pro 5500M"; 121 if ([pMetalDevice.name hasPrefix:pAMDRadeonPro5300Prefix] || [pMetalDevice.name hasPrefix:pAMDRadeonPro5500Prefix]) 122 bRet = false; 123 } 124 125 [pMetalDevice release]; 126 return bRet; 127} 128 129#endif 130 131/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 132
