void FOpenGLDynamicRHI::RHIResizeViewport(FViewportRHIParamRef ViewportRHI,uint32 SizeX,uint32 SizeY,bool bIsFullscreen) { FOpenGLViewport* Viewport = ResourceCast(ViewportRHI); check( IsInGameThread() ); //#if !PLATFORM_MAC // SCOPED_SUSPEND_RENDERING_THREAD(true); //#endif Viewport->Resize(SizeX,SizeY,bIsFullscreen); }
bool PlatformBlitToViewport( FPlatformOpenGLDevice* Device, const FOpenGLViewport& Viewport, uint32 BackbufferSizeX, uint32 BackbufferSizeY, bool bPresent,bool bLockToVsync, int32 SyncInterval ) { if (Viewport.GetCustomPresent()) { Viewport.GetCustomPresent()->Present(SyncInterval); } else { AndroidEGL::GetInstance()->SwapBuffers(); } return true; }
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; }
FTexture2DRHIRef FOpenGLDynamicRHI::RHIGetViewportBackBuffer(FViewportRHIParamRef ViewportRHI) { FOpenGLViewport* Viewport = ResourceCast(ViewportRHI); return Viewport->GetBackBuffer(); }
void FOpenGLDynamicRHI::RHIEndDrawingViewport(FViewportRHIParamRef ViewportRHI,bool bPresent,bool bLockToVsync) { VERIFY_GL_SCOPE(); FOpenGLViewport* Viewport = ResourceCast(ViewportRHI); SCOPE_CYCLE_COUNTER(STAT_OpenGLPresentTime); check(DrawingViewport.GetReference() == Viewport); FOpenGLTexture2D* BackBuffer = Viewport->GetBackBuffer(); bool bNeedFinishFrame = PlatformBlitToViewport(PlatformDevice, *Viewport, BackBuffer->GetSizeX(), BackBuffer->GetSizeY(), bPresent, bLockToVsync, RHIOpenGLConsoleVariables::SyncInterval ); // Always consider the Framebuffer in the rendering context dirty after the blit RenderingContextState.Framebuffer = -1; DrawingViewport = NULL; // Don't wait on the GPU when using SLI, let the driver determine how many frames behind the GPU should be allowed to get if (GNumActiveGPUsForRendering == 1) { if (bNeedFinishFrame) { static const auto CFinishFrameVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.FinishCurrentFrame")); if (!CFinishFrameVar->GetValueOnRenderThread()) { // Wait for the GPU to finish rendering the previous frame before finishing this frame. Viewport->WaitForFrameEventCompletion(); Viewport->IssueFrameEvent(); } else { // Finish current frame immediately to reduce latency Viewport->IssueFrameEvent(); Viewport->WaitForFrameEventCompletion(); } } // If the input latency timer has been triggered, block until the GPU is completely // finished displaying this frame and calculate the delta time. if ( GInputLatencyTimer.RenderThreadTrigger ) { Viewport->WaitForFrameEventCompletion(); uint32 EndTime = FPlatformTime::Cycles(); GInputLatencyTimer.DeltaTime = EndTime - GInputLatencyTimer.StartTime; GInputLatencyTimer.RenderThreadTrigger = false; } } if (bRevertToSharedContextAfterDrawingViewport) { PlatformSharedContextSetup(PlatformDevice); bRevertToSharedContextAfterDrawingViewport = 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; }