@@ -310,6 +310,11 @@ int32_t GPUDisplayBackendOpenGL::InitBackendA()
310310 GPUError (" Unsupported OpenGL runtime %d.%d < %d.%d" , glVersion[0 ], glVersion[1 ], GPUDisplayFrontend::GL_MIN_VERSION_MAJOR , GPUDisplayFrontend::GL_MIN_VERSION_MINOR );
311311 return (1 );
312312 }
313+ for (GLenum limit : {GL_MAX_TEXTURE_SIZE , GL_MAX_RENDERBUFFER_SIZE , GL_MAX_FRAMEBUFFER_WIDTH , GL_MAX_FRAMEBUFFER_HEIGHT }) {
314+ GLint value = 0 ;
315+ glGetIntegerv (limit, &value);
316+ mMaxRenderSize = std::min<uint32_t >(mMaxRenderSize , value);
317+ }
313318 mVBOId .resize (GPUTPCGeometry::NSECTORS );
314319 CHKERR (glCreateBuffers (mVBOId .size (), mVBOId .data ()));
315320 CHKERR (glBindBuffer (GL_ARRAY_BUFFER , mVBOId [0 ]));
@@ -325,11 +330,13 @@ int32_t GPUDisplayBackendOpenGL::InitBackendA()
325330 CHKERR (mVertexShaderTexture = loadShader (GL_VERTEX_SHADER , _binary_opengl_vertexTexture_vert_spv_start, _binary_opengl_vertexTexture_vert_spv_len));
326331 CHKERR (mFragmentShaderTexture = loadShader (GL_FRAGMENT_SHADER , _binary_opengl_fragmentTexture_frag_spv_start, _binary_opengl_fragmentTexture_frag_spv_len));
327332 CHKERR (mFragmentShaderText = loadShader (GL_FRAGMENT_SHADER , _binary_opengl_fragmentText_frag_spv_start, _binary_opengl_fragmentText_frag_spv_len));
333+ CHKERR (mVertexShaderFullscreen = loadShader (GL_VERTEX_SHADER , _binary_opengl_vertexFullscreen_vert_spv_start, _binary_opengl_vertexFullscreen_vert_spv_len));
334+ CHKERR (mFragmentShaderDownsample = loadShader (GL_FRAGMENT_SHADER , _binary_opengl_fragmentDownsample_frag_spv_start, _binary_opengl_fragmentDownsample_frag_spv_len));
328335 CHKERR (mVertexShaderSmoothPoint = loadShader (GL_VERTEX_SHADER , _binary_opengl_vertexSmoothPoint_vert_spv_start, _binary_opengl_vertexSmoothPoint_vert_spv_len));
329336 CHKERR (mFragmentShaderSmoothPoint = loadShader (GL_FRAGMENT_SHADER , _binary_opengl_fragmentSmoothPoint_frag_spv_start, _binary_opengl_fragmentSmoothPoint_frag_spv_len));
330337 CHKERR (mVertexShaderSmoothLine = loadShader (GL_VERTEX_SHADER , _binary_opengl_vertexSmoothLine_vert_spv_start, _binary_opengl_vertexSmoothLine_vert_spv_len));
331338 CHKERR (mFragmentShaderSmoothLine = loadShader (GL_FRAGMENT_SHADER , _binary_opengl_fragmentSmoothLine_frag_spv_start, _binary_opengl_fragmentSmoothLine_frag_spv_len));
332- if (checkShaderStatus (mVertexShader ) || checkShaderStatus (mFragmentShader ) || checkShaderStatus (mVertexShaderSmoothPoint ) || checkShaderStatus (mFragmentShaderSmoothPoint ) || checkShaderStatus (mVertexShaderSmoothLine ) || checkShaderStatus (mFragmentShaderSmoothLine ) || checkShaderStatus (mVertexShaderTexture ) || checkShaderStatus (mFragmentShaderTexture ) || checkShaderStatus (mFragmentShaderText )) {
339+ if (checkShaderStatus (mVertexShader ) || checkShaderStatus (mFragmentShader ) || checkShaderStatus (mVertexShaderSmoothPoint ) || checkShaderStatus (mFragmentShaderSmoothPoint ) || checkShaderStatus (mVertexShaderSmoothLine ) || checkShaderStatus (mFragmentShaderSmoothLine ) || checkShaderStatus (mVertexShaderTexture ) || checkShaderStatus (mFragmentShaderTexture ) || checkShaderStatus (mFragmentShaderText ) || checkShaderStatus ( mVertexShaderFullscreen ) || checkShaderStatus ( mFragmentShaderDownsample ) ) {
333340 return 1 ;
334341 }
335342 CHKERR (mShaderProgram = glCreateProgram ());
@@ -367,6 +374,13 @@ int32_t GPUDisplayBackendOpenGL::InitBackendA()
367374 if (checkProgramStatus (mShaderProgramTexture )) {
368375 return 1 ;
369376 }
377+ CHKERR (mShaderProgramDownsample = glCreateProgram ());
378+ CHKERR (glAttachShader (mShaderProgramDownsample , mVertexShaderFullscreen ));
379+ CHKERR (glAttachShader (mShaderProgramDownsample , mFragmentShaderDownsample ));
380+ CHKERR (glLinkProgram (mShaderProgramDownsample ));
381+ if (checkProgramStatus (mShaderProgramDownsample )) {
382+ return 1 ;
383+ }
370384 CHKERR (glGenVertexArrays (1 , &mVertexArray ));
371385
372386 CHKERR (glGenVertexArrays (1 , &VAO_texture));
@@ -399,6 +413,9 @@ void GPUDisplayBackendOpenGL::ExitBackendA()
399413 CHKERR (glDeleteProgram (mShaderProgramText ));
400414 CHKERR (glDeleteShader (mFragmentShaderText ));
401415 CHKERR (glDeleteProgram (mShaderProgramTexture ));
416+ CHKERR (glDeleteProgram (mShaderProgramDownsample ));
417+ CHKERR (glDeleteShader (mVertexShaderFullscreen ));
418+ CHKERR (glDeleteShader (mFragmentShaderDownsample ));
402419 CHKERR (glDeleteShader (mVertexShaderTexture ));
403420 CHKERR (glDeleteShader (mFragmentShaderTexture ));
404421
@@ -548,8 +565,10 @@ void GPUDisplayBackendOpenGL::finishDraw(bool doScreenshot, bool toMixBuffer, fl
548565 setFrameBuffer (mDownsampleFactor != 1 ? mOffscreenBuffer .fb_id : 0 );
549566 mixImages (includeMixImage);
550567 }
551- if (mDownsampleFactor != 1 && !toMixBuffer) {
568+ if (mDownsampleFactor == 2 && !toMixBuffer) { // The linear blit is only exact for factor 2
552569 CHKERR (glBlitNamedFramebuffer (mOffscreenBuffer .fb_id , 0 , 0 , 0 , mRenderWidth , mRenderHeight , 0 , 0 , mScreenWidth , mScreenHeight , GL_COLOR_BUFFER_BIT , GL_LINEAR ));
570+ } else if (mDownsampleFactor != 1 && !toMixBuffer) {
571+ drawDownsample (mOffscreenBuffer .fbCol_id , 0 , mScreenWidth , mScreenHeight , mDownsampleFactor );
553572 }
554573
555574 if (doScreenshot && !toMixBuffer) {
@@ -565,7 +584,12 @@ void GPUDisplayBackendOpenGL::readImageToPixels()
565584 GLfb tmpBuffer;
566585 if (mDisplay ->cfgR ().drawQualityDownsampleFSAA && mDisplay ->cfgR ().screenshotScaleFactor != 1 ) {
567586 createFB (tmpBuffer, false , true , false , width, height);
568- CHKERR (glBlitNamedFramebuffer (mOffscreenBuffer .fb_id , tmpBuffer.fb_id , 0 , 0 , mRenderWidth , mRenderHeight , 0 , 0 , width, height, GL_COLOR_BUFFER_BIT , GL_LINEAR ));
587+ const int32_t factor = mRenderWidth / width;
588+ if (factor > 2 ) {
589+ drawDownsample (mOffscreenBuffer .fbCol_id , tmpBuffer.fb_id , width, height, factor);
590+ } else {
591+ CHKERR (glBlitNamedFramebuffer (mOffscreenBuffer .fb_id , tmpBuffer.fb_id , 0 , 0 , mRenderWidth , mRenderHeight , 0 , 0 , width, height, GL_COLOR_BUFFER_BIT , GL_LINEAR ));
592+ }
569593 }
570594 setFrameBuffer (tmpBuffer.created ? tmpBuffer.fb_id : (scaleFactor != 1 ? mOffscreenBuffer .fb_id : 0 ));
571595 CHKERR (glPixelStorei (GL_PACK_ALIGNMENT , 1 ));
@@ -611,6 +635,25 @@ void GPUDisplayBackendOpenGL::finishText()
611635 }
612636}
613637
638+ void GPUDisplayBackendOpenGL::drawDownsample (uint32_t srcTexture, uint32_t dstFramebuffer, uint32_t width, uint32_t height, int32_t factor)
639+ {
640+ setFrameBuffer (dstFramebuffer);
641+ CHKERR (glViewport (0 , 0 , width, height));
642+ CHKERR (glDisable (GL_DEPTH_TEST ));
643+ CHKERR (glDisable (GL_BLEND ));
644+ CHKERR (glUseProgram (mShaderProgramDownsample ));
645+ CHKERR (glUniform1i (UNIFORM_LOCATION_COLOR , factor));
646+ CHKERR (glActiveTexture (GL_TEXTURE0 ));
647+ CHKERR (glBindTexture (GL_TEXTURE_2D , srcTexture));
648+ CHKERR (glBindVertexArray (VAO_texture)); // Any VAO, the full-screen triangle has no vertex input
649+ CHKERR (glDrawArrays (GL_TRIANGLES , 0 , 3 ));
650+ CHKERR (glBindVertexArray (0 ));
651+ CHKERR (glBindTexture (GL_TEXTURE_2D , 0 ));
652+ CHKERR (glUseProgram (0 ));
653+ CHKERR (glEnable (GL_BLEND ));
654+ setDepthBuffer ();
655+ }
656+
614657void GPUDisplayBackendOpenGL::mixImages (float mixSlaveImage)
615658{
616659 hmm_mat4 proj = HMM_Orthographic (0 .f , mRenderWidth , 0 .f , mRenderHeight , -1 .f , 1 .f );
@@ -821,7 +864,7 @@ void GPUDisplayBackendOpenGL::updateRenderer(bool withScreenshot)
821864 createFB (mOffscreenBufferMSAA , false , true , true , mRenderWidth , mRenderHeight );
822865 }
823866 if (mDownsampleFactor != 1 ) {
824- createFB (mOffscreenBuffer , false , true , false , mRenderWidth , mRenderHeight );
867+ createFB (mOffscreenBuffer , mDownsampleFactor != 2 , true , false , mRenderWidth , mRenderHeight ); // Texture for shader downsampling (factor != 2), screenshot downsampling uses the shader only if this factor is != 2 as well
825868 }
826869 createFB (mMixBuffer , true , true , false , mRenderWidth , mRenderHeight );
827870 setQuality ();
0 commit comments