bool PlatformBlitToViewport( FPlatformOpenGLDevice* Device, const FOpenGLViewport& Viewport, uint32 BackbufferSizeX, uint32 BackbufferSizeY, bool bPresent,bool bLockToVsync, int32 SyncInterval ) { if (FOpenGL::IsES2()) { AndroidEGL::GetInstance()->SwapBuffers(); } else { FPlatformOpenGLContext* const Context = Viewport.GetGLContext(); check(Context && Context->eglContext ); FScopeContext ScopeContext(Context); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //Disabling for now to work around a GL_INVALID_OPERATION which might or might not be legit in the context of EGL. //Note that the drawbuffer state is part of the FBO state, so we don't need to touch it per frame. //glDrawBuffer(GL_BACK); glBindFramebuffer(GL_READ_FRAMEBUFFER, Context->ViewportFramebuffer); glReadBuffer(GL_COLOR_ATTACHMENT0); //LOGD("PlatformBlitToViewport: backbuffer (%d, %d) to screen (%d, %d)", BackbufferSizeX, BackbufferSizeY, GRealScreenWidth, GRealScreenHeight); uint32 GRealScreenHeight, GRealScreenWidth; AndroidEGL::GetInstance()->GetDimensions( GRealScreenWidth, GRealScreenHeight); glBlitFramebuffer( 0, 0, BackbufferSizeX, BackbufferSizeY, 0, GRealScreenHeight, GRealScreenWidth, 0, GL_COLOR_BUFFER_BIT, GL_LINEAR ); if (bPresent) { uint32 IdleStart = FPlatformTime::Cycles(); AndroidEGL::GetInstance()->SwapBuffers(); REPORT_GL_END_BUFFER_EVENT_FOR_FRAME_DUMP(); // INITIATE_GL_FRAME_DUMP_EVERY_X_CALLS( 1000 ); GRenderThreadIdle[ERenderThreadIdleTypes::WaitingForGPUPresent] += FPlatformTime::Cycles() - IdleStart; GRenderThreadNumIdle[ERenderThreadIdleTypes::WaitingForGPUPresent]++; } } // return true; //Do not want WaitForFrameEventCompletion return false; }
/** * Main function for transferring data to on-screen buffers. * On Windows it temporarily switches OpenGL context, on Mac only context's output view. */ bool PlatformBlitToViewport( FPlatformOpenGLDevice* Device, const FOpenGLViewport& Viewport, uint32 BackbufferSizeX, uint32 BackbufferSizeY, bool bPresent,bool bLockToVsync, int32 SyncInterval ) { FPlatformOpenGLContext* const Context = Viewport.GetGLContext(); check(Context && Context->DeviceContext); FScopeLock ScopeLock(Device->ContextUsageGuard); { FPlatformOpenGLContext TempContext = *Context; if (Device->ViewportContexts.Num() == 1) { TempContext.OpenGLContext = Device->RenderingContext.OpenGLContext; TempContext.ViewportFramebuffer = Device->RenderingContext.ViewportFramebuffer; } FScopeContext ScopeContext(&TempContext); GLuint vfb = TempContext.ViewportFramebuffer; if (Viewport.GetCustomPresent()) { Device->TargetDirty = false; glDisable(GL_FRAMEBUFFER_SRGB); bool bShouldPresent = Viewport.GetCustomPresent()->Present(SyncInterval); glEnable(GL_FRAMEBUFFER_SRGB); if (!bShouldPresent) { return false; } else { Device->TargetDirty = true; } } if (Device->ViewportContexts.Num() == 1 && Device->TargetDirty) { glBindFramebuffer(GL_FRAMEBUFFER, TempContext.ViewportFramebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, Context->BackBufferTarget, Context->BackBufferResource, 0); FOpenGL::CheckFrameBuffer(); Device->TargetDirty = false; } glDisable(GL_FRAMEBUFFER_SRGB); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); FOpenGL::DrawBuffer(GL_BACK); glBindFramebuffer(GL_READ_FRAMEBUFFER, TempContext.ViewportFramebuffer); glReadBuffer(GL_COLOR_ATTACHMENT0); glBlitFramebuffer( 0, 0, BackbufferSizeX, BackbufferSizeY, 0, BackbufferSizeY, BackbufferSizeX, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST ); glEnable(GL_FRAMEBUFFER_SRGB); if (bPresent) { int32 RealSyncInterval = bLockToVsync ? SyncInterval : 0; if (wglSwapIntervalEXT_ProcAddress && Context->SyncInterval != RealSyncInterval) { wglSwapIntervalEXT_ProcAddress(RealSyncInterval); Context->SyncInterval = RealSyncInterval; } ::SwapBuffers(Context->DeviceContext); REPORT_GL_END_BUFFER_EVENT_FOR_FRAME_DUMP(); // INITIATE_GL_FRAME_DUMP_EVERY_X_CALLS( 1000 ); } } return true; }