2022-04-04 19:44:25 +02:00
# include "OpenGL.hpp"
# include "../Compositor.hpp"
2022-04-17 18:47:10 +02:00
# include "../helpers/MiscFunctions.hpp"
2022-04-04 19:44:25 +02:00
CHyprOpenGLImpl : : CHyprOpenGLImpl ( ) {
2022-05-25 23:29:36 +02:00
RASSERT ( eglMakeCurrent ( wlr_egl_get_display ( g_pCompositor - > m_sWLREGL ) , EGL_NO_SURFACE , EGL_NO_SURFACE , wlr_egl_get_context ( g_pCompositor - > m_sWLREGL ) ) , " Couldn't unset current EGL! " ) ;
2022-04-04 19:44:25 +02:00
auto * const EXTENSIONS = ( const char * ) glGetString ( GL_EXTENSIONS ) ;
RASSERT ( EXTENSIONS , " Couldn't retrieve openGL extensions! " ) ;
m_iDRMFD = g_pCompositor - > m_iDRMFD ;
m_szExtensions = EXTENSIONS ;
Debug : : log ( LOG , " Creating the Hypr OpenGL Renderer! " ) ;
Debug : : log ( LOG , " Using: %s " , glGetString ( GL_VERSION ) ) ;
Debug : : log ( LOG , " Vendor: %s " , glGetString ( GL_VENDOR ) ) ;
Debug : : log ( LOG , " Renderer: %s " , glGetString ( GL_RENDERER ) ) ;
Debug : : log ( LOG , " Supported extensions size: %d " , std : : count ( m_szExtensions . begin ( ) , m_szExtensions . end ( ) , ' ' ) ) ;
2022-04-13 17:34:13 +02:00
# ifdef GLES2
Debug : : log ( WARN , " !RENDERER: Using the legacy GLES2 renderer! " ) ;
# endif
2022-04-04 19:44:25 +02:00
// End shaders
2022-05-06 16:06:21 +02:00
pixman_region32_init ( & m_rOriginalDamageRegion ) ;
// End
2022-05-25 23:29:36 +02:00
RASSERT ( eglMakeCurrent ( wlr_egl_get_display ( g_pCompositor - > m_sWLREGL ) , EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT ) , " Couldn't unset current EGL! " ) ;
2022-04-04 19:44:25 +02:00
// Done!
}
GLuint CHyprOpenGLImpl : : createProgram ( const std : : string & vert , const std : : string & frag ) {
auto vertCompiled = compileShader ( GL_VERTEX_SHADER , vert ) ;
RASSERT ( vertCompiled , " Compiling shader failed. VERTEX NULL! Shader source: \n \n %s " , vert . c_str ( ) ) ;
auto fragCompiled = compileShader ( GL_FRAGMENT_SHADER , frag ) ;
RASSERT ( fragCompiled , " Compiling shader failed. FRAGMENT NULL! Shader source: \n \n %s " , frag . c_str ( ) ) ;
auto prog = glCreateProgram ( ) ;
glAttachShader ( prog , vertCompiled ) ;
glAttachShader ( prog , fragCompiled ) ;
glLinkProgram ( prog ) ;
glDetachShader ( prog , vertCompiled ) ;
glDetachShader ( prog , fragCompiled ) ;
glDeleteShader ( vertCompiled ) ;
glDeleteShader ( fragCompiled ) ;
GLint ok ;
glGetProgramiv ( prog , GL_LINK_STATUS , & ok ) ;
RASSERT ( ok ! = GL_FALSE , " createProgram() failed! GL_LINK_STATUS not OK! " ) ;
return prog ;
}
GLuint CHyprOpenGLImpl : : compileShader ( const GLuint & type , std : : string src ) {
auto shader = glCreateShader ( type ) ;
auto shaderSource = src . c_str ( ) ;
glShaderSource ( shader , 1 , ( const GLchar * * ) & shaderSource , nullptr ) ;
glCompileShader ( shader ) ;
GLint ok ;
glGetShaderiv ( shader , GL_COMPILE_STATUS , & ok ) ;
RASSERT ( ok ! = GL_FALSE , " compileShader() failed! GL_COMPILE_STATUS not OK! " ) ;
return shader ;
}
2022-07-27 12:32:00 +02:00
void CHyprOpenGLImpl : : begin ( CMonitor * pMonitor , pixman_region32_t * pDamage , bool fake ) {
2022-04-04 19:44:25 +02:00
m_RenderData . pMonitor = pMonitor ;
2022-08-12 17:10:07 +02:00
if ( eglGetCurrentContext ( ) ! = wlr_egl_get_context ( g_pCompositor - > m_sWLREGL ) ) {
eglMakeCurrent ( wlr_egl_get_display ( g_pCompositor - > m_sWLREGL ) , EGL_NO_SURFACE , EGL_NO_SURFACE , wlr_egl_get_context ( g_pCompositor - > m_sWLREGL ) ) ;
}
2022-05-18 20:33:54 +02:00
glViewport ( 0 , 0 , pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y ) ;
2022-04-04 19:44:25 +02:00
2022-06-28 11:30:07 +02:00
matrixProjection ( m_RenderData . projection , pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y , WL_OUTPUT_TRANSFORM_NORMAL ) ;
2022-04-04 19:44:25 +02:00
2022-06-29 12:54:53 +02:00
m_RenderData . pCurrentMonData = & m_mMonitorRenderResources [ pMonitor ] ;
2022-04-04 19:44:25 +02:00
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-04-05 20:49:15 +02:00
glGetIntegerv ( GL_FRAMEBUFFER_BINDING , & m_iCurrentOutputFb ) ;
2022-04-09 15:01:28 +02:00
m_iWLROutputFb = m_iCurrentOutputFb ;
// ensure a framebuffer for the monitor exists
2022-06-29 12:54:53 +02:00
if ( m_mMonitorRenderResources . find ( pMonitor ) = = m_mMonitorRenderResources . end ( ) | | m_RenderData . pCurrentMonData - > primaryFB . m_Size ! = pMonitor - > vecPixelSize ) {
m_RenderData . pCurrentMonData - > stencilTex . allocate ( ) ;
2022-04-11 16:39:48 +02:00
2022-06-29 12:54:53 +02:00
m_RenderData . pCurrentMonData - > primaryFB . m_pStencilTex = & m_RenderData . pCurrentMonData - > stencilTex ;
m_RenderData . pCurrentMonData - > mirrorFB . m_pStencilTex = & m_RenderData . pCurrentMonData - > stencilTex ;
m_RenderData . pCurrentMonData - > mirrorSwapFB . m_pStencilTex = & m_RenderData . pCurrentMonData - > stencilTex ;
2022-04-11 16:39:48 +02:00
2022-06-29 12:54:53 +02:00
m_RenderData . pCurrentMonData - > primaryFB . alloc ( pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y ) ;
m_RenderData . pCurrentMonData - > mirrorFB . alloc ( pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y ) ;
m_RenderData . pCurrentMonData - > mirrorSwapFB . alloc ( pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y ) ;
2022-09-13 15:25:42 +02:00
m_RenderData . pCurrentMonData - > monitorMirrorFB . alloc ( pMonitor - > vecPixelSize . x , pMonitor - > vecPixelSize . y ) ;
2022-04-11 16:39:48 +02:00
2022-04-10 14:32:18 +02:00
createBGTextureForMonitor ( pMonitor ) ;
}
2022-04-09 15:01:28 +02:00
2022-08-11 20:29:21 +02:00
if ( ! m_RenderData . pCurrentMonData - > m_bShadersInitialized )
initShaders ( ) ;
2022-04-11 16:39:48 +02:00
// bind the primary Hypr Framebuffer
2022-06-29 12:54:53 +02:00
m_RenderData . pCurrentMonData - > primaryFB . bind ( ) ;
2022-04-14 16:43:29 +02:00
m_RenderData . pDamage = pDamage ;
2022-05-18 20:33:54 +02:00
m_bFakeFrame = fake ;
2022-04-04 19:44:25 +02:00
}
void CHyprOpenGLImpl : : end ( ) {
2022-04-09 15:01:28 +02:00
// end the render, copy the data to the WLR framebuffer
2022-05-18 20:33:54 +02:00
if ( ! m_bFakeFrame ) {
2022-09-13 15:25:42 +02:00
pixman_region32_copy ( m_RenderData . pDamage , & m_rOriginalDamageRegion ) ;
if ( ! m_RenderData . pMonitor - > mirrors . empty ( ) )
g_pHyprOpenGL - > saveBufferForMirror ( ) ; // save with original damage region
2022-05-18 20:33:54 +02:00
glBindFramebuffer ( GL_FRAMEBUFFER , m_iWLROutputFb ) ;
2022-05-29 12:27:45 +02:00
wlr_box monbox = { 0 , 0 , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y } ;
2022-04-09 15:01:28 +02:00
2022-05-18 20:33:54 +02:00
clear ( CColor ( 11 , 11 , 11 , 255 ) ) ;
2022-04-09 15:01:28 +02:00
2022-05-29 12:27:45 +02:00
m_bEndFrame = true ;
2022-06-29 12:54:53 +02:00
renderTexture ( m_RenderData . pCurrentMonData - > primaryFB . m_cTex , & monbox , 255.f , 0 ) ;
2022-05-29 12:27:45 +02:00
m_bEndFrame = false ;
2022-05-18 20:33:54 +02:00
}
2022-04-09 15:01:28 +02:00
// reset our data
2022-04-04 19:44:25 +02:00
m_RenderData . pMonitor = nullptr ;
2022-04-09 15:01:28 +02:00
m_iWLROutputFb = 0 ;
2022-04-04 19:44:25 +02:00
}
2022-08-11 20:29:21 +02:00
void CHyprOpenGLImpl : : initShaders ( ) {
GLuint prog = createProgram ( QUADVERTSRC , QUADFRAGSRC ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . program = prog ;
m_RenderData . pCurrentMonData - > m_shQUAD . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . color = glGetUniformLocation ( prog , " color " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . topLeft = glGetUniformLocation ( prog , " topLeft " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . bottomRight = glGetUniformLocation ( prog , " bottomRight " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . fullSize = glGetUniformLocation ( prog , " fullSize " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shQUAD . primitiveMultisample = glGetUniformLocation ( prog , " primitiveMultisample " ) ;
prog = createProgram ( TEXVERTSRC , TEXFRAGSRCRGBA ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . program = prog ;
m_RenderData . pCurrentMonData - > m_shRGBA . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . tex = glGetUniformLocation ( prog , " tex " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . alpha = glGetUniformLocation ( prog , " alpha " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . discardOpaque = glGetUniformLocation ( prog , " discardOpaque " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . topLeft = glGetUniformLocation ( prog , " topLeft " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . bottomRight = glGetUniformLocation ( prog , " bottomRight " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . fullSize = glGetUniformLocation ( prog , " fullSize " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . primitiveMultisample = glGetUniformLocation ( prog , " primitiveMultisample " ) ;
2022-08-30 12:46:17 +02:00
m_RenderData . pCurrentMonData - > m_shRGBA . applyTint = glGetUniformLocation ( prog , " applyTint " ) ;
m_RenderData . pCurrentMonData - > m_shRGBA . tint = glGetUniformLocation ( prog , " tint " ) ;
2022-08-11 20:29:21 +02:00
prog = createProgram ( TEXVERTSRC , TEXFRAGSRCRGBX ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . program = prog ;
m_RenderData . pCurrentMonData - > m_shRGBX . tex = glGetUniformLocation ( prog , " tex " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . alpha = glGetUniformLocation ( prog , " alpha " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . discardOpaque = glGetUniformLocation ( prog , " discardOpaque " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . topLeft = glGetUniformLocation ( prog , " topLeft " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . bottomRight = glGetUniformLocation ( prog , " bottomRight " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . fullSize = glGetUniformLocation ( prog , " fullSize " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . primitiveMultisample = glGetUniformLocation ( prog , " primitiveMultisample " ) ;
2022-08-30 12:46:17 +02:00
m_RenderData . pCurrentMonData - > m_shRGBX . applyTint = glGetUniformLocation ( prog , " applyTint " ) ;
m_RenderData . pCurrentMonData - > m_shRGBX . tint = glGetUniformLocation ( prog , " tint " ) ;
2022-08-11 20:29:21 +02:00
prog = createProgram ( TEXVERTSRC , TEXFRAGSRCEXT ) ;
m_RenderData . pCurrentMonData - > m_shEXT . program = prog ;
m_RenderData . pCurrentMonData - > m_shEXT . tex = glGetUniformLocation ( prog , " tex " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . alpha = glGetUniformLocation ( prog , " alpha " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . discardOpaque = glGetUniformLocation ( prog , " discardOpaque " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . topLeft = glGetUniformLocation ( prog , " topLeft " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . bottomRight = glGetUniformLocation ( prog , " bottomRight " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . fullSize = glGetUniformLocation ( prog , " fullSize " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . primitiveMultisample = glGetUniformLocation ( prog , " primitiveMultisample " ) ;
2022-08-30 12:46:17 +02:00
m_RenderData . pCurrentMonData - > m_shEXT . applyTint = glGetUniformLocation ( prog , " applyTint " ) ;
m_RenderData . pCurrentMonData - > m_shEXT . tint = glGetUniformLocation ( prog , " tint " ) ;
2022-08-11 20:29:21 +02:00
prog = createProgram ( TEXVERTSRC , FRAGBLUR1 ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . program = prog ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . tex = glGetUniformLocation ( prog , " tex " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . alpha = glGetUniformLocation ( prog , " alpha " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR1 . halfpixel = glGetUniformLocation ( prog , " halfpixel " ) ;
prog = createProgram ( TEXVERTSRC , FRAGBLUR2 ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . program = prog ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . tex = glGetUniformLocation ( prog , " tex " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . alpha = glGetUniformLocation ( prog , " alpha " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shBLUR2 . halfpixel = glGetUniformLocation ( prog , " halfpixel " ) ;
prog = createProgram ( QUADVERTSRC , FRAGSHADOW ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . program = prog ;
m_RenderData . pCurrentMonData - > m_shSHADOW . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . topLeft = glGetUniformLocation ( prog , " topLeft " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . bottomRight = glGetUniformLocation ( prog , " bottomRight " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . fullSize = glGetUniformLocation ( prog , " fullSize " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . range = glGetUniformLocation ( prog , " range " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . shadowPower = glGetUniformLocation ( prog , " shadowPower " ) ;
m_RenderData . pCurrentMonData - > m_shSHADOW . color = glGetUniformLocation ( prog , " color " ) ;
prog = createProgram ( QUADVERTSRC , FRAGBORDER1 ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . program = prog ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . proj = glGetUniformLocation ( prog , " proj " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . thick = glGetUniformLocation ( prog , " thick " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . texAttrib = glGetAttribLocation ( prog , " texcoord " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . topLeft = glGetUniformLocation ( prog , " topLeft " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . bottomRight = glGetUniformLocation ( prog , " bottomRight " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . fullSize = glGetUniformLocation ( prog , " fullSize " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . radius = glGetUniformLocation ( prog , " radius " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . primitiveMultisample = glGetUniformLocation ( prog , " primitiveMultisample " ) ;
m_RenderData . pCurrentMonData - > m_shBORDER1 . color = glGetUniformLocation ( prog , " color " ) ;
m_RenderData . pCurrentMonData - > m_bShadersInitialized = true ;
Debug : : log ( LOG , " Shaders initialized successfully. " ) ;
}
2022-04-04 19:44:25 +02:00
void CHyprOpenGLImpl : : clear ( const CColor & color ) {
RASSERT ( m_RenderData . pMonitor , " Tried to render without begin()! " ) ;
glClearColor ( color . r / 255.f , color . g / 255.f , color . b / 255.f , color . a / 255.f ) ;
2022-04-14 16:43:29 +02:00
if ( pixman_region32_not_empty ( m_RenderData . pDamage ) ) {
PIXMAN_DAMAGE_FOREACH ( m_RenderData . pDamage ) {
const auto RECT = RECTSARR [ i ] ;
scissor ( & RECT ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
}
}
2022-04-14 17:00:35 +02:00
scissor ( ( wlr_box * ) nullptr ) ;
2022-04-04 19:44:25 +02:00
}
2022-09-04 19:27:38 +02:00
void CHyprOpenGLImpl : : scissor ( const wlr_box * pBox , bool transform ) {
2022-04-04 21:45:35 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to scissor without begin()! " ) ;
2022-05-18 20:35:24 +02:00
if ( ! pBox ) {
2022-04-04 19:44:25 +02:00
glDisable ( GL_SCISSOR_TEST ) ;
return ;
}
2022-05-29 12:27:45 +02:00
wlr_box newBox = * pBox ;
2022-09-04 19:27:38 +02:00
if ( transform ) {
int w , h ;
wlr_output_transformed_resolution ( m_RenderData . pMonitor - > output , & w , & h ) ;
2022-05-29 12:27:45 +02:00
2022-09-04 19:27:38 +02:00
const auto TR = wlr_output_transform_invert ( m_RenderData . pMonitor - > transform ) ;
wlr_box_transform ( & newBox , & newBox , TR , w , h ) ;
}
2022-05-29 12:27:45 +02:00
glScissor ( newBox . x , newBox . y , newBox . width , newBox . height ) ;
2022-04-04 19:44:25 +02:00
glEnable ( GL_SCISSOR_TEST ) ;
2022-04-04 21:45:35 +02:00
}
2022-09-04 19:27:38 +02:00
void CHyprOpenGLImpl : : scissor ( const pixman_box32 * pBox , bool transform ) {
2022-04-14 16:43:29 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to scissor without begin()! " ) ;
2022-05-18 20:35:24 +02:00
if ( ! pBox ) {
2022-04-14 16:43:29 +02:00
glDisable ( GL_SCISSOR_TEST ) ;
return ;
}
2022-05-29 12:27:45 +02:00
wlr_box newBox = { pBox - > x1 , pBox - > y1 , pBox - > x2 - pBox - > x1 , pBox - > y2 - pBox - > y1 } ;
2022-09-04 19:27:38 +02:00
scissor ( & newBox , transform ) ;
2022-04-14 16:43:29 +02:00
}
2022-09-04 19:27:38 +02:00
void CHyprOpenGLImpl : : scissor ( const int x , const int y , const int w , const int h , bool transform ) {
2022-05-02 16:54:40 +02:00
wlr_box box = { x , y , w , h } ;
2022-09-04 19:27:38 +02:00
scissor ( & box , transform ) ;
2022-05-02 16:54:40 +02:00
}
2022-05-17 13:16:37 +02:00
void CHyprOpenGLImpl : : renderRect ( wlr_box * box , const CColor & col , int round ) {
2022-06-21 23:09:20 +02:00
renderRectWithDamage ( box , col , m_RenderData . pDamage , round ) ;
}
void CHyprOpenGLImpl : : renderRectWithDamage ( wlr_box * box , const CColor & col , pixman_region32_t * damage , int round ) {
2022-04-04 21:45:35 +02:00
RASSERT ( ( box - > width > 0 & & box - > height > 0 ) , " Tried to render rect with width/height < 0! " ) ;
RASSERT ( m_RenderData . pMonitor , " Tried to render rect without begin()! " ) ;
float matrix [ 9 ] ;
2022-05-29 12:27:45 +02:00
wlr_matrix_project_box ( matrix , box , wlr_output_transform_invert ( ! m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData . pMonitor - > transform ) , 0 , m_RenderData . pMonitor - > output - > transform_matrix ) ; // TODO: write own, don't use WLR here
2022-04-04 21:45:35 +02:00
float glMatrix [ 9 ] ;
wlr_matrix_multiply ( glMatrix , m_RenderData . projection , matrix ) ;
wlr_matrix_multiply ( glMatrix , matrixFlip180 , glMatrix ) ;
wlr_matrix_transpose ( glMatrix , glMatrix ) ;
2022-05-17 13:16:37 +02:00
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-04-04 21:45:35 +02:00
2022-08-11 20:29:21 +02:00
glUseProgram ( m_RenderData . pCurrentMonData - > m_shQUAD . program ) ;
2022-04-04 21:45:35 +02:00
2022-08-11 20:29:21 +02:00
glUniformMatrix3fv ( m_RenderData . pCurrentMonData - > m_shQUAD . proj , 1 , GL_FALSE , glMatrix ) ;
glUniform4f ( m_RenderData . pCurrentMonData - > m_shQUAD . color , col . r / 255.f , col . g / 255.f , col . b / 255.f , col . a / 255.f ) ;
2022-04-04 21:45:35 +02:00
2022-05-17 13:16:37 +02:00
const auto TOPLEFT = Vector2D ( round , round ) ;
const auto BOTTOMRIGHT = Vector2D ( box - > width - round , box - > height - round ) ;
const auto FULLSIZE = Vector2D ( box - > width , box - > height ) ;
2022-06-07 20:41:40 +02:00
static auto * const PMULTISAMPLEEDGES = & g_pConfigManager - > getConfigValuePtr ( " decoration:multisample_edges " ) - > intValue ;
2022-05-17 13:16:37 +02:00
// Rounded corners
2022-08-11 20:29:21 +02:00
glUniform2f ( m_RenderData . pCurrentMonData - > m_shQUAD . topLeft , ( float ) TOPLEFT . x , ( float ) TOPLEFT . y ) ;
glUniform2f ( m_RenderData . pCurrentMonData - > m_shQUAD . bottomRight , ( float ) BOTTOMRIGHT . x , ( float ) BOTTOMRIGHT . y ) ;
glUniform2f ( m_RenderData . pCurrentMonData - > m_shQUAD . fullSize , ( float ) FULLSIZE . x , ( float ) FULLSIZE . y ) ;
glUniform1f ( m_RenderData . pCurrentMonData - > m_shQUAD . radius , round ) ;
glUniform1i ( m_RenderData . pCurrentMonData - > m_shQUAD . primitiveMultisample , ( int ) ( * PMULTISAMPLEEDGES = = 1 & & round ! = 0 ) ) ;
2022-05-17 13:16:37 +02:00
2022-08-11 20:29:21 +02:00
glVertexAttribPointer ( m_RenderData . pCurrentMonData - > m_shQUAD . posAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
glVertexAttribPointer ( m_RenderData . pCurrentMonData - > m_shQUAD . texAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
2022-04-04 21:45:35 +02:00
2022-08-11 20:29:21 +02:00
glEnableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shQUAD . posAttrib ) ;
glEnableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shQUAD . texAttrib ) ;
2022-04-04 21:45:35 +02:00
2022-06-21 23:09:20 +02:00
if ( pixman_region32_not_empty ( damage ) ) {
PIXMAN_DAMAGE_FOREACH ( damage ) {
2022-05-17 13:16:37 +02:00
const auto RECT = RECTSARR [ i ] ;
scissor ( & RECT ) ;
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
}
}
2022-04-04 21:45:35 +02:00
2022-08-11 20:29:21 +02:00
glDisableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shQUAD . posAttrib ) ;
glDisableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shQUAD . texAttrib ) ;
2022-05-17 13:16:37 +02:00
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-04-05 14:33:54 +02:00
}
2022-07-04 15:58:12 +02:00
void CHyprOpenGLImpl : : renderTexture ( wlr_texture * tex , wlr_box * pBox , float alpha , int round , bool allowCustomUV ) {
2022-04-05 14:33:54 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to render texture without begin()! " ) ;
2022-07-04 15:58:12 +02:00
renderTexture ( CTexture ( tex ) , pBox , alpha , round , false , allowCustomUV ) ;
2022-04-05 14:33:54 +02:00
}
2022-07-04 15:58:12 +02:00
void CHyprOpenGLImpl : : renderTexture ( const CTexture & tex , wlr_box * pBox , float alpha , int round , bool discardopaque , bool allowCustomUV ) {
2022-04-14 16:43:29 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to render texture without begin()! " ) ;
2022-08-30 12:46:17 +02:00
renderTextureInternalWithDamage ( tex , pBox , alpha , m_RenderData . pDamage , round , discardopaque , false , allowCustomUV , true ) ;
2022-04-14 17:00:35 +02:00
scissor ( ( wlr_box * ) nullptr ) ;
2022-04-14 16:43:29 +02:00
}
2022-08-30 12:46:17 +02:00
void CHyprOpenGLImpl : : renderTextureInternalWithDamage ( const CTexture & tex , wlr_box * pBox , float alpha , pixman_region32_t * damage , int round , bool discardOpaque , bool noAA , bool allowCustomUV , bool allowDim ) {
2022-04-05 14:33:54 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to render texture without begin()! " ) ;
RASSERT ( ( tex . m_iTexID > 0 ) , " Attempted to draw NULL texture! " ) ;
2022-08-30 12:46:17 +02:00
static auto * const PDIMINACTIVE = & g_pConfigManager - > getConfigValuePtr ( " decoration:dim_inactive " ) - > intValue ;
2022-04-14 16:43:29 +02:00
// get transform
2022-05-29 12:27:45 +02:00
const auto TRANSFORM = wlr_output_transform_invert ( ! m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData . pMonitor - > transform ) ;
2022-04-14 16:43:29 +02:00
float matrix [ 9 ] ;
wlr_matrix_project_box ( matrix , pBox , TRANSFORM , 0 , m_RenderData . pMonitor - > output - > transform_matrix ) ;
2022-04-05 14:33:54 +02:00
float glMatrix [ 9 ] ;
wlr_matrix_multiply ( glMatrix , m_RenderData . projection , matrix ) ;
wlr_matrix_multiply ( glMatrix , matrixFlip180 , glMatrix ) ;
wlr_matrix_transpose ( glMatrix , glMatrix ) ;
CShader * shader = nullptr ;
2022-04-05 17:01:44 +02:00
glEnable ( GL_BLEND ) ;
2022-05-06 16:06:21 +02:00
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-04-05 17:01:44 +02:00
2022-04-05 14:33:54 +02:00
switch ( tex . m_iType ) {
case TEXTURE_RGBA :
2022-08-11 20:29:21 +02:00
shader = & m_RenderData . pCurrentMonData - > m_shRGBA ;
2022-04-05 14:33:54 +02:00
break ;
case TEXTURE_RGBX :
2022-08-11 20:29:21 +02:00
shader = & m_RenderData . pCurrentMonData - > m_shRGBX ;
2022-04-05 14:33:54 +02:00
break ;
case TEXTURE_EXTERNAL :
2022-08-11 20:29:21 +02:00
shader = & m_RenderData . pCurrentMonData - > m_shEXT ;
2022-04-05 14:33:54 +02:00
break ;
default :
RASSERT ( false , " tex.m_iTarget unsupported! " ) ;
}
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( tex . m_iTarget , tex . m_iTexID ) ;
glTexParameteri ( tex . m_iTarget , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glUseProgram ( shader - > program ) ;
glUniformMatrix3fv ( shader - > proj , 1 , GL_FALSE , glMatrix ) ;
glUniform1i ( shader - > tex , 0 ) ;
glUniform1f ( shader - > alpha , alpha / 255.f ) ;
2022-04-17 13:15:56 +02:00
glUniform1i ( shader - > discardOpaque , ( int ) discardOpaque ) ;
2022-04-05 14:33:54 +02:00
2022-04-05 15:50:47 +02:00
// round is in px
// so we need to do some maf
const auto TOPLEFT = Vector2D ( round , round ) ;
2022-06-24 15:59:59 +02:00
const auto BOTTOMRIGHT = Vector2D ( pBox - > width - round , pBox - > height - round ) ;
const auto FULLSIZE = Vector2D ( pBox - > width , pBox - > height ) ;
2022-06-07 20:41:40 +02:00
static auto * const PMULTISAMPLEEDGES = & g_pConfigManager - > getConfigValuePtr ( " decoration:multisample_edges " ) - > intValue ;
2022-04-05 15:50:47 +02:00
// Rounded corners
2022-07-29 17:07:33 +02:00
glUniform2f ( shader - > topLeft , ( float ) TOPLEFT . x , ( float ) TOPLEFT . y ) ;
glUniform2f ( shader - > bottomRight , ( float ) BOTTOMRIGHT . x , ( float ) BOTTOMRIGHT . y ) ;
glUniform2f ( shader - > fullSize , ( float ) FULLSIZE . x , ( float ) FULLSIZE . y ) ;
glUniform1f ( shader - > radius , round ) ;
glUniform1i ( shader - > primitiveMultisample , ( int ) ( * PMULTISAMPLEEDGES = = 1 & & round ! = 0 & & ! noAA ) ) ;
2022-04-05 15:50:47 +02:00
2022-08-30 12:46:17 +02:00
if ( allowDim & & m_pCurrentWindow & & * PDIMINACTIVE & & m_pCurrentWindow ! = g_pCompositor - > m_pLastWindow ) {
glUniform1i ( shader - > applyTint , 1 ) ;
const auto DIM = m_pCurrentWindow - > m_fDimPercent . fl ( ) ;
glUniform3f ( shader - > tint , 1.f - DIM , 1.f - DIM , 1.f - DIM ) ;
} else {
glUniform1i ( shader - > applyTint , 0 ) ;
}
2022-04-05 14:33:54 +02:00
glVertexAttribPointer ( shader - > posAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
2022-06-22 15:45:56 +02:00
2022-07-19 13:36:54 +02:00
const float verts [ ] = {
m_RenderData . primarySurfaceUVBottomRight . x , m_RenderData . primarySurfaceUVTopLeft . y , // top right
m_RenderData . primarySurfaceUVTopLeft . x , m_RenderData . primarySurfaceUVTopLeft . y , // top left
m_RenderData . primarySurfaceUVBottomRight . x , m_RenderData . primarySurfaceUVBottomRight . y , // bottom right
m_RenderData . primarySurfaceUVTopLeft . x , m_RenderData . primarySurfaceUVBottomRight . y , // bottom left
} ;
2022-06-22 15:45:56 +02:00
2022-07-19 13:36:54 +02:00
if ( allowCustomUV & & m_RenderData . primarySurfaceUVTopLeft ! = Vector2D ( - 1 , - 1 ) ) {
2022-06-22 15:45:56 +02:00
glVertexAttribPointer ( shader - > texAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , verts ) ;
} else {
glVertexAttribPointer ( shader - > texAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
}
2022-04-05 14:33:54 +02:00
glEnableVertexAttribArray ( shader - > posAttrib ) ;
glEnableVertexAttribArray ( shader - > texAttrib ) ;
2022-05-10 09:56:58 +02:00
if ( pixman_region32_not_empty ( m_RenderData . pDamage ) ) {
PIXMAN_DAMAGE_FOREACH ( m_RenderData . pDamage ) {
const auto RECT = RECTSARR [ i ] ;
scissor ( & RECT ) ;
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
}
}
2022-04-05 14:33:54 +02:00
glDisableVertexAttribArray ( shader - > posAttrib ) ;
glDisableVertexAttribArray ( shader - > texAttrib ) ;
glBindTexture ( tex . m_iTarget , 0 ) ;
2022-04-05 16:47:03 +02:00
}
2022-04-24 16:41:01 +02:00
// This probably isn't the fastest
// but it works... well, I guess?
//
// Dual (or more) kawase blur
2022-05-09 21:37:41 +02:00
CFramebuffer * CHyprOpenGLImpl : : blurMainFramebufferWithDamage ( float a , wlr_box * pBox , pixman_region32_t * originalDamage ) {
2022-04-09 16:51:08 +02:00
2022-05-02 16:54:40 +02:00
glDisable ( GL_BLEND ) ;
glDisable ( GL_STENCIL_TEST ) ;
2022-04-24 16:41:01 +02:00
2022-05-02 16:54:40 +02:00
// get transforms for the full monitor
2022-09-04 19:27:38 +02:00
const auto TRANSFORM = wlr_output_transform_invert ( m_RenderData . pMonitor - > transform ) ;
2022-04-14 16:43:29 +02:00
float matrix [ 9 ] ;
2022-09-04 19:27:38 +02:00
wlr_box MONITORBOX = { 0 , 0 , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y } ;
2022-05-02 16:54:40 +02:00
wlr_matrix_project_box ( matrix , & MONITORBOX , TRANSFORM , 0 , m_RenderData . pMonitor - > output - > transform_matrix ) ;
2022-04-09 16:51:08 +02:00
float glMatrix [ 9 ] ;
2022-05-02 16:54:40 +02:00
wlr_matrix_multiply ( glMatrix , m_RenderData . projection , matrix ) ;
2022-04-09 16:51:08 +02:00
wlr_matrix_multiply ( glMatrix , matrixFlip180 , glMatrix ) ;
wlr_matrix_transpose ( glMatrix , glMatrix ) ;
2022-05-02 16:54:40 +02:00
// get the config settings
2022-06-07 20:41:40 +02:00
static auto * const PBLURSIZE = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_size " ) - > intValue ;
static auto * const PBLURPASSES = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_passes " ) - > intValue ;
2022-04-09 16:51:08 +02:00
2022-05-09 21:37:41 +02:00
// prep damage
pixman_region32_t damage ;
pixman_region32_init ( & damage ) ;
pixman_region32_copy ( & damage , originalDamage ) ;
2022-09-04 23:08:04 +02:00
wlr_region_transform ( & damage , & damage , wlr_output_transform_invert ( m_RenderData . pMonitor - > transform ) , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y ) ;
2022-06-07 20:41:40 +02:00
wlr_region_expand ( & damage , & damage , pow ( 2 , * PBLURPASSES ) * * PBLURSIZE ) ;
2022-09-04 23:08:04 +02:00
2022-05-02 16:54:40 +02:00
// helper
2022-06-29 12:54:53 +02:00
const auto PMIRRORFB = & m_RenderData . pCurrentMonData - > mirrorFB ;
const auto PMIRRORSWAPFB = & m_RenderData . pCurrentMonData - > mirrorSwapFB ;
2022-05-02 16:54:40 +02:00
2022-06-29 12:54:53 +02:00
CFramebuffer * currentRenderToFB = & m_RenderData . pCurrentMonData - > primaryFB ;
2022-05-02 16:54:40 +02:00
// declare the draw func
auto drawPass = [ & ] ( CShader * pShader , pixman_region32_t * pDamage ) {
if ( currentRenderToFB = = PMIRRORFB )
PMIRRORSWAPFB - > bind ( ) ;
else
PMIRRORFB - > bind ( ) ;
2022-04-09 16:51:08 +02:00
glActiveTexture ( GL_TEXTURE0 ) ;
2022-05-02 16:54:40 +02:00
glBindTexture ( currentRenderToFB - > m_cTex . m_iTarget , currentRenderToFB - > m_cTex . m_iTexID ) ;
glTexParameteri ( currentRenderToFB - > m_cTex . m_iTarget , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2022-04-09 16:51:08 +02:00
glUseProgram ( pShader - > program ) ;
2022-05-02 16:54:40 +02:00
// prep two shaders
2022-04-09 16:51:08 +02:00
glUniformMatrix3fv ( pShader - > proj , 1 , GL_FALSE , glMatrix ) ;
2022-07-29 17:07:33 +02:00
glUniform1f ( pShader - > radius , * PBLURSIZE * ( a / 255.f ) ) ; // this makes the blursize change with a
2022-08-11 20:29:21 +02:00
if ( pShader = = & m_RenderData . pCurrentMonData - > m_shBLUR1 )
glUniform2f ( m_RenderData . pCurrentMonData - > m_shBLUR1 . halfpixel , 0.5f / ( m_RenderData . pMonitor - > vecPixelSize . x / 2.f ) , 0.5f / ( m_RenderData . pMonitor - > vecPixelSize . y / 2.f ) ) ;
2022-05-02 16:54:40 +02:00
else
2022-08-11 20:29:21 +02:00
glUniform2f ( m_RenderData . pCurrentMonData - > m_shBLUR2 . halfpixel , 0.5f / ( m_RenderData . pMonitor - > vecPixelSize . x * 2.f ) , 0.5f / ( m_RenderData . pMonitor - > vecPixelSize . y * 2.f ) ) ;
2022-04-09 16:51:08 +02:00
glUniform1i ( pShader - > tex , 0 ) ;
glVertexAttribPointer ( pShader - > posAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
glVertexAttribPointer ( pShader - > texAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
glEnableVertexAttribArray ( pShader - > posAttrib ) ;
glEnableVertexAttribArray ( pShader - > texAttrib ) ;
2022-05-02 16:54:40 +02:00
if ( pixman_region32_not_empty ( pDamage ) ) {
PIXMAN_DAMAGE_FOREACH ( pDamage ) {
const auto RECT = RECTSARR [ i ] ;
2022-09-04 19:27:38 +02:00
scissor ( & RECT , false /* this region is already transformed */ ) ;
2022-05-02 16:54:40 +02:00
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
}
}
2022-04-09 16:51:08 +02:00
glDisableVertexAttribArray ( pShader - > posAttrib ) ;
glDisableVertexAttribArray ( pShader - > texAttrib ) ;
2022-05-02 16:54:40 +02:00
if ( currentRenderToFB ! = PMIRRORFB )
currentRenderToFB = PMIRRORFB ;
else
currentRenderToFB = PMIRRORSWAPFB ;
} ;
2022-04-24 16:41:01 +02:00
2022-05-02 16:54:40 +02:00
// draw the things.
// first draw is prim -> mirr
PMIRRORFB - > bind ( ) ;
2022-06-29 12:54:53 +02:00
glBindTexture ( m_RenderData . pCurrentMonData - > primaryFB . m_cTex . m_iTarget , m_RenderData . pCurrentMonData - > primaryFB . m_cTex . m_iTexID ) ;
2022-04-24 16:41:01 +02:00
2022-05-02 16:54:40 +02:00
// damage region will be scaled, make a temp
pixman_region32_t tempDamage ;
pixman_region32_init ( & tempDamage ) ;
2022-09-04 19:27:38 +02:00
wlr_region_scale ( & tempDamage , & damage , 1.f / 2.f ) ; // when DOWNscaling, we make the region twice as small because it's the TARGET
2022-08-11 20:29:21 +02:00
drawPass ( & m_RenderData . pCurrentMonData - > m_shBLUR1 , & tempDamage ) ;
2022-04-24 16:41:01 +02:00
2022-05-02 16:54:40 +02:00
// and draw
2022-06-07 20:41:40 +02:00
for ( int i = 1 ; i < * PBLURPASSES ; + + i ) {
2022-05-09 21:37:41 +02:00
wlr_region_scale ( & tempDamage , & damage , 1.f / ( 1 < < ( i + 1 ) ) ) ;
2022-08-11 20:29:21 +02:00
drawPass ( & m_RenderData . pCurrentMonData - > m_shBLUR1 , & tempDamage ) ; // down
2022-05-02 16:54:40 +02:00
}
2022-04-24 16:41:01 +02:00
2022-06-07 20:41:40 +02:00
for ( int i = * PBLURPASSES - 1 ; i > = 0 ; - - i ) {
2022-05-09 21:37:41 +02:00
wlr_region_scale ( & tempDamage , & damage , 1.f / ( 1 < < i ) ) ; // when upsampling we make the region twice as big
2022-08-11 20:29:21 +02:00
drawPass ( & m_RenderData . pCurrentMonData - > m_shBLUR2 , & tempDamage ) ; // up
2022-04-09 17:06:09 +02:00
}
2022-04-09 16:51:08 +02:00
2022-05-02 16:54:40 +02:00
// finish
pixman_region32_fini ( & tempDamage ) ;
2022-05-09 21:37:41 +02:00
pixman_region32_fini ( & damage ) ;
2022-05-02 16:54:40 +02:00
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
glBindTexture ( PMIRRORFB - > m_cTex . m_iTarget , 0 ) ;
return currentRenderToFB ;
}
2022-08-01 12:16:33 +02:00
void CHyprOpenGLImpl : : markBlurDirtyForMonitor ( CMonitor * pMonitor ) {
m_mMonitorRenderResources [ pMonitor ] . blurFBDirty = true ;
}
2022-08-01 20:18:26 +02:00
void CHyprOpenGLImpl : : preRender ( CMonitor * pMonitor ) {
static auto * const PBLURNEWOPTIMIZE = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_new_optimizations " ) - > intValue ;
if ( ! * PBLURNEWOPTIMIZE | | ! m_mMonitorRenderResources [ pMonitor ] . blurFBDirty )
return ;
bool has = false ;
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( w - > m_iWorkspaceID = = pMonitor - > activeWorkspace & & w - > m_bIsMapped & & ! w - > m_bHidden & & ! w - > m_bIsFloating ) {
has = true ;
break ;
}
}
if ( has )
g_pHyprRenderer - > damageMonitor ( pMonitor ) ;
}
2022-08-01 12:16:33 +02:00
void CHyprOpenGLImpl : : preBlurForCurrentMonitor ( ) {
// make the fake dmg
pixman_region32_t fakeDamage ;
pixman_region32_init_rect ( & fakeDamage , 0 , 0 , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y ) ;
wlr_box wholeMonitor = { 0 , 0 , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y } ;
const auto POUTFB = blurMainFramebufferWithDamage ( 255 , & wholeMonitor , & fakeDamage ) ;
// render onto blurFB
m_RenderData . pCurrentMonData - > blurFB . alloc ( m_RenderData . pMonitor - > vecPixelSize . x , m_RenderData . pMonitor - > vecPixelSize . y ) ;
m_RenderData . pCurrentMonData - > blurFB . bind ( ) ;
clear ( CColor ( 0 , 0 , 0 , 0 ) ) ;
2022-09-05 21:26:21 +02:00
m_bEndFrame = true ; // fix transformed
2022-08-01 12:16:33 +02:00
renderTextureInternalWithDamage ( POUTFB - > m_cTex , & wholeMonitor , 255 , & fakeDamage , 0 , false , true , false ) ;
2022-09-05 21:26:21 +02:00
m_bEndFrame = false ;
2022-08-01 12:16:33 +02:00
m_RenderData . pCurrentMonData - > primaryFB . bind ( ) ;
m_RenderData . pCurrentMonData - > blurFBDirty = false ;
}
2022-08-01 12:23:09 +02:00
void CHyprOpenGLImpl : : preWindowPass ( ) {
2022-08-27 21:37:35 +02:00
static auto * const PBLURNEWOPTIMIZE = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_new_optimizations " ) - > intValue ;
2022-08-01 12:23:09 +02:00
if ( ! m_RenderData . pCurrentMonData - > blurFBDirty | | ! * PBLURNEWOPTIMIZE )
return ;
bool hasWindows = false ;
for ( auto & w : g_pCompositor - > m_vWindows ) {
2022-08-01 20:32:46 +02:00
if ( w - > m_iWorkspaceID = = m_RenderData . pMonitor - > activeWorkspace & & ! w - > m_bHidden & & w - > m_bIsMapped & & ! w - > m_bIsFloating ) {
2022-08-01 12:23:09 +02:00
hasWindows = true ;
break ;
}
}
if ( ! hasWindows )
return ;
// blur the main FB, it will be rendered onto the mirror
preBlurForCurrentMonitor ( ) ;
}
2022-06-26 19:39:56 +02:00
void CHyprOpenGLImpl : : renderTextureWithBlur ( const CTexture & tex , wlr_box * pBox , float a , wlr_surface * pSurface , int round ) {
2022-05-02 16:54:40 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to render texture with blur without begin()! " ) ;
2022-06-07 20:41:40 +02:00
static auto * const PBLURENABLED = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur " ) - > intValue ;
2022-08-01 12:16:33 +02:00
static auto * const PNOBLUROVERSIZED = & g_pConfigManager - > getConfigValuePtr ( " decoration:no_blur_on_oversized " ) - > intValue ;
2022-08-27 21:37:35 +02:00
static auto * const PBLURNEWOPTIMIZE = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_new_optimizations " ) - > intValue ;
2022-06-07 20:41:40 +02:00
2022-06-24 22:28:54 +02:00
if ( * PBLURENABLED = = 0 | | ( * PNOBLUROVERSIZED & & m_RenderData . primarySurfaceUVTopLeft ! = Vector2D ( - 1 , - 1 ) ) | | ( m_pCurrentWindow & & m_pCurrentWindow - > m_sAdditionalConfigData . forceNoBlur ) ) {
2022-06-26 19:39:56 +02:00
renderTexture ( tex , pBox , a , round , false , true ) ;
2022-05-02 16:54:40 +02:00
return ;
}
2022-04-09 16:51:08 +02:00
2022-05-02 23:03:22 +02:00
// make a damage region for this window
pixman_region32_t damage ;
pixman_region32_init ( & damage ) ;
pixman_region32_intersect_rect ( & damage , m_RenderData . pDamage , pBox - > x , pBox - > y , pBox - > width , pBox - > height ) ; // clip it to the box
2022-05-09 21:37:41 +02:00
// amazing hack: the surface has an opaque region!
pixman_region32_t inverseOpaque ;
pixman_region32_init ( & inverseOpaque ) ;
2022-05-10 09:19:54 +02:00
if ( a = = 255.f ) {
2022-05-29 15:44:30 +02:00
pixman_box32_t monbox = { 0 , 0 , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y } ;
2022-05-10 09:19:54 +02:00
pixman_region32_copy ( & inverseOpaque , & pSurface - > current . opaque ) ;
pixman_region32_translate ( & inverseOpaque , pBox - > x , pBox - > y ) ;
pixman_region32_inverse ( & inverseOpaque , & inverseOpaque , & monbox ) ;
pixman_region32_intersect ( & inverseOpaque , & damage , & inverseOpaque ) ;
} else {
pixman_region32_copy ( & inverseOpaque , & damage ) ;
}
2022-05-09 21:37:41 +02:00
2022-06-07 20:10:14 +02:00
if ( ! pixman_region32_not_empty ( & inverseOpaque ) ) {
2022-07-15 19:21:13 +02:00
renderTexture ( tex , pBox , a , round , false , true ) ; // reject blurring a fully opaque window
2022-06-07 20:10:14 +02:00
return ;
}
2022-05-02 16:54:40 +02:00
2022-08-01 15:32:20 +02:00
// vvv TODO: layered blur fbs?
2022-08-20 20:15:40 +02:00
const bool USENEWOPTIMIZE = ( * PBLURNEWOPTIMIZE & & m_pCurrentWindow & & ! m_pCurrentWindow - > m_bIsFloating & & m_RenderData . pCurrentMonData - > blurFB . m_cTex . m_iTexID & & m_pCurrentWindow - > m_iWorkspaceID ! = SPECIAL_WORKSPACE_ID ) ;
2022-08-01 15:32:20 +02:00
const auto POUTFB = USENEWOPTIMIZE ? & m_RenderData . pCurrentMonData - > blurFB : blurMainFramebufferWithDamage ( a , pBox , & inverseOpaque ) ;
2022-05-10 09:19:54 +02:00
pixman_region32_fini ( & inverseOpaque ) ;
2022-05-02 16:54:40 +02:00
// bind primary
2022-06-29 12:54:53 +02:00
m_RenderData . pCurrentMonData - > primaryFB . bind ( ) ;
2022-05-02 16:54:40 +02:00
2022-08-01 15:29:49 +02:00
// make a stencil for rounded corners to work with blur
scissor ( ( wlr_box * ) nullptr ) ; // allow the entire window and stencil to render
glClearStencil ( 0 ) ;
glClear ( GL_STENCIL_BUFFER_BIT ) ;
2022-04-24 16:41:01 +02:00
2022-08-01 15:29:49 +02:00
glEnable ( GL_STENCIL_TEST ) ;
2022-04-24 16:41:01 +02:00
2022-08-01 15:29:49 +02:00
glStencilFunc ( GL_ALWAYS , 1 , - 1 ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2022-04-24 16:41:01 +02:00
2022-08-01 15:29:49 +02:00
glColorMask ( GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE ) ;
2022-08-01 15:32:20 +02:00
if ( USENEWOPTIMIZE )
renderRect ( pBox , CColor ( 0 , 0 , 0 , 0 ) , round ) ;
else
renderTexture ( tex , pBox , a , round , true , true ) ; // discard opaque
2022-08-01 15:29:49 +02:00
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
2022-04-24 16:41:01 +02:00
2022-08-01 15:29:49 +02:00
glStencilFunc ( GL_EQUAL , 1 , - 1 ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2022-04-24 16:41:01 +02:00
2022-05-02 16:54:40 +02:00
// stencil done. Render everything.
2022-05-29 15:44:30 +02:00
wlr_box MONITORBOX = { 0 , 0 , m_RenderData . pMonitor - > vecTransformedSize . x , m_RenderData . pMonitor - > vecTransformedSize . y } ;
2022-05-02 16:54:40 +02:00
if ( pixman_region32_not_empty ( & damage ) ) {
2022-05-10 09:56:58 +02:00
// render our great blurred FB
2022-06-07 20:41:40 +02:00
static auto * const PBLURIGNOREOPACITY = & g_pConfigManager - > getConfigValuePtr ( " decoration:blur_ignore_opacity " ) - > intValue ;
2022-09-04 19:27:38 +02:00
m_bEndFrame = true ; // fix transformed
2022-08-01 15:29:49 +02:00
renderTextureInternalWithDamage ( POUTFB - > m_cTex , & MONITORBOX , * PBLURIGNOREOPACITY ? 255.f : a , & damage , 0 , false , false , false ) ;
2022-09-04 19:27:38 +02:00
m_bEndFrame = false ;
2022-05-28 18:57:32 +02:00
2022-05-17 13:16:37 +02:00
// render the window, but clear stencil
2022-08-01 15:29:49 +02:00
glClearStencil ( 0 ) ;
glClear ( GL_STENCIL_BUFFER_BIT ) ;
2022-05-17 13:16:37 +02:00
2022-08-01 15:29:49 +02:00
// draw window
glDisable ( GL_STENCIL_TEST ) ;
2022-08-30 12:46:17 +02:00
renderTextureInternalWithDamage ( tex , pBox , a , & damage , round , false , false , true , true ) ;
2022-04-24 16:41:01 +02:00
}
2022-08-01 15:29:49 +02:00
glStencilMask ( - 1 ) ;
glStencilFunc ( GL_ALWAYS , 1 , 0xFF ) ;
2022-05-02 16:54:40 +02:00
pixman_region32_fini ( & damage ) ;
2022-04-24 16:41:01 +02:00
scissor ( ( wlr_box * ) nullptr ) ;
2022-04-09 16:51:08 +02:00
}
2022-04-05 16:47:03 +02:00
void pushVert2D ( float x , float y , float * arr , int & counter , wlr_box * box ) {
// 0-1 space god damnit
arr [ counter * 2 + 0 ] = x / box - > width ;
arr [ counter * 2 + 1 ] = y / box - > height ;
counter + + ;
}
2022-06-26 19:39:56 +02:00
void CHyprOpenGLImpl : : renderBorder ( wlr_box * box , const CColor & col , int round ) {
2022-04-05 16:47:03 +02:00
RASSERT ( ( box - > width > 0 & & box - > height > 0 ) , " Tried to render rect with width/height < 0! " ) ;
RASSERT ( m_RenderData . pMonitor , " Tried to render rect without begin()! " ) ;
2022-06-26 19:39:56 +02:00
static auto * const PBORDERSIZE = & g_pConfigManager - > getConfigValuePtr ( " general:border_size " ) - > intValue ;
static auto * const PMULTISAMPLE = & g_pConfigManager - > getConfigValuePtr ( " decoration:multisample_edges " ) - > intValue ;
2022-08-05 22:21:14 +02:00
if ( * PBORDERSIZE < 1 )
return ;
2022-08-04 17:21:01 +02:00
if ( round < 1 ) {
// zero rounding, just lines
wlr_box borderbox = { box - > x - * PBORDERSIZE , box - > y - * PBORDERSIZE , * PBORDERSIZE , box - > height + 2 * * PBORDERSIZE } ;
renderRect ( & borderbox , col , 0 ) ; // left
borderbox = { box - > x , box - > y - ( int ) * PBORDERSIZE , box - > width + ( int ) * PBORDERSIZE , ( int ) * PBORDERSIZE } ;
renderRect ( & borderbox , col , 0 ) ; // top
borderbox = { box - > x + box - > width , box - > y , ( int ) * PBORDERSIZE , box - > height + ( int ) * PBORDERSIZE } ;
renderRect ( & borderbox , col , 0 ) ; // right
borderbox = { box - > x , box - > y + box - > height , box - > width , ( int ) * PBORDERSIZE } ;
renderRect ( & borderbox , col , 0 ) ; // bottom
return ;
}
2022-06-26 19:39:56 +02:00
// adjust box
box - > x - = * PBORDERSIZE ;
box - > y - = * PBORDERSIZE ;
box - > width + = 2 * * PBORDERSIZE ;
box - > height + = 2 * * PBORDERSIZE ;
round + = * PBORDERSIZE ;
float matrix [ 9 ] ;
wlr_matrix_project_box ( matrix , box , wlr_output_transform_invert ( ! m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData . pMonitor - > transform ) , 0 , m_RenderData . pMonitor - > output - > transform_matrix ) ; // TODO: write own, don't use WLR here
float glMatrix [ 9 ] ;
wlr_matrix_multiply ( glMatrix , m_RenderData . projection , matrix ) ;
wlr_matrix_multiply ( glMatrix , matrixFlip180 , glMatrix ) ;
wlr_matrix_transpose ( glMatrix , glMatrix ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-08-11 20:29:21 +02:00
glUseProgram ( m_RenderData . pCurrentMonData - > m_shBORDER1 . program ) ;
2022-04-05 16:47:03 +02:00
2022-08-11 20:29:21 +02:00
glUniformMatrix3fv ( m_RenderData . pCurrentMonData - > m_shBORDER1 . proj , 1 , GL_FALSE , glMatrix ) ;
glUniform4f ( m_RenderData . pCurrentMonData - > m_shBORDER1 . color , col . r / 255.f , col . g / 255.f , col . b / 255.f , col . a / 255.f ) ;
2022-04-05 16:47:03 +02:00
2022-06-26 19:39:56 +02:00
const auto TOPLEFT = Vector2D ( round , round ) ;
const auto BOTTOMRIGHT = Vector2D ( box - > width - round , box - > height - round ) ;
const auto FULLSIZE = Vector2D ( box - > width , box - > height ) ;
2022-04-05 16:47:03 +02:00
2022-08-11 20:29:21 +02:00
glUniform2f ( m_RenderData . pCurrentMonData - > m_shBORDER1 . topLeft , ( float ) TOPLEFT . x , ( float ) TOPLEFT . y ) ;
glUniform2f ( m_RenderData . pCurrentMonData - > m_shBORDER1 . bottomRight , ( float ) BOTTOMRIGHT . x , ( float ) BOTTOMRIGHT . y ) ;
glUniform2f ( m_RenderData . pCurrentMonData - > m_shBORDER1 . fullSize , ( float ) FULLSIZE . x , ( float ) FULLSIZE . y ) ;
glUniform1f ( m_RenderData . pCurrentMonData - > m_shBORDER1 . radius , round ) ;
glUniform1f ( m_RenderData . pCurrentMonData - > m_shBORDER1 . thick , * PBORDERSIZE ) ;
glUniform1i ( m_RenderData . pCurrentMonData - > m_shBORDER1 . primitiveMultisample , * PMULTISAMPLE ) ;
2022-06-26 19:39:56 +02:00
2022-08-11 20:29:21 +02:00
glVertexAttribPointer ( m_RenderData . pCurrentMonData - > m_shBORDER1 . posAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
glVertexAttribPointer ( m_RenderData . pCurrentMonData - > m_shBORDER1 . texAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
2022-06-26 19:39:56 +02:00
2022-08-11 20:29:21 +02:00
glEnableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shBORDER1 . posAttrib ) ;
glEnableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shBORDER1 . texAttrib ) ;
2022-06-26 19:39:56 +02:00
if ( pixman_region32_not_empty ( m_RenderData . pDamage ) ) {
PIXMAN_DAMAGE_FOREACH ( m_RenderData . pDamage ) {
const auto RECT = RECTSARR [ i ] ;
scissor ( & RECT ) ;
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
}
}
2022-08-11 20:29:21 +02:00
glDisableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shBORDER1 . posAttrib ) ;
glDisableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shBORDER1 . texAttrib ) ;
2022-06-26 19:39:56 +02:00
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-04-05 20:49:15 +02:00
}
void CHyprOpenGLImpl : : makeWindowSnapshot ( CWindow * pWindow ) {
// we trust the window is valid.
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pWindow - > m_iMonitorID ) ;
wlr_output_attach_render ( PMONITOR - > output , nullptr ) ;
2022-04-14 16:43:29 +02:00
// we need to "damage" the entire monitor
// so that we render the entire window
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage ;
pixman_region32_init ( & fakeDamage ) ;
2022-07-30 22:07:40 +02:00
pixman_region32_union_rect ( & fakeDamage , & fakeDamage , 0 , 0 , ( int ) PMONITOR - > vecTransformedSize . x , ( int ) PMONITOR - > vecTransformedSize . y ) ;
2022-04-14 16:43:29 +02:00
2022-05-18 20:33:54 +02:00
begin ( PMONITOR , & fakeDamage , true ) ;
2022-04-14 16:43:29 +02:00
2022-04-05 20:49:15 +02:00
clear ( CColor ( 0 , 0 , 0 , 0 ) ) ; // JIC
timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
2022-04-10 18:25:45 +02:00
// this is a hack but it works :P
// we need to disable blur or else we will get a black background, as the shader
// will try to copy the bg to apply blur.
// this isn't entirely correct, but like, oh well.
// small todo: maybe make this correct? :P
const auto BLURVAL = g_pConfigManager - > getInt ( " decoration:blur " ) ;
g_pConfigManager - > setInt ( " decoration:blur " , 0 ) ;
2022-05-19 20:16:08 +02:00
// render onto the window fb
const auto PFRAMEBUFFER = & m_mWindowFramebuffers [ pWindow ] ;
glViewport ( 0 , 0 , g_pHyprOpenGL - > m_RenderData . pMonitor - > vecPixelSize . x , g_pHyprOpenGL - > m_RenderData . pMonitor - > vecPixelSize . y ) ;
2022-08-30 19:40:19 +02:00
PFRAMEBUFFER - > m_pStencilTex = & m_RenderData . pCurrentMonData - > stencilTex ;
2022-05-19 20:16:08 +02:00
PFRAMEBUFFER - > alloc ( PMONITOR - > vecPixelSize . x , PMONITOR - > vecPixelSize . y ) ;
PFRAMEBUFFER - > bind ( ) ;
clear ( CColor ( 0 , 0 , 0 , 0 ) ) ; // JIC
2022-08-30 19:40:19 +02:00
g_pHyprRenderer - > renderWindow ( pWindow , PMONITOR , & now , ! pWindow - > m_bX11DoesntWantBorders , RENDER_PASS_ALL ) ;
g_pConfigManager - > setInt ( " decoration:blur " , BLURVAL ) ;
2022-05-19 20:16:08 +02:00
2022-04-05 20:49:15 +02:00
// restore original fb
2022-04-13 17:34:13 +02:00
# ifndef GLES2
2022-04-05 20:49:15 +02:00
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , m_iCurrentOutputFb ) ;
2022-04-13 17:34:13 +02:00
# else
glBindFramebuffer ( GL_FRAMEBUFFER , m_iCurrentOutputFb ) ;
# endif
2022-04-05 20:49:15 +02:00
end ( ) ;
2022-07-12 23:11:34 +02:00
pixman_region32_fini ( & fakeDamage ) ;
2022-04-05 20:49:15 +02:00
wlr_output_rollback ( PMONITOR - > output ) ;
}
2022-05-14 17:23:46 +02:00
void CHyprOpenGLImpl : : makeLayerSnapshot ( SLayerSurface * pLayer ) {
// we trust the window is valid.
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( pLayer - > monitorID ) ;
wlr_output_attach_render ( PMONITOR - > output , nullptr ) ;
// we need to "damage" the entire monitor
// so that we render the entire window
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage ;
pixman_region32_init ( & fakeDamage ) ;
2022-08-22 13:36:00 +02:00
pixman_region32_union_rect ( & fakeDamage , & fakeDamage , 0 , 0 , ( int ) PMONITOR - > vecTransformedSize . x , ( int ) PMONITOR - > vecTransformedSize . y ) ;
2022-05-14 17:23:46 +02:00
2022-05-18 20:33:54 +02:00
begin ( PMONITOR , & fakeDamage , true ) ;
2022-05-14 17:23:46 +02:00
const auto PFRAMEBUFFER = & m_mLayerFramebuffers [ pLayer ] ;
2022-05-18 20:33:54 +02:00
glViewport ( 0 , 0 , g_pHyprOpenGL - > m_RenderData . pMonitor - > vecPixelSize . x , g_pHyprOpenGL - > m_RenderData . pMonitor - > vecPixelSize . y ) ;
2022-05-14 17:23:46 +02:00
2022-05-18 20:33:54 +02:00
PFRAMEBUFFER - > alloc ( PMONITOR - > vecPixelSize . x , PMONITOR - > vecPixelSize . y ) ;
2022-05-14 17:23:46 +02:00
PFRAMEBUFFER - > bind ( ) ;
clear ( CColor ( 0 , 0 , 0 , 0 ) ) ; // JIC
timespec now ;
clock_gettime ( CLOCK_MONOTONIC , & now ) ;
// draw the layer
g_pHyprRenderer - > renderLayer ( pLayer , PMONITOR , & now ) ;
2022-05-19 20:16:08 +02:00
// TODO: WARN:
// revise if any stencil-requiring rendering is done to the layers.
2022-05-14 17:23:46 +02:00
// restore original fb
# ifndef GLES2
glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , m_iCurrentOutputFb ) ;
# else
glBindFramebuffer ( GL_FRAMEBUFFER , m_iCurrentOutputFb ) ;
# endif
end ( ) ;
2022-07-12 23:11:34 +02:00
pixman_region32_fini ( & fakeDamage ) ;
2022-05-14 17:23:46 +02:00
wlr_output_rollback ( PMONITOR - > output ) ;
}
2022-04-05 20:49:15 +02:00
void CHyprOpenGLImpl : : renderSnapshot ( CWindow * * pWindow ) {
2022-04-10 14:32:18 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to render snapshot rect without begin()! " ) ;
2022-04-05 20:49:15 +02:00
const auto PWINDOW = * pWindow ;
auto it = m_mWindowFramebuffers . begin ( ) ;
2022-05-14 17:23:46 +02:00
for ( ; it ! = m_mWindowFramebuffers . end ( ) ; it + + ) {
2022-04-05 20:49:15 +02:00
if ( it - > first = = PWINDOW ) {
break ;
}
}
if ( it = = m_mWindowFramebuffers . end ( ) | | ! it - > second . m_cTex . m_iTexID )
return ;
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( PWINDOW - > m_iMonitorID ) ;
2022-05-28 18:28:55 +02:00
wlr_box windowBox ;
// some mafs to figure out the correct box
2022-06-30 20:02:04 +02:00
// the originalClosedPos is relative to the monitor's pos
Vector2D scaleXY = Vector2D ( ( PMONITOR - > scale * PWINDOW - > m_vRealSize . vec ( ) . x / ( PWINDOW - > m_vOriginalClosedSize . x * PMONITOR - > scale ) ) , ( PMONITOR - > scale * PWINDOW - > m_vRealSize . vec ( ) . y / ( PWINDOW - > m_vOriginalClosedSize . y * PMONITOR - > scale ) ) ) ;
2022-05-28 18:28:55 +02:00
2022-07-20 16:28:05 +02:00
windowBox . width = PMONITOR - > vecTransformedSize . x * scaleXY . x ;
windowBox . height = PMONITOR - > vecTransformedSize . y * scaleXY . y ;
2022-06-30 20:02:04 +02:00
windowBox . x = ( ( PWINDOW - > m_vRealPosition . vec ( ) . x - PMONITOR - > vecPosition . x ) * PMONITOR - > scale ) - ( ( PWINDOW - > m_vOriginalClosedPos . x * PMONITOR - > scale ) * scaleXY . x ) ;
windowBox . y = ( ( PWINDOW - > m_vRealPosition . vec ( ) . y - PMONITOR - > vecPosition . y ) * PMONITOR - > scale ) - ( ( PWINDOW - > m_vOriginalClosedPos . y * PMONITOR - > scale ) * scaleXY . y ) ;
2022-04-05 20:49:15 +02:00
2022-05-10 09:56:58 +02:00
pixman_region32_t fakeDamage ;
2022-07-20 16:28:05 +02:00
pixman_region32_init_rect ( & fakeDamage , 0 , 0 , PMONITOR - > vecTransformedSize . x , PMONITOR - > vecTransformedSize . y ) ;
2022-05-10 09:56:58 +02:00
2022-08-30 19:40:19 +02:00
m_bEndFrame = true ;
2022-05-10 09:56:58 +02:00
renderTextureInternalWithDamage ( it - > second . m_cTex , & windowBox , PWINDOW - > m_fAlpha . fl ( ) , & fakeDamage , 0 ) ;
2022-08-30 19:40:19 +02:00
m_bEndFrame = false ;
2022-05-10 09:56:58 +02:00
pixman_region32_fini ( & fakeDamage ) ;
2022-07-30 22:26:46 +02:00
static auto * const PDAMAGEMON = & g_pConfigManager - > getConfigValuePtr ( " misc:damage_entire_on_snapshot " ) - > intValue ;
if ( * PDAMAGEMON )
PMONITOR - > forceFullFrames + = 1 ;
2022-04-10 14:32:18 +02:00
}
2022-05-14 17:23:46 +02:00
void CHyprOpenGLImpl : : renderSnapshot ( SLayerSurface * * pLayer ) {
RASSERT ( m_RenderData . pMonitor , " Tried to render snapshot rect without begin()! " ) ;
const auto PLAYER = * pLayer ;
auto it = m_mLayerFramebuffers . begin ( ) ;
for ( ; it ! = m_mLayerFramebuffers . end ( ) ; it + + ) {
if ( it - > first = = PLAYER ) {
break ;
}
}
if ( it = = m_mLayerFramebuffers . end ( ) | | ! it - > second . m_cTex . m_iTexID )
return ;
const auto PMONITOR = g_pCompositor - > getMonitorFromID ( PLAYER - > monitorID ) ;
2022-08-22 13:36:00 +02:00
wlr_box monbox = { 0 , 0 , PMONITOR - > vecTransformedSize . x , PMONITOR - > vecTransformedSize . y } ;
2022-05-14 17:23:46 +02:00
pixman_region32_t fakeDamage ;
2022-08-22 13:38:40 +02:00
pixman_region32_init_rect ( & fakeDamage , 0 , 0 , PMONITOR - > vecTransformedSize . x , PMONITOR - > vecTransformedSize . y ) ;
2022-05-14 17:23:46 +02:00
2022-08-22 13:36:00 +02:00
m_bEndFrame = true ;
renderTextureInternalWithDamage ( it - > second . m_cTex , & monbox , PLAYER - > alpha . fl ( ) , & fakeDamage , 0 ) ;
m_bEndFrame = false ;
2022-05-14 17:23:46 +02:00
pixman_region32_fini ( & fakeDamage ) ;
2022-07-30 22:26:46 +02:00
static auto * const PDAMAGEMON = & g_pConfigManager - > getConfigValuePtr ( " misc:damage_entire_on_snapshot " ) - > intValue ;
if ( * PDAMAGEMON )
PMONITOR - > forceFullFrames + = 1 ;
2022-05-14 17:23:46 +02:00
}
2022-06-25 20:31:54 +02:00
void CHyprOpenGLImpl : : renderRoundedShadow ( wlr_box * box , int round , int range , float a ) {
2022-06-25 20:28:40 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to render shadow without begin()! " ) ;
RASSERT ( ( box - > width > 0 & & box - > height > 0 ) , " Tried to render shadow with width/height < 0! " ) ;
2022-07-16 12:44:45 +02:00
RASSERT ( m_pCurrentWindow , " Tried to render shadow without a window! " ) ;
2022-06-25 20:28:40 +02:00
static auto * const PSHADOWPOWER = & g_pConfigManager - > getConfigValuePtr ( " decoration:shadow_render_power " ) - > intValue ;
const auto SHADOWPOWER = std : : clamp ( ( int ) * PSHADOWPOWER , 1 , 4 ) ;
2022-07-16 12:44:45 +02:00
const auto col = m_pCurrentWindow - > m_cRealShadowColor . col ( ) ;
2022-06-25 20:28:40 +02:00
float matrix [ 9 ] ;
wlr_matrix_project_box ( matrix , box , wlr_output_transform_invert ( ! m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData . pMonitor - > transform ) , 0 , m_RenderData . pMonitor - > output - > transform_matrix ) ; // TODO: write own, don't use WLR here
float glMatrix [ 9 ] ;
wlr_matrix_multiply ( glMatrix , m_RenderData . projection , matrix ) ;
wlr_matrix_multiply ( glMatrix , matrixFlip180 , glMatrix ) ;
wlr_matrix_transpose ( glMatrix , glMatrix ) ;
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2022-08-11 20:29:21 +02:00
glUseProgram ( m_RenderData . pCurrentMonData - > m_shSHADOW . program ) ;
2022-06-25 20:28:40 +02:00
2022-08-11 20:29:21 +02:00
glUniformMatrix3fv ( m_RenderData . pCurrentMonData - > m_shSHADOW . proj , 1 , GL_FALSE , glMatrix ) ;
glUniform4f ( m_RenderData . pCurrentMonData - > m_shSHADOW . color , col . r / 255.f , col . g / 255.f , col . b / 255.f , col . a / 255.f * a ) ;
2022-06-25 20:28:40 +02:00
const auto TOPLEFT = Vector2D ( range + round , range + round ) ;
const auto BOTTOMRIGHT = Vector2D ( box - > width - ( range + round ) , box - > height - ( range + round ) ) ;
const auto FULLSIZE = Vector2D ( box - > width , box - > height ) ;
// Rounded corners
2022-08-11 20:29:21 +02:00
glUniform2f ( m_RenderData . pCurrentMonData - > m_shSHADOW . topLeft , ( float ) TOPLEFT . x , ( float ) TOPLEFT . y ) ;
glUniform2f ( m_RenderData . pCurrentMonData - > m_shSHADOW . bottomRight , ( float ) BOTTOMRIGHT . x , ( float ) BOTTOMRIGHT . y ) ;
glUniform2f ( m_RenderData . pCurrentMonData - > m_shSHADOW . fullSize , ( float ) FULLSIZE . x , ( float ) FULLSIZE . y ) ;
glUniform1f ( m_RenderData . pCurrentMonData - > m_shSHADOW . radius , range + round ) ;
glUniform1f ( m_RenderData . pCurrentMonData - > m_shSHADOW . range , range ) ;
glUniform1f ( m_RenderData . pCurrentMonData - > m_shSHADOW . shadowPower , SHADOWPOWER ) ;
2022-06-25 20:28:40 +02:00
2022-08-11 20:29:21 +02:00
glVertexAttribPointer ( m_RenderData . pCurrentMonData - > m_shSHADOW . posAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
glVertexAttribPointer ( m_RenderData . pCurrentMonData - > m_shSHADOW . texAttrib , 2 , GL_FLOAT , GL_FALSE , 0 , fullVerts ) ;
2022-06-25 20:28:40 +02:00
2022-08-11 20:29:21 +02:00
glEnableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shSHADOW . posAttrib ) ;
glEnableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shSHADOW . texAttrib ) ;
2022-06-25 20:28:40 +02:00
if ( pixman_region32_not_empty ( m_RenderData . pDamage ) ) {
PIXMAN_DAMAGE_FOREACH ( m_RenderData . pDamage ) {
const auto RECT = RECTSARR [ i ] ;
scissor ( & RECT ) ;
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
}
}
2022-08-11 20:29:21 +02:00
glDisableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shSHADOW . posAttrib ) ;
glDisableVertexAttribArray ( m_RenderData . pCurrentMonData - > m_shSHADOW . texAttrib ) ;
2022-06-25 20:28:40 +02:00
glBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA ) ;
}
2022-09-13 15:25:42 +02:00
void CHyprOpenGLImpl : : saveBufferForMirror ( ) {
m_RenderData . pCurrentMonData - > monitorMirrorFB . bind ( ) ;
wlr_box monbox = { 0 , 0 , m_RenderData . pMonitor - > vecPixelSize . x , m_RenderData . pMonitor - > vecPixelSize . y } ;
renderTexture ( m_RenderData . pCurrentMonData - > primaryFB . m_cTex , & monbox , 255.f , 0 , false , false ) ;
m_RenderData . pCurrentMonData - > primaryFB . bind ( ) ;
}
void CHyprOpenGLImpl : : renderMirrored ( ) {
wlr_box monbox = { 0 , 0 , m_RenderData . pMonitor - > vecPixelSize . x , m_RenderData . pMonitor - > vecPixelSize . y } ;
const auto PFB = & m_mMonitorRenderResources [ m_RenderData . pMonitor - > pMirrorOf ] . monitorMirrorFB ;
if ( PFB - > m_cTex . m_iTexID < = 0 )
return ;
renderTexture ( PFB - > m_cTex , & monbox , 255.f , 0 , false , false ) ;
}
2022-07-10 15:41:26 +02:00
void CHyprOpenGLImpl : : renderSplash ( cairo_t * const CAIRO , cairo_surface_t * const CAIROSURFACE ) {
cairo_select_font_face ( CAIRO , " Sans " , CAIRO_FONT_SLANT_NORMAL , CAIRO_FONT_WEIGHT_NORMAL ) ;
const auto FONTSIZE = ( int ) ( m_RenderData . pMonitor - > vecPixelSize . y / 76 ) ;
cairo_set_font_size ( CAIRO , FONTSIZE ) ;
cairo_set_source_rgba ( CAIRO , 1.f , 1.f , 1.f , 0.32f ) ;
cairo_text_extents_t textExtents ;
cairo_text_extents ( CAIRO , g_pCompositor - > m_szCurrentSplash . c_str ( ) , & textExtents ) ;
2022-09-05 11:31:54 +02:00
cairo_move_to ( CAIRO , m_RenderData . pMonitor - > vecPixelSize . x / 2.f - textExtents . width / 2.f , m_RenderData . pMonitor - > vecPixelSize . y - textExtents . height - 1 ) ;
2022-07-10 15:41:26 +02:00
cairo_show_text ( CAIRO , g_pCompositor - > m_szCurrentSplash . c_str ( ) ) ;
cairo_surface_flush ( CAIROSURFACE ) ;
}
2022-07-27 12:32:00 +02:00
void CHyprOpenGLImpl : : createBGTextureForMonitor ( CMonitor * pMonitor ) {
2022-04-10 14:32:18 +02:00
RASSERT ( m_RenderData . pMonitor , " Tried to createBGTex without begin()! " ) ;
2022-07-10 15:41:26 +02:00
static auto * const PNOSPLASH = & g_pConfigManager - > getConfigValuePtr ( " misc:disable_splash_rendering " ) - > intValue ;
2022-04-10 14:32:18 +02:00
// release the last tex if exists
const auto PTEX = & m_mMonitorBGTextures [ pMonitor ] ;
PTEX - > destroyTexture ( ) ;
PTEX - > allocate ( ) ;
2022-04-12 21:49:35 +02:00
Debug : : log ( LOG , " Allocated texture for BGTex " ) ;
2022-07-08 16:46:42 +02:00
// TODO: use relative paths to the installation
// or configure the paths at build time
2022-04-10 14:32:18 +02:00
// check if wallpapers exist
if ( ! std : : filesystem : : exists ( " /usr/share/hyprland/wall_8K.png " ) )
return ; // the texture will be empty, oh well. We'll clear with a solid color anyways.
// get the adequate tex
std : : string texPath = " /usr/share/hyprland/wall_ " ;
2022-04-13 18:49:15 +02:00
Vector2D textureSize ;
2022-08-13 22:33:51 +02:00
if ( pMonitor - > vecTransformedSize . x > 3850 ) {
2022-04-13 18:49:15 +02:00
textureSize = Vector2D ( 7680 , 4320 ) ;
2022-04-10 14:32:18 +02:00
texPath + = " 8K.png " ;
2022-08-13 22:33:51 +02:00
} else if ( pMonitor - > vecTransformedSize . x > 1930 ) {
2022-04-13 18:49:15 +02:00
textureSize = Vector2D ( 3840 , 2160 ) ;
2022-04-10 14:32:18 +02:00
texPath + = " 4K.png " ;
2022-04-13 18:49:15 +02:00
} else {
textureSize = Vector2D ( 1920 , 1080 ) ;
2022-04-10 14:32:18 +02:00
texPath + = " 2K.png " ;
2022-04-13 18:49:15 +02:00
}
2022-04-10 14:32:18 +02:00
2022-07-31 23:44:04 +02:00
PTEX - > m_vSize = textureSize ;
2022-04-10 14:32:18 +02:00
// create a new one with cairo
const auto CAIROSURFACE = cairo_image_surface_create_from_png ( texPath . c_str ( ) ) ;
const auto CAIRO = cairo_create ( CAIROSURFACE ) ;
2022-07-10 15:41:26 +02:00
if ( ! * PNOSPLASH )
renderSplash ( CAIRO , CAIROSURFACE ) ;
2022-04-10 14:32:18 +02:00
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data ( CAIROSURFACE ) ;
glBindTexture ( GL_TEXTURE_2D , PTEX - > m_iTexID ) ;
2022-08-13 22:33:51 +02:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2022-04-13 17:34:13 +02:00
# ifndef GLES2
2022-04-10 14:32:18 +02:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_SWIZZLE_R , GL_BLUE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_SWIZZLE_B , GL_RED ) ;
2022-04-13 17:34:13 +02:00
# endif
2022-04-13 18:49:15 +02:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , textureSize . x , textureSize . y , 0 , GL_RGBA , GL_UNSIGNED_BYTE , DATA ) ;
2022-04-10 14:32:18 +02:00
cairo_surface_destroy ( CAIROSURFACE ) ;
cairo_destroy ( CAIRO ) ;
2022-04-12 21:49:35 +02:00
2022-07-31 23:44:04 +02:00
// calc the target box
const float MONRATIO = m_RenderData . pMonitor - > vecTransformedSize . x / m_RenderData . pMonitor - > vecTransformedSize . y ;
const float WPRATIO = 1.77f ;
Vector2D origin ;
float scale ;
if ( MONRATIO > WPRATIO ) {
scale = m_RenderData . pMonitor - > vecTransformedSize . x / PTEX - > m_vSize . x ;
origin . y = - ( PTEX - > m_vSize . y * scale - m_RenderData . pMonitor - > vecTransformedSize . y ) / 2.f / scale ;
} else {
scale = m_RenderData . pMonitor - > vecTransformedSize . y / PTEX - > m_vSize . y ;
origin . x = - ( PTEX - > m_vSize . x * scale - m_RenderData . pMonitor - > vecTransformedSize . x ) / 2.f / scale ;
}
wlr_box box = { origin . x * scale , origin . y * scale , PTEX - > m_vSize . x * scale , PTEX - > m_vSize . y * scale } ;
m_mMonitorRenderResources [ pMonitor ] . backgroundTexBox = box ;
2022-04-12 21:49:35 +02:00
Debug : : log ( LOG , " Background created for monitor %s " , pMonitor - > szName . c_str ( ) ) ;
2022-04-10 14:32:18 +02:00
}
void CHyprOpenGLImpl : : clearWithTex ( ) {
RASSERT ( m_RenderData . pMonitor , " Tried to render BGtex without begin()! " ) ;
2022-05-18 20:33:54 +02:00
2022-07-10 15:41:26 +02:00
static auto * const PRENDERTEX = & g_pConfigManager - > getConfigValuePtr ( " misc:disable_hyprland_logo " ) - > intValue ;
2022-04-10 14:32:18 +02:00
2022-07-07 20:16:40 +02:00
if ( ! * PRENDERTEX ) {
2022-07-31 23:44:04 +02:00
renderTexture ( m_mMonitorBGTextures [ m_RenderData . pMonitor ] , & m_mMonitorRenderResources [ m_RenderData . pMonitor ] . backgroundTexBox , 255 , 0 ) ;
2022-07-07 20:16:40 +02:00
}
2022-04-19 19:01:23 +02:00
}
2022-07-27 12:32:00 +02:00
void CHyprOpenGLImpl : : destroyMonitorResources ( CMonitor * pMonitor ) {
2022-04-19 19:01:23 +02:00
g_pHyprOpenGL - > m_mMonitorRenderResources [ pMonitor ] . mirrorFB . release ( ) ;
g_pHyprOpenGL - > m_mMonitorRenderResources [ pMonitor ] . primaryFB . release ( ) ;
g_pHyprOpenGL - > m_mMonitorRenderResources [ pMonitor ] . stencilTex . destroyTexture ( ) ;
g_pHyprOpenGL - > m_mMonitorBGTextures [ pMonitor ] . destroyTexture ( ) ;
g_pHyprOpenGL - > m_mMonitorRenderResources . erase ( pMonitor ) ;
g_pHyprOpenGL - > m_mMonitorBGTextures . erase ( pMonitor ) ;
Debug : : log ( LOG , " Monitor %s -> destroyed all render data " , pMonitor - > szName . c_str ( ) ) ;
}