/ include / MetalKit / MTKView.hpp
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  }