MTKView.hpp
1 /* 2 * 3 * Copyright 2020-2021 Apple Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 //------------------------------------------------------------------------------------------------------------------------------------------------------------- 19 // 20 // MetalKit/MTKView.hpp 21 // 22 //------------------------------------------------------------------------------------------------------------------------------------------------------------- 23 24 #pragma once 25 26 //------------------------------------------------------------------------------------------------------------------------------------------------------------- 27 28 #include "MetalKitPrivate.hpp" 29 30 #include <AppKit/AppKit.hpp> 31 #include <Metal/Metal.hpp> 32 #include <QuartzCore/QuartzCore.hpp> 33 34 #include <CoreGraphics/CGColorSpace.h> 35 36 //------------------------------------------------------------------------------------------------------------------------------------------------------------- 37 38 namespace MTK 39 { 40 class ViewDelegate 41 { 42 public: 43 virtual ~ViewDelegate() { } 44 virtual void drawInMTKView( class View* pView ) { } 45 virtual void drawableSizeWillChange( class View* pView, CGSize size ) { } 46 }; 47 48 class View : public NS::Referencing< MTK::View, NS::View > 49 { 50 public: 51 static View* alloc(); 52 View* init( CGRect frame, const MTL::Device* pDevice ); 53 View* init( NS::Coder* pCoder ); 54 55 void setDevice( const MTL::Device* pDevice ); 56 MTL::Device* device() const; 57 58 void setDelegate( const MTK::ViewDelegate* pDelegate ); 59 ViewDelegate* delegate() const; 60 61 CA::MetalDrawable* currentDrawable() const; 62 63 void setFramebufferOnly( bool framebufferOnly ); 64 bool framebufferOnly() const; 65 66 void setDepthStencilAttachmentTextureUsage( MTL::TextureUsage textureUsage ); 67 MTL::TextureUsage depthStencilAttachmentTextureUsage() const; 68 69 void setMultisampleColorAttachmentTextureUsage( MTL::TextureUsage textureUsage ); 70 MTL::TextureUsage multisampleColorAttachmentTextureUsage() const; 71 72 void setPresentsWithTransaction( bool presentsWithTransaction ); 73 bool presentsWithTransaction() const; 74 75 void setColorPixelFormat( MTL::PixelFormat colorPixelFormat ); 76 MTL::PixelFormat colorPixelFormat() const; 77 78 void setDepthStencilPixelFormat( MTL::PixelFormat colorPixelFormat ); 79 MTL::PixelFormat depthStencilPixelFormat() const; 80 81 void setSampleCount( NS::UInteger sampleCount ); 82 NS::UInteger sampleCount() const; 83 84 void setClearColor( MTL::ClearColor clearColor ); 85 MTL::ClearColor clearColor() const; 86 87 void setClearDepth( double clearDepth ); 88 double clearDepth() const; 89 90 void setClearStencil( uint32_t clearStencil ); 91 uint32_t clearStencil() const; 92 93 MTL::Texture* depthStencilTexture() const; 94 95 MTL::Texture* multisampleColorTexture() const; 96 97 void releaseDrawables() const; 98 99 MTL::RenderPassDescriptor* currentRenderPassDescriptor() const; 100 101 void setPreferredFramesPerSecond( NS::Integer preferredFramesPerSecond ); 102 NS::Integer preferredFramesPerSecond() const; 103 104 void setEnableSetNeedsDisplay( bool enableSetNeedsDisplay ); 105 bool enableSetNeedsDisplay() const; 106 107 void setAutoresizeDrawable( bool autoresizeDrawable ); 108 bool autoresizeDrawable(); 109 110 void setDrawableSize( CGSize drawableSize ); 111 CGSize drawableSize() const; 112 113 CGSize preferredDrawableSize() const; 114 MTL::Device* preferredDevice() const; 115 116 void setPaused( bool paused ); 117 bool isPaused() const; 118 119 void setColorSpace( CGColorSpaceRef colorSpace ); 120 CGColorSpaceRef colorSpace() const; 121 122 void draw(); 123 124 }; 125 } 126 127 _NS_INLINE MTK::View* MTK::View::alloc() 128 { 129 return NS::Object::alloc< View >( _MTK_PRIVATE_CLS( MTKView ) ); 130 } 131 132 _NS_INLINE MTK::View* MTK::View::init( CGRect frame, const MTL::Device* pDevice ) 133 { 134 return NS::Object::sendMessage< View* >( this, _MTK_PRIVATE_SEL( initWithFrame_device_ ), frame, pDevice ); 135 } 136 137 _NS_INLINE MTK::View* MTK::View::init( NS::Coder* pCoder ) 138 { 139 return NS::Object::sendMessage< View* >( this, _MTK_PRIVATE_SEL( initWithCoder_ ), pCoder ); 140 } 141 142 _NS_INLINE void MTK::View::setDevice( const MTL::Device* pDevice ) 143 { 144 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setDevice_ ), pDevice ); 145 } 146 147 _NS_INLINE MTL::Device* MTK::View::device() const 148 { 149 return NS::Object::sendMessage< MTL::Device* >( this, _MTK_PRIVATE_SEL( device ) ); 150 } 151 152 _NS_INLINE void MTK::View::setDelegate( const MTK::ViewDelegate* pDelegate ) 153 { 154 // TODO: Same problem as NS::Application::setDelegate. 155 // Requires a similar soution 156 NS::Value* pWrapper = NS::Value::value( pDelegate ); 157 158 // drawInMTKView: 159 160 void (*drawDispatch)( NS::Value*, SEL, id ) = []( NS::Value* pSelf, SEL _cmd, id pMTKView ){ 161 auto pDel = reinterpret_cast< MTK::ViewDelegate* >( pSelf->pointerValue() ); 162 pDel->drawInMTKView( (MTK::View *)pMTKView ); 163 }; 164 165 class_addMethod( (Class)objc_lookUpClass( "NSValue" ), sel_registerName( "drawInMTKView:" ), (IMP)drawDispatch, "v@:@" ); 166 167 // mtkView:drawableSizeWillChange: 168 169 void (*drawableSizeWillChange)( NS::Value*, SEL, View*, CGSize ) = []( NS::Value* pSelf, SEL, View* pMTKView, CGSize size){ 170 auto pDel = reinterpret_cast< MTK::ViewDelegate* >( pSelf->pointerValue() ); 171 pDel->drawableSizeWillChange( pMTKView, size ); 172 }; 173 174 #if CGFLOAT_IS_DOUBLE 175 const char* cbparams = "v@:@{CGSize=dd}"; 176 #else 177 const char* cbparams = "v@:@{CGSize=ff}"; 178 #endif // CGFLOAT_IS_DOUBLE 179 180 class_addMethod( (Class)objc_lookUpClass( "NSValue" ), sel_registerName( "mtkView:drawableSizeWillChange:"), (IMP)drawableSizeWillChange, cbparams ); 181 182 // This circular reference leaks the wrapper object to keep it around for the dispatch to work. 183 // It may be better to hoist it to the MTK::View as a member. 184 objc_setAssociatedObject( (id)pWrapper, "mtkviewdelegate_cpp", (id)pWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC ); 185 186 NS::Object::sendMessage< void >( this, sel_registerName( "setDelegate:" ), pWrapper ); 187 } 188 189 _NS_INLINE MTK::ViewDelegate* MTK::View::delegate() const 190 { 191 NS::Value* pWrapper = NS::Object::sendMessage< NS::Value* >( this, _MTK_PRIVATE_SEL( delegate ) ); 192 if ( pWrapper ) 193 { 194 return reinterpret_cast< ViewDelegate* >( pWrapper->pointerValue() ); 195 } 196 return nullptr; 197 } 198 199 _NS_INLINE CA::MetalDrawable* MTK::View::currentDrawable() const 200 { 201 return NS::Object::sendMessage< CA::MetalDrawable* >( this, _MTK_PRIVATE_SEL( currentDrawable ) ); 202 } 203 204 _NS_INLINE void MTK::View::setFramebufferOnly( bool framebufferOnly ) 205 { 206 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setFramebufferOnly_ ), framebufferOnly ); 207 } 208 209 _NS_INLINE bool MTK::View::framebufferOnly() const 210 { 211 return NS::Object::sendMessage< bool >( this, _MTK_PRIVATE_SEL( framebufferOnly ) ); 212 } 213 214 _NS_INLINE void MTK::View::setDepthStencilAttachmentTextureUsage( MTL::TextureUsage textureUsage ) 215 { 216 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setDepthStencilAttachmentTextureUsage_ ), textureUsage ); 217 } 218 219 _NS_INLINE MTL::TextureUsage MTK::View::depthStencilAttachmentTextureUsage() const 220 { 221 return NS::Object::sendMessage< MTL::TextureUsage >( this, _MTK_PRIVATE_SEL( depthStencilAttachmentTextureUsage ) ); 222 } 223 224 _NS_INLINE void MTK::View::setMultisampleColorAttachmentTextureUsage( MTL::TextureUsage textureUsage ) 225 { 226 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setMultisampleColorAttachmentTextureUsage_ ), textureUsage ); 227 } 228 229 _NS_INLINE MTL::TextureUsage MTK::View::multisampleColorAttachmentTextureUsage() const 230 { 231 return NS::Object::sendMessage< MTL::TextureUsage >( this, _MTK_PRIVATE_SEL( multisampleColorAttachmentTextureUsage ) ); 232 } 233 234 _NS_INLINE void MTK::View::setPresentsWithTransaction( bool presentsWithTransaction ) 235 { 236 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setPresentsWithTransaction_ ), presentsWithTransaction ); 237 } 238 239 _NS_INLINE bool MTK::View::presentsWithTransaction() const 240 { 241 return NS::Object::sendMessage< bool >( this, _MTK_PRIVATE_SEL( presentsWithTransaction ) ); 242 } 243 244 _NS_INLINE void MTK::View::setColorPixelFormat( MTL::PixelFormat colorPixelFormat ) 245 { 246 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setColorPixelFormat_ ), colorPixelFormat ); 247 } 248 249 _NS_INLINE MTL::PixelFormat MTK::View::colorPixelFormat() const 250 { 251 return NS::Object::sendMessage< MTL::PixelFormat >( this, _MTK_PRIVATE_SEL( colorPixelFormat ) ); 252 } 253 254 _NS_INLINE void MTK::View::setDepthStencilPixelFormat( MTL::PixelFormat colorPixelFormat ) 255 { 256 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setDepthStencilPixelFormat_ ), colorPixelFormat ); 257 } 258 259 _NS_INLINE MTL::PixelFormat MTK::View::depthStencilPixelFormat() const 260 { 261 return NS::Object::sendMessage< MTL::PixelFormat >( this, _MTK_PRIVATE_SEL( depthStencilPixelFormat ) ); 262 } 263 264 _NS_INLINE void MTK::View::setSampleCount( NS::UInteger sampleCount ) 265 { 266 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setSampleCount_), sampleCount ); 267 } 268 269 _NS_INLINE NS::UInteger MTK::View::sampleCount() const 270 { 271 return NS::Object::sendMessage< NS::UInteger >( this, _MTK_PRIVATE_SEL( sampleCount ) ); 272 } 273 274 _NS_INLINE void MTK::View::setClearColor( MTL::ClearColor clearColor ) 275 { 276 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setClearColor_ ), clearColor ); 277 } 278 279 _NS_INLINE MTL::ClearColor MTK::View::clearColor() const 280 { 281 return NS::Object::sendMessage< MTL::ClearColor >( this, _MTK_PRIVATE_SEL( clearColor) ); 282 } 283 284 _NS_INLINE void MTK::View::setClearDepth( double clearDepth ) 285 { 286 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setClearDepth_ ), clearDepth ); 287 } 288 289 _NS_INLINE double MTK::View::clearDepth() const 290 { 291 return NS::Object::sendMessage< double >( this, _MTK_PRIVATE_SEL( clearDepth ) ); 292 } 293 294 _NS_INLINE void MTK::View::setClearStencil( uint32_t clearStencil ) 295 { 296 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setClearStencil_ ), clearStencil ); 297 } 298 299 _NS_INLINE uint32_t MTK::View::clearStencil() const 300 { 301 return NS::Object::sendMessage< uint32_t >( this, _MTK_PRIVATE_SEL( clearStencil ) ); 302 } 303 304 _NS_INLINE MTL::Texture* MTK::View::depthStencilTexture() const 305 { 306 return NS::Object::sendMessage< MTL::Texture* >( this, _MTK_PRIVATE_SEL( depthStencilTexture ) ); 307 } 308 309 _NS_INLINE MTL::Texture* MTK::View::multisampleColorTexture() const 310 { 311 return NS::Object::sendMessage< MTL::Texture* >( this, _MTK_PRIVATE_SEL( multisampleColorTexture ) ); 312 } 313 314 _NS_INLINE void MTK::View::releaseDrawables() const 315 { 316 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( releaseDrawables ) ); 317 } 318 319 _NS_INLINE MTL::RenderPassDescriptor* MTK::View::currentRenderPassDescriptor() const 320 { 321 return NS::Object::sendMessage< MTL::RenderPassDescriptor* >( this, _MTK_PRIVATE_SEL( currentRenderPassDescriptor ) ); 322 } 323 324 _NS_INLINE void MTK::View::setPreferredFramesPerSecond( NS::Integer preferredFramesPerSecond ) 325 { 326 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setPreferredFramesPerSecond_ ), preferredFramesPerSecond ); 327 } 328 329 _NS_INLINE NS::Integer MTK::View::preferredFramesPerSecond() const 330 { 331 return NS::Object::sendMessage< NS::Integer >( this, _MTK_PRIVATE_SEL( preferredFramesPerSecond ) ); 332 } 333 334 _NS_INLINE void MTK::View::setEnableSetNeedsDisplay( bool enableSetNeedsDisplay ) 335 { 336 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setEnableSetNeedsDisplay_ ), enableSetNeedsDisplay ); 337 } 338 339 _NS_INLINE bool MTK::View::enableSetNeedsDisplay() const 340 { 341 return NS::Object::sendMessage< bool >( this, _MTK_PRIVATE_SEL( enableSetNeedsDisplay ) ); 342 } 343 344 _NS_INLINE void MTK::View::setAutoresizeDrawable( bool autoresizeDrawable ) 345 { 346 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setAutoresizeDrawable_ ), autoresizeDrawable ); 347 } 348 349 _NS_INLINE bool MTK::View::autoresizeDrawable() 350 { 351 return NS::Object::sendMessage< bool >( this, _MTK_PRIVATE_SEL( autoresizeDrawable ) ); 352 } 353 354 _NS_INLINE void MTK::View::setDrawableSize( CGSize drawableSize ) 355 { 356 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setDrawableSize_ ), drawableSize ); 357 } 358 359 _NS_INLINE CGSize MTK::View::drawableSize() const 360 { 361 return NS::Object::sendMessage< CGSize >( this, _MTK_PRIVATE_SEL( drawableSize ) ); 362 } 363 364 _NS_INLINE CGSize MTK::View::preferredDrawableSize() const 365 { 366 return NS::Object::sendMessage< CGSize >( this, _MTK_PRIVATE_SEL( preferredDrawableSize ) ); 367 } 368 369 _NS_INLINE MTL::Device* MTK::View::preferredDevice() const 370 { 371 return NS::Object::sendMessage< MTL::Device* >( this, _MTK_PRIVATE_SEL( preferredDevice ) ); 372 } 373 374 _NS_INLINE void MTK::View::setPaused( bool paused ) 375 { 376 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setPaused_ ), paused ); 377 } 378 379 _NS_INLINE bool MTK::View::isPaused() const 380 { 381 return NS::Object::sendMessage< bool >( this, _MTK_PRIVATE_SEL( isPaused ) ); 382 } 383 384 _NS_INLINE void MTK::View::setColorSpace( CGColorSpaceRef colorSpace ) 385 { 386 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( setColorspace_), colorSpace ); 387 } 388 389 _NS_INLINE CGColorSpaceRef MTK::View::colorSpace() const 390 { 391 return NS::Object::sendMessage< CGColorSpaceRef >( this, _MTK_PRIVATE_SEL( colorspace ) ); 392 } 393 394 _NS_INLINE void MTK::View::draw() 395 { 396 NS::Object::sendMessage< void >( this, _MTK_PRIVATE_SEL( draw ) ); 397 }