Badminton-Scoreboard/Classes/Unity/UnityRendering.h
2023-10-08 10:24:48 +08:00

324 lines
13 KiB
Objective-C

#pragma once
#include <stdint.h>
#ifdef __OBJC__
@class CAEAGLLayer;
@class EAGLContext;
#else
typedef struct objc_object CAEAGLLayer;
typedef struct objc_object EAGLContext;
#endif
#ifdef __OBJC__
@class CAMetalLayer;
@protocol CAMetalDrawable;
@protocol MTLDrawable;
@protocol MTLDevice;
@protocol MTLTexture;
@protocol MTLCommandBuffer;
@protocol MTLCommandQueue;
@protocol MTLCommandEncoder;
typedef id<CAMetalDrawable> CAMetalDrawableRef;
typedef id<MTLDevice> MTLDeviceRef;
typedef id<MTLTexture> MTLTextureRef;
typedef id<MTLCommandBuffer> MTLCommandBufferRef;
typedef id<MTLCommandQueue> MTLCommandQueueRef;
typedef id<MTLCommandEncoder> MTLCommandEncoderRef;
#else
typedef struct objc_object CAMetalLayer;
typedef struct objc_object* CAMetalDrawableRef;
typedef struct objc_object* MTLDeviceRef;
typedef struct objc_object* MTLTextureRef;
typedef struct objc_object* MTLCommandBufferRef;
typedef struct objc_object* MTLCommandQueueRef;
typedef struct objc_object* MTLCommandEncoderRef;
#endif
// unity internal native render buffer struct (the one you acquire in C# with RenderBuffer.GetNativeRenderBufferPtr())
struct RenderSurfaceBase;
typedef struct RenderSurfaceBase* UnityRenderBufferHandle;
// be aware that this struct is shared with unity implementation so you should absolutely not change it
typedef struct UnityRenderBufferDesc
{
unsigned width, height, depth;
unsigned samples;
int backbuffer;
} UnityRenderBufferDesc;
// trick to make structure inheritance work transparently between c/cpp
// for c we use "anonymous struct"
#ifdef __cplusplus
#define START_STRUCT(T, Base) struct T : Base {
#define END_STRUCT(T) };
#else
#define START_STRUCT(T, Base) typedef struct T { struct Base;
#define END_STRUCT(T) } T;
#endif
// we will keep objc objects in struct, so we need to explicitely mark references as strong to not confuse ARC
// please note that actual object lifetime is managed in objc++ code, so __unsafe_unretained is good enough for objc code
// DO NOT assign objects to UnityDisplaySurface* members in objc code.
// DO NOT store objects from UnityDisplaySurface* members in objc code, as this wont be caught by ARC
#ifdef __OBJC__
#ifdef __cplusplus
#define OBJC_OBJECT_PTR __strong
#else
#define OBJC_OBJECT_PTR __unsafe_unretained
#endif
#else
#define OBJC_OBJECT_PTR
#endif
// unity common rendering (display) surface
typedef struct UnityDisplaySurfaceBase
{
UnityRenderBufferHandle unityColorBuffer;
UnityRenderBufferHandle unityDepthBuffer;
UnityRenderBufferHandle systemColorBuffer;
UnityRenderBufferHandle systemDepthBuffer;
void* cvTextureCache; // CVMetalTextureCacheRef
void* cvTextureCacheTexture; // CVMetalTextureRef
void* cvPixelBuffer; // CVPixelBufferRef
unsigned targetW, targetH;
unsigned systemW, systemH;
int msaaSamples;
int useCVTextureCache; // [bool]
int srgb; // [bool]
int wideColor; // [bool]
int hdr; // [bool]
int disableDepthAndStencil; // [bool]
int allowScreenshot; // [bool] currently we allow screenshots (from script) only on main display
int memorylessDepth; // [bool]
int api; // [UnityRenderingAPI]
} UnityDisplaySurfaceBase;
// START_STRUCT confuse clang c compiler (though it is idiomatic c code that works)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-declarations"
// on iOS/tvOS: we render to the drawable directly
// and we need proxy only to delay acquiring drawable until we actually want to render to the "backbuffer"
// thus just one proxy and it will be marked as "empty" (we only need it to query texture params, like extents)
// on macOS: we render to the offscreen RT and blit to the drawable, thus we need several proxy RT
// and all of them will be full blown textures (with GPU backing)
#if PLATFORM_OSX
#define kUnityNumOffscreenSurfaces 2
#else
#define kUnityNumOffscreenSurfaces 1
#endif
// Metal display surface
START_STRUCT(UnityDisplaySurfaceMTL, UnityDisplaySurfaceBase)
OBJC_OBJECT_PTR CAMetalLayer * layer;
OBJC_OBJECT_PTR MTLDeviceRef device;
OBJC_OBJECT_PTR MTLCommandQueueRef commandQueue;
OBJC_OBJECT_PTR MTLCommandQueueRef drawableCommandQueue;
OBJC_OBJECT_PTR MTLCommandBufferRef presentCB;
OBJC_OBJECT_PTR CAMetalDrawableRef drawable;
OBJC_OBJECT_PTR MTLTextureRef drawableProxyRT[kUnityNumOffscreenSurfaces];
int drawableProxyNeedsClear[kUnityNumOffscreenSurfaces]; // [bool] Tracks whether the drawableProxy requires a clear after initial creation
// This is used on a Mac with drawableProxyRT when off-screen rendering is used
int proxySwaps; // Counts times proxy RTs have swapped since surface recreated
int proxyReady; // [bool] Proxy RT has swapped since last present; frame ended
OBJC_OBJECT_PTR MTLTextureRef systemColorRB;
OBJC_OBJECT_PTR MTLTextureRef targetColorRT;
OBJC_OBJECT_PTR MTLTextureRef targetAAColorRT;
OBJC_OBJECT_PTR MTLTextureRef depthRB;
OBJC_OBJECT_PTR MTLTextureRef stencilRB;
unsigned colorFormat; // [MTLPixelFormat]
unsigned depthFormat; // [MTLPixelFormat]
int framebufferOnly;
END_STRUCT(UnityDisplaySurfaceMTL)
// START_STRUCT confuse clang c compiler (though it is idiomatic c code that works)
#pragma clang diagnostic pop
// be aware that this enum is shared with unity implementation so you should absolutely not change it
typedef enum UnityRenderingAPI
{
apiMetal = 4,
// command line argument: -nographics
// does not initialize real graphics device and bypass all the rendering
// currently supported only on simulators
apiNoGraphics = -1,
} UnityRenderingAPI;
typedef struct RenderingSurfaceParams
{
// rendering setup
int msaaSampleCount;
int renderW;
int renderH;
int srgb;
int wideColor;
int hdr;
int metalFramebufferOnly;
int metalMemorylessDepth;
// unity setup
int disableDepthAndStencil;
int useCVTextureCache;
} RenderingSurfaceParams;
#ifdef __cplusplus
extern "C" {
#endif
int UnitySelectedRenderingAPI(void);
#ifdef __cplusplus
} // extern "C"
#endif
// metal
#ifdef __cplusplus
extern "C" {
#endif
void InitRenderingMTL(void);
void CreateSystemRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void DestroySystemRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void CreateRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void DestroyRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface);
void CreateSharedDepthbufferMTL(UnityDisplaySurfaceMTL* surface);
void DestroySharedDepthbufferMTL(UnityDisplaySurfaceMTL* surface);
void CreateUnityRenderBuffersMTL(UnityDisplaySurfaceMTL* surface);
void DestroyUnityRenderBuffersMTL(UnityDisplaySurfaceMTL* surface);
void StartFrameRenderingMTL(UnityDisplaySurfaceMTL* surface);
void EndFrameRenderingMTL(UnityDisplaySurfaceMTL* surface);
void PreparePresentMTL(UnityDisplaySurfaceMTL* surface);
void PresentMTL(UnityDisplaySurfaceMTL* surface);
// Acquires CAMetalDrawable resource for the surface and returns the drawable texture
MTLTextureRef AcquireDrawableMTL(UnityDisplaySurfaceMTL* surface);
unsigned UnityHDRSurfaceDepth(void);
// starting with ios11 apple insists on having just one presentDrawable per command buffer
// hence we keep normal processing for main screen, but when airplay is used we will create extra command buffers
void PreparePresentNonMainScreenMTL(UnityDisplaySurfaceMTL* surface);
void SetDrawableSizeMTL(UnityDisplaySurfaceMTL* surface, int width, int height);
#ifdef __cplusplus
} // extern "C"
#endif
// no graphics
#ifdef __cplusplus
extern "C" {
#endif
void InitRenderingNULL(void);
void CreateSystemRenderingSurfaceNULL(UnityDisplaySurfaceBase* surface);
void CreateRenderingSurfaceNULL(UnityDisplaySurfaceBase* surface);
void DestroyRenderingSurfaceNULL(UnityDisplaySurfaceBase* surface);
void CreateSharedDepthbufferNULL(UnityDisplaySurfaceBase* surface);
void DestroySharedDepthbufferNULL(UnityDisplaySurfaceBase* surface);
void CreateUnityRenderBuffersNULL(UnityDisplaySurfaceBase* surface);
void DestroySystemRenderingSurfaceNULL(UnityDisplaySurfaceBase* surface);
void DestroyUnityRenderBuffersNULL(UnityDisplaySurfaceBase* surface);
void StartFrameRenderingNULL(UnityDisplaySurfaceBase* surface);
void EndFrameRenderingNULL(UnityDisplaySurfaceBase* surface);
void PreparePresentNULL(UnityDisplaySurfaceBase* surface);
void PresentNULL(UnityDisplaySurfaceBase* surface);
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// for Create* functions if surf is null we will actuially create new one, otherwise we update the one provided
// metal: resolveTex should be non-nil only if tex have AA
UnityRenderBufferHandle UnityCreateExternalSurfaceMTL(UnityRenderBufferHandle surf, int isColor, MTLTextureRef tex, const UnityRenderBufferDesc* desc);
// Passing non-nil displaySurface will mark render surface as proxy and will do a delayed drawable acquisition when setting up framebuffer
UnityRenderBufferHandle UnityCreateExternalColorSurfaceMTL(UnityRenderBufferHandle surf, MTLTextureRef tex, MTLTextureRef resolveTex, const UnityRenderBufferDesc* desc, UnityDisplaySurfaceMTL* displaySurface);
UnityRenderBufferHandle UnityCreateExternalDepthSurfaceMTL(UnityRenderBufferHandle surf, MTLTextureRef tex, MTLTextureRef stencilTex, const UnityRenderBufferDesc* desc);
// creates "dummy" surface - will indicate "missing" buffer (e.g. depth-only RT will have color as dummy)
UnityRenderBufferHandle UnityCreateDummySurface(UnityRenderBufferHandle surf, int isColor, const UnityRenderBufferDesc* desc);
// disable rendering to render buffers (all Cameras that were rendering to one of buffers would be reset to use backbuffer)
void UnityDisableRenderBuffers(UnityRenderBufferHandle color, UnityRenderBufferHandle depth);
// destroys render buffer
void UnityDestroyExternalSurface(UnityRenderBufferHandle surf);
// sets current render target
void UnitySetRenderTarget(UnityRenderBufferHandle color, UnityRenderBufferHandle depth);
// final blit to backbuffer
void UnityBlitToBackbuffer(UnityRenderBufferHandle srcColor, UnityRenderBufferHandle dstColor, UnityRenderBufferHandle dstDepth);
// get native renderbuffer from handle
// sets vSync on OSX 10.13 and up
#if PLATFORM_OSX
void MetalUpdateDisplaySync(void);
#endif
UnityRenderBufferHandle UnityNativeRenderBufferFromHandle(void *rb);
MTLCommandBufferRef UnityCurrentMTLCommandBuffer(void);
void UnityUpdateDrawableSize(UnityDisplaySurfaceMTL* surface);
#ifdef __cplusplus
} // extern "C"
#endif
// metal/gles unification
#define GLES_METAL_COMMON_IMPL_SURF(f) \
inline void f(UnityDisplaySurfaceBase* surface) \
{ \
switch(surface->api) { \
case apiMetal: f ## MTL((UnityDisplaySurfaceMTL*)surface); break; \
case apiNoGraphics: f ## NULL(surface); break; \
} \
} \
#define GLES_METAL_COMMON_IMPL(f) \
inline void f() \
{ \
switch(UnitySelectedRenderingAPI()) { \
case apiMetal: f ## MTL(); break; \
case apiNoGraphics: f ## NULL(); break; \
} \
} \
GLES_METAL_COMMON_IMPL(InitRendering);
GLES_METAL_COMMON_IMPL_SURF(CreateSystemRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(DestroySystemRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(CreateRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(DestroyRenderingSurface);
GLES_METAL_COMMON_IMPL_SURF(CreateSharedDepthbuffer);
GLES_METAL_COMMON_IMPL_SURF(DestroySharedDepthbuffer);
GLES_METAL_COMMON_IMPL_SURF(CreateUnityRenderBuffers);
GLES_METAL_COMMON_IMPL_SURF(DestroyUnityRenderBuffers);
GLES_METAL_COMMON_IMPL_SURF(StartFrameRendering);
GLES_METAL_COMMON_IMPL_SURF(EndFrameRendering);
GLES_METAL_COMMON_IMPL_SURF(PreparePresent);
GLES_METAL_COMMON_IMPL_SURF(Present);
#undef GLES_METAL_COMMON_IMPL_SURF
#undef GLES_METAL_COMMON_IMPL