123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- #include <QuartzCore/QuartzCore.h>
- #include <stdio.h>
- #include "GlesHelper.h"
- #include "UnityAppController.h"
- #include "DisplayManager.h"
- #include "EAGLContextHelper.h"
- #include "CVTextureCache.h"
- #include "InternalProfiler.h"
- // here goes some gles magic
- // we include gles3 header so we will use gles3 constants.
- // sure all the actual gles3 is guarded (and constants are staying same)
- #include <OpenGLES/ES3/gl.h>
- #include <OpenGLES/ES3/glext.h>
- // here are the prototypes for gles2 ext functions that moved to core in gles3
- extern "C" void glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum* attachments);
- extern "C" void glRenderbufferStorageMultisampleAPPLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
- extern "C" void glResolveMultisampleFramebufferAPPLE(void);
- #define SAFE_GL_DELETE(func, obj) do { if(obj) { func(1,&obj); obj = 0; } } while(0)
- #define DISCARD_FBO(ctx, fbo, cnt, att) \
- do{ \
- if(surface->context.API >= 3) glInvalidateFramebuffer(fbo, cnt, att);\
- else if(_supportsDiscard) glDiscardFramebufferEXT(fbo, cnt, att);\
- } while(0)
- #define CREATE_RB_AA(ctx, aa, fmt, w, h) \
- do{ \
- if(surface->context.API >= 3) glRenderbufferStorageMultisample(GL_RENDERBUFFER, aa, fmt, w, h); \
- else if(_supportsDiscard) glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, aa, fmt, w, h);\
- } while(0)
- static bool _supportsDiscard = false;
- static bool _supportsPackedStencil = false;
- extern "C" void InitRenderingGLES()
- {
- int api = UnitySelectedRenderingAPI();
- assert(api == apiOpenGLES2 || api == apiOpenGLES3);
- _supportsDiscard = api == apiOpenGLES2 ? UnityHasRenderingAPIExtension("GL_EXT_discard_framebuffer") : true;
- _supportsMSAA = api == apiOpenGLES2 ? UnityHasRenderingAPIExtension("GL_APPLE_framebuffer_multisample") : true;
- _supportsPackedStencil = api == apiOpenGLES2 ? UnityHasRenderingAPIExtension("GL_OES_packed_depth_stencil") : true;
- }
- extern "C" void CreateSystemRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- DestroySystemRenderingSurfaceGLES(surface);
- surface->layer.opaque = YES;
- surface->layer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking: @(FALSE), kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8 };
- surface->colorFormat = GL_RGBA8;
- glGenRenderbuffers(1, &surface->systemColorRB);
- glBindRenderbuffer(GL_RENDERBUFFER, surface->systemColorRB);
- AllocateRenderBufferStorageFromEAGLLayer((__bridge void*)surface->context, (__bridge void*)surface->layer);
- glGenFramebuffers(1, &surface->systemFB);
- UnityBindFramebuffer(kDrawFramebuffer, surface->systemFB);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, surface->systemColorRB);
- }
- extern "C" void CreateRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- DestroyRenderingSurfaceGLES(surface);
- bool needRenderingSurface = surface->targetW != surface->systemW || surface->targetH != surface->systemH || surface->useCVTextureCache;
- if (needRenderingSurface)
- {
- GLint oldTexBinding = 0;
- if (surface->useCVTextureCache)
- surface->cvTextureCache = CreateCVTextureCache();
- if (surface->cvTextureCache)
- {
- surface->cvTextureCacheTexture = CreateReadableRTFromCVTextureCache(surface->cvTextureCache, surface->targetW, surface->targetH, &surface->cvPixelBuffer);
- surface->targetColorRT = GetGLTextureFromCVTextureCache(surface->cvTextureCacheTexture);
- }
- else
- {
- glGenTextures(1, &surface->targetColorRT);
- }
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexBinding);
- glBindTexture(GL_TEXTURE_2D, surface->targetColorRT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GLES_UPSCALE_FILTER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GLES_UPSCALE_FILTER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- if (!surface->cvTextureCache)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->targetW, surface->targetH, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- glGenFramebuffers(1, &surface->targetFB);
- UnityBindFramebuffer(kDrawFramebuffer, surface->targetFB);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, surface->targetColorRT, 0);
- glBindTexture(GL_TEXTURE_2D, oldTexBinding);
- }
- if (_supportsMSAA && surface->msaaSamples > 1)
- {
- glGenRenderbuffers(1, &surface->msaaColorRB);
- glBindRenderbuffer(GL_RENDERBUFFER, surface->msaaColorRB);
- glGenFramebuffers(1, &surface->msaaFB);
- UnityBindFramebuffer(kDrawFramebuffer, surface->msaaFB);
- CREATE_RB_AA(surface->context, surface->msaaSamples, surface->colorFormat, surface->targetW, surface->targetH);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, surface->msaaColorRB);
- }
- }
- extern "C" void CreateSharedDepthbufferGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- DestroySharedDepthbufferGLES(surface);
- if (surface->disableDepthAndStencil)
- return;
- surface->depthFormat = GL_DEPTH_COMPONENT24;
- if (_supportsPackedStencil)
- surface->depthFormat = GL_DEPTH24_STENCIL8;
- glGenRenderbuffers(1, &surface->depthRB);
- glBindRenderbuffer(GL_RENDERBUFFER, surface->depthRB);
- bool needMSAA = _supportsMSAA && surface->msaaSamples > 1;
- if (needMSAA)
- CREATE_RB_AA(surface->context, surface->msaaSamples, surface->depthFormat, surface->targetW, surface->targetH);
- if (!needMSAA)
- glRenderbufferStorage(GL_RENDERBUFFER, surface->depthFormat, surface->targetW, surface->targetH);
- if (surface->msaaFB)
- UnityBindFramebuffer(kDrawFramebuffer, surface->msaaFB);
- else if (surface->targetFB)
- UnityBindFramebuffer(kDrawFramebuffer, surface->targetFB);
- else
- UnityBindFramebuffer(kDrawFramebuffer, surface->systemFB);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, surface->depthRB);
- if (_supportsPackedStencil)
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, surface->depthRB);
- }
- extern "C" void CreateUnityRenderBuffersGLES(UnityDisplaySurfaceGLES* surface)
- {
- UnityRenderBufferDesc target_desc = {surface->targetW, surface->targetH, 1, (unsigned int)surface->msaaSamples, 1};
- UnityRenderBufferDesc system_desc = {surface->systemW, surface->systemH, 1, 1, 1};
- {
- unsigned texid = 0, rbid = 0, fbo = 0;
- if (surface->msaaFB)
- {
- rbid = surface->msaaColorRB;
- fbo = surface->msaaFB;
- }
- else if (surface->targetFB)
- {
- texid = surface->targetColorRT;
- fbo = surface->targetFB;
- }
- else
- {
- rbid = surface->systemColorRB;
- fbo = surface->systemFB;
- }
- surface->unityColorBuffer = UnityCreateExternalSurfaceGLES(surface->unityColorBuffer, true, texid, rbid, surface->colorFormat, &target_desc);
- if (surface->depthRB)
- surface->unityDepthBuffer = UnityCreateExternalSurfaceGLES(surface->unityDepthBuffer, false, 0, surface->depthRB, surface->depthFormat, &target_desc);
- else
- surface->unityDepthBuffer = UnityCreateDummySurface(surface->unityDepthBuffer, false, &target_desc);
- UnityRegisterFBO(surface->unityColorBuffer, surface->unityDepthBuffer, fbo);
- }
- surface->systemColorBuffer = surface->systemDepthBuffer = 0;
- if (surface->msaaFB || surface->targetFB)
- {
- unsigned rbid = surface->systemColorRB;
- surface->systemColorBuffer = UnityCreateExternalSurfaceGLES(surface->systemColorBuffer, true, 0, rbid, surface->colorFormat, &system_desc);
- surface->systemDepthBuffer = UnityCreateDummySurface(surface->systemDepthBuffer, false, &system_desc);
- UnityRegisterFBO(surface->systemColorBuffer, surface->systemDepthBuffer, surface->systemFB);
- }
- surface->resolvedColorBuffer = 0;
- if (surface->msaaFB && surface->targetFB)
- surface->resolvedColorBuffer = UnityCreateExternalSurfaceGLES(surface->resolvedColorBuffer, true, surface->targetColorRT, 0, surface->colorFormat, &target_desc);
- }
- extern "C" void DestroySystemRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- UnityBindFramebuffer(kDrawFramebuffer, 0);
- if (surface->systemColorRB)
- {
- glBindRenderbuffer(GL_RENDERBUFFER, surface->systemColorRB);
- DeallocateRenderBufferStorageFromEAGLLayer((__bridge void*)surface->context);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glDeleteRenderbuffers(1, &surface->systemColorRB);
- surface->systemColorRB = 0;
- }
- if (surface->targetFB == 0 && surface->msaaFB == 0)
- SAFE_GL_DELETE(glDeleteRenderbuffers, surface->depthRB);
- SAFE_GL_DELETE(glDeleteFramebuffers, surface->systemFB);
- }
- extern "C" void DestroyRenderingSurfaceGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- if (surface->targetColorRT && !surface->cvTextureCache)
- {
- glDeleteTextures(1, &surface->targetColorRT); UnityOnDeleteGLTexture(surface->targetColorRT);
- surface->targetColorRT = 0;
- }
- UnityBindFramebuffer(kDrawFramebuffer, 0);
- UnityBindFramebuffer(kReadFramebuffer, 0);
- if (surface->cvTextureCacheTexture)
- CFRelease(surface->cvTextureCacheTexture);
- if (surface->cvPixelBuffer)
- CFRelease(surface->cvPixelBuffer);
- if (surface->cvTextureCache)
- CFRelease(surface->cvTextureCache);
- surface->cvTextureCache = 0;
- SAFE_GL_DELETE(glDeleteFramebuffers, surface->targetFB);
- SAFE_GL_DELETE(glDeleteRenderbuffers, surface->msaaColorRB);
- SAFE_GL_DELETE(glDeleteFramebuffers, surface->msaaFB);
- }
- extern "C" void DestroySharedDepthbufferGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- SAFE_GL_DELETE(glDeleteRenderbuffers, surface->depthRB);
- }
- extern "C" void DestroyUnityRenderBuffersGLES(UnityDisplaySurfaceGLES* surface)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- if (surface->unityColorBuffer)
- UnityDestroyExternalSurface(surface->unityColorBuffer);
- if (surface->systemColorBuffer)
- UnityDestroyExternalSurface(surface->systemColorBuffer);
- surface->unityColorBuffer = surface->systemColorBuffer = 0;
- if (surface->unityDepthBuffer)
- UnityDestroyExternalSurface(surface->unityDepthBuffer);
- if (surface->systemDepthBuffer)
- UnityDestroyExternalSurface(surface->systemDepthBuffer);
- surface->unityDepthBuffer = surface->systemDepthBuffer = 0;
- if (surface->resolvedColorBuffer)
- UnityDestroyExternalSurface(surface->resolvedColorBuffer);
- surface->resolvedColorBuffer = 0;
- }
- extern "C" void PreparePresentGLES(UnityDisplaySurfaceGLES* surface)
- {
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- if (_supportsMSAA && surface->msaaSamples > 1)
- {
- Profiler_StartMSAAResolve();
- GLuint targetFB = surface->targetFB ? surface->targetFB : surface->systemFB;
- UnityBindFramebuffer(kReadFramebuffer, surface->msaaFB);
- UnityBindFramebuffer(kDrawFramebuffer, targetFB);
- GLenum discardAttach[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
- DISCARD_FBO(surface->context, GL_READ_FRAMEBUFFER, 2, discardAttach);
- if (surface->context.API < 3)
- {
- glResolveMultisampleFramebufferAPPLE();
- }
- else
- {
- const GLint w = surface->targetW, h = surface->targetH;
- glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
- Profiler_EndMSAAResolve();
- }
- if (surface->allowScreenshot && UnityIsCaptureScreenshotRequested())
- {
- GLint targetFB = surface->targetFB ? surface->targetFB : surface->systemFB;
- UnityBindFramebuffer(kReadFramebuffer, targetFB);
- UnityCaptureScreenshot();
- }
- }
- APP_CONTROLLER_RENDER_PLUGIN_METHOD(onFrameResolved);
- if (surface->targetColorRT)
- {
- // shaders are bound to context
- EAGLContextSetCurrentAutoRestore autorestore(UnityGetMainScreenContextGLES());
- assert(surface->systemColorBuffer != 0 && surface->systemDepthBuffer != 0);
- UnityRenderBufferHandle src = surface->resolvedColorBuffer ? surface->resolvedColorBuffer : surface->unityColorBuffer;
- UnityBlitToBackbuffer(src, surface->systemColorBuffer, surface->systemDepthBuffer);
- }
- if (_supportsDiscard)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- GLenum discardAttach[] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
- if (surface->msaaFB)
- DISCARD_FBO(surface->context, GL_READ_FRAMEBUFFER, 3, discardAttach);
- if (surface->targetFB)
- {
- UnityBindFramebuffer(kDrawFramebuffer, surface->targetFB);
- DISCARD_FBO(surface->context, GL_FRAMEBUFFER, 3, discardAttach);
- }
- UnityBindFramebuffer(kDrawFramebuffer, surface->systemFB);
- DISCARD_FBO(surface->context, GL_FRAMEBUFFER, 2, &discardAttach[1]);
- }
- }
- extern "C" void PresentGLES(UnityDisplaySurfaceGLES* surface)
- {
- if (surface->context && surface->systemColorRB)
- {
- EAGLContextSetCurrentAutoRestore autorestore(surface->context);
- glBindRenderbuffer(GL_RENDERBUFFER, surface->systemColorRB);
- [surface->context presentRenderbuffer: GL_RENDERBUFFER];
- }
- }
- extern "C" void StartFrameRenderingGLES(UnityDisplaySurfaceGLES* /*surface*/)
- {
- }
- extern "C" void EndFrameRenderingGLES(UnityDisplaySurfaceGLES* /*surface*/)
- {
- }
- extern "C" void CheckGLESError(const char* file, int line)
- {
- GLenum e = glGetError();
- if (e)
- ::printf("OpenGLES error 0x%04X in %s:%i\n", e, file, line);
- }
|