From 02bb410cdb89d2c85d472e5d82381c6a93537ebb Mon Sep 17 00:00:00 2001 From: decimad Date: Thu, 22 Dec 2016 18:58:29 +0100 Subject: [PATCH] Refactor COMPOSITOR/OPENGL_COMPOSITOR to enable customization of scene rendering and presentation --- common/CMakeLists.txt | 1 + common/gal/cairo/cairo_compositor.cpp | 6 ++ common/gal/opengl/antialiasing.cpp | 56 +++++++++++++++++ common/gal/opengl/antialiasing.h | 46 ++++++++++++++ common/gal/opengl/opengl_compositor.cpp | 83 ++++++++++++++++++------- common/gal/opengl/opengl_gal.cpp | 14 ++--- include/gal/cairo/cairo_compositor.h | 6 ++ include/gal/compositor.h | 14 ++++- include/gal/opengl/opengl_compositor.h | 17 +++++ include/math/vector2d.h | 5 +- 10 files changed, 215 insertions(+), 33 deletions(-) create mode 100644 common/gal/opengl/antialiasing.cpp create mode 100644 common/gal/opengl/antialiasing.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 08546c6129..b27107da68 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -46,6 +46,7 @@ set( GAL_SRCS gal/opengl/noncached_container.cpp gal/opengl/vertex_manager.cpp gal/opengl/gpu_manager.cpp + gal/opengl/antialiasing.cpp gal/opengl/opengl_compositor.cpp gal/opengl/utils.cpp diff --git a/common/gal/cairo/cairo_compositor.cpp b/common/gal/cairo/cairo_compositor.cpp index 813c554c76..f8b7cf1e76 100644 --- a/common/gal/cairo/cairo_compositor.cpp +++ b/common/gal/cairo/cairo_compositor.cpp @@ -119,6 +119,9 @@ void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) cairo_set_matrix( *m_currentContext, &m_matrix ); } +void CAIRO_COMPOSITOR::Begin() +{ +} void CAIRO_COMPOSITOR::ClearBuffer() { @@ -144,6 +147,9 @@ void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) cairo_set_matrix( m_mainContext, &m_matrix ); } +void CAIRO_COMPOSITOR::Present() +{ +} void CAIRO_COMPOSITOR::clean() { diff --git a/common/gal/opengl/antialiasing.cpp b/common/gal/opengl/antialiasing.cpp new file mode 100644 index 0000000000..58b979b461 --- /dev/null +++ b/common/gal/opengl/antialiasing.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +#include + +#include "gl_builtin_shaders.h" + +namespace KIGFX { + + // ========================= + // ANTIALIASING_NONE + // ========================= + + ANTIALIASING_NONE::ANTIALIASING_NONE( OPENGL_COMPOSITOR* aCompositor ) + : compositor(aCompositor) + { + } + + bool ANTIALIASING_NONE::Init() + { + // Nothing to initialize + return true; + } + + VECTOR2U ANTIALIASING_NONE::GetInternalBufferSize() + { + return compositor->GetScreenSize(); + } + + void ANTIALIASING_NONE::DrawBuffer( GLuint buffer ) + { + compositor->DrawBuffer( buffer, OPENGL_COMPOSITOR::DIRECT_RENDERING ); + } + + void ANTIALIASING_NONE::Present() + { + // Nothing to present, draw_buffer already drew to the screen + } + + void ANTIALIASING_NONE::OnLostBuffers() + { + // Nothing to do + } + + void ANTIALIASING_NONE::Begin() + { + // Nothing to do + } + + unsigned int ANTIALIASING_NONE::CreateBuffer() + { + return compositor->CreateBuffer( compositor->GetScreenSize() ); + } + +} diff --git a/common/gal/opengl/antialiasing.h b/common/gal/opengl/antialiasing.h new file mode 100644 index 0000000000..c2bae7b87f --- /dev/null +++ b/common/gal/opengl/antialiasing.h @@ -0,0 +1,46 @@ +#ifndef OPENGL_ANTIALIASING_H__ +#define OPENGL_ANTIALIASING_H__ + +#include +#include +#include + +namespace KIGFX { + + class OPENGL_COMPOSITOR; + + class OPENGL_PRESENTOR + { + public: + virtual bool Init() = 0; + virtual unsigned int CreateBuffer() = 0; + + virtual VECTOR2U GetInternalBufferSize() = 0; + virtual void OnLostBuffers() = 0; + + virtual void Begin() = 0; + virtual void DrawBuffer(GLuint buffer) = 0; + virtual void Present() = 0; + }; + + class ANTIALIASING_NONE : public OPENGL_PRESENTOR { + public: + ANTIALIASING_NONE( OPENGL_COMPOSITOR* aCompositor ); + + bool Init() override; + unsigned int CreateBuffer() override; + + VECTOR2U GetInternalBufferSize() override; + void OnLostBuffers() override; + + void Begin() override; + void DrawBuffer( GLuint buffer ) override; + void Present() override; + + private: + OPENGL_COMPOSITOR* compositor; + }; + +} + +#endif diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp index 95f9aff2fd..8e1892ea70 100644 --- a/common/gal/opengl/opengl_compositor.cpp +++ b/common/gal/opengl/opengl_compositor.cpp @@ -40,6 +40,7 @@ OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() : m_initialized( false ), m_curBuffer( 0 ), m_mainFbo( 0 ), m_depthBuffer( 0 ), m_curFbo( DIRECT_RENDERING ) { + m_antialiasing.reset( new ANTIALIASING_NONE( this ) ); } @@ -55,6 +56,8 @@ void OPENGL_COMPOSITOR::Initialize() if( m_initialized ) return; + VECTOR2U dims = m_antialiasing->GetInternalBufferSize(); + // We need framebuffer objects for drawing the screen contents // Generate framebuffer and a depth buffer glGenFramebuffersEXT( 1, &m_mainFbo ); @@ -68,7 +71,7 @@ void OPENGL_COMPOSITOR::Initialize() glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depthBuffer ); checkGlError( "binding renderbuffer" ); - glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, m_width, m_height ); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, dims.x, dims.y ); checkGlError( "creating renderbuffer storage" ); glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, m_depthBuffer ); @@ -86,12 +89,18 @@ void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight ) if( m_initialized ) clean(); + m_antialiasing->OnLostBuffers(); + m_width = aWidth; m_height = aHeight; } - unsigned int OPENGL_COMPOSITOR::CreateBuffer() +{ + return m_antialiasing->CreateBuffer(); +} + +unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2U aDimensions ) { assert( m_initialized ); @@ -109,7 +118,7 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*) &maxTextureSize ); - if( maxTextureSize < (int) m_width || maxTextureSize < (int) m_height ) + if( maxTextureSize < (int) aDimensions.x || maxTextureSize < (int) aDimensions.y ) { throw std::runtime_error( "Requested texture size is not supported. " "Could not create a buffer." ); @@ -120,6 +129,7 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() GLuint textureTarget; // Generate the texture for the pixel storage + glActiveTexture( GL_TEXTURE0 ); glGenTextures( 1, &textureTarget ); checkGlError( "generating framebuffer texture target" ); glBindTexture( GL_TEXTURE_2D, textureTarget ); @@ -127,7 +137,7 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() // Set texture parameters glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, aDimensions.x, aDimensions.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); checkGlError( "creating framebuffer texture" ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); @@ -190,12 +200,17 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() bindFb( DIRECT_RENDERING ); // Store the new buffer - OPENGL_BUFFER buffer = { textureTarget, attachmentPoint }; + OPENGL_BUFFER buffer = { aDimensions, textureTarget, attachmentPoint }; m_buffers.push_back( buffer ); return usedBuffers(); } +GLenum OPENGL_COMPOSITOR::GetBufferTexture( unsigned int aBufferHandle ) +{ + assert( aBufferHandle > 0 && aBufferHandle <= usedBuffers() ); + return m_buffers[aBufferHandle - 1].textureTarget; +} void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) { @@ -211,7 +226,14 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) m_curBuffer = aBufferHandle - 1; glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint ); checkGlError( "setting draw buffer" ); + + glViewport( 0, 0, + m_buffers[m_curBuffer].dimensions.x, m_buffers[m_curBuffer].dimensions.y ); + } else { + glViewport( 0, 0, GetScreenSize().x, GetScreenSize().y ); } + + } @@ -223,14 +245,29 @@ void OPENGL_COMPOSITOR::ClearBuffer() glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); } +VECTOR2U OPENGL_COMPOSITOR::GetScreenSize() const +{ + return{ m_width, m_height }; +} -void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) +void OPENGL_COMPOSITOR::Begin() +{ + m_antialiasing->Begin(); +} + +void OPENGL_COMPOSITOR::DrawBuffer(unsigned int aBufferHandle) +{ + m_antialiasing->DrawBuffer( aBufferHandle ); +} + +void OPENGL_COMPOSITOR::DrawBuffer(unsigned int aSourceHandle, unsigned int aDestHandle) { assert( m_initialized ); - assert( aBufferHandle != 0 && aBufferHandle <= usedBuffers() ); + assert( aSourceHandle != 0 && aSourceHandle <= usedBuffers() ); + assert (aDestHandle <= usedBuffers() ); // Switch to the main framebuffer and blit the scene - bindFb( DIRECT_RENDERING ); + bindFb( aDestHandle ); // Depth test has to be disabled to make transparency working glDisable( GL_DEPTH_TEST ); @@ -238,7 +275,7 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) // Enable texturing and bind the main texture glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, m_buffers[aBufferHandle - 1].textureTarget ); + glBindTexture( GL_TEXTURE_2D, m_buffers[aSourceHandle - 1].textureTarget ); // Draw a full screen quad with the texture glMatrixMode( GL_MODELVIEW ); @@ -249,19 +286,19 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) glLoadIdentity(); glBegin( GL_TRIANGLES ); - glTexCoord2f( 0.0f, 1.0f ); - glVertex2f( -1.0f, -1.0f ); - glTexCoord2f( 1.0f, 1.0f ); - glVertex2f( 1.0f, -1.0f ); - glTexCoord2f( 1.0f, 0.0f ); - glVertex2f( 1.0f, 1.0f ); + glTexCoord2f( 0.0f, 1.0f ); + glVertex2f ( -1.0f, 1.0f ); + glTexCoord2f( 0.0f, 0.0f ); + glVertex2f ( -1.0f, -1.0f ); + glTexCoord2f( 1.0f, 1.0f ); + glVertex2f ( 1.0f, 1.0f ); - glTexCoord2f( 0.0f, 1.0f ); - glVertex2f( -1.0f, -1.0f ); - glTexCoord2f( 1.0f, 0.0f ); - glVertex2f( 1.0f, 1.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex2f( -1.0f, 1.0f ); + glTexCoord2f( 1.0f, 1.0f ); + glVertex2f ( 1.0f, 1.0f ); + glTexCoord2f( 0.0f, 0.0f ); + glVertex2f ( -1.0f, -1.0f ); + glTexCoord2f( 1.0f, 0.0f ); + glVertex2f ( 1.0f, -1.0f ); glEnd(); glPopMatrix(); @@ -269,6 +306,10 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) glPopMatrix(); } +void OPENGL_COMPOSITOR::Present() +{ + m_antialiasing->Present(); +} void OPENGL_COMPOSITOR::bindFb( unsigned int aFb ) { // Currently there are only 2 valid FBOs diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 7a3f26bf22..29b783e45f 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -199,19 +199,12 @@ void OPENGL_GAL::BeginDrawing() GL_CONTEXT_MANAGER::Get().LockCtx( glPrivContext, this ); -#ifdef RETINA_OPENGL_PATCH - const float scaleFactor = GetBackingScaleFactor(); -#else - const float scaleFactor = 1.0f; -#endif - // Set up the view port glMatrixMode( GL_PROJECTION ); glLoadIdentity(); - glViewport( 0, 0, (GLsizei) screenSize.x * scaleFactor, (GLsizei) screenSize.y * scaleFactor ); - // Create the screen transformation - glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); + // Create the screen transformation (Do the RH-LH conversion here) + glOrtho( 0, (GLint) screenSize.x, (GLsizei) screenSize.y, 0, -depthRange.x, -depthRange.y ); if( !isFramebufferInitialized ) { @@ -223,6 +216,8 @@ void OPENGL_GAL::BeginDrawing() isFramebufferInitialized = true; } + compositor->Begin(); + // Disable 2D Textures glDisable( GL_TEXTURE_2D ); @@ -336,6 +331,7 @@ void OPENGL_GAL::EndDrawing() // Draw the remaining contents, blit the rendering targets to the screen, swap the buffers compositor->DrawBuffer( mainBuffer ); compositor->DrawBuffer( overlayBuffer ); + compositor->Present(); blitCursor(); SwapBuffers(); diff --git a/include/gal/cairo/cairo_compositor.h b/include/gal/cairo/cairo_compositor.h index 906458f5ef..3b3fb92bbe 100644 --- a/include/gal/cairo/cairo_compositor.h +++ b/include/gal/cairo/cairo_compositor.h @@ -62,12 +62,18 @@ public: /// @copydoc COMPOSITOR::SetBuffer() virtual void SetBuffer( unsigned int aBufferHandle ) override; + /// @copydoc COMPOSITOR::Begin() + virtual void Begin() override; + /// @copydoc COMPOSITOR::ClearBuffer() virtual void ClearBuffer() override; /// @copydoc COMPOSITOR::DrawBuffer() virtual void DrawBuffer( unsigned int aBufferHandle ) override; + /// @copydoc COMPOSITOR::Present() + virtual void Present() override; + /** * Function SetMainContext() * Sets a context to be treated as the main context (ie. as a target of buffers rendering and diff --git a/include/gal/compositor.h b/include/gal/compositor.h index cd1d636a9a..2b605e1ae1 100644 --- a/include/gal/compositor.h +++ b/include/gal/compositor.h @@ -88,14 +88,26 @@ public: */ virtual void ClearBuffer() = 0; + /** + * Function Begin() + * Call this at the beginning of each frame + */ + virtual void Begin() = 0; + /** * Function DrawBuffer() - * draws the selected buffer on the screen. + * draws the selected buffer to the output buffer. * * @param aBufferHandle is the handle of the buffer to be drawn. */ virtual void DrawBuffer( unsigned int aBufferHandle ) = 0; + /** + * Function Present() + * Call this to present the output buffer to the screen. + */ + virtual void Present() = 0; + protected: unsigned int m_width; ///< Width of the buffer (in pixels) unsigned int m_height; ///< Height of the buffer (in pixels) diff --git a/include/gal/opengl/opengl_compositor.h b/include/gal/opengl/opengl_compositor.h index e1fe0e52bf..9cee8bc37c 100644 --- a/include/gal/opengl/opengl_compositor.h +++ b/include/gal/opengl/opengl_compositor.h @@ -32,11 +32,13 @@ #define OPENGL_COMPOSITOR_H_ #include +#include #include #include namespace KIGFX { + class OPENGL_COMPOSITOR : public COMPOSITOR { public: @@ -70,13 +72,26 @@ public: /// @copydoc COMPOSITOR::DrawBuffer() virtual void DrawBuffer( unsigned int aBufferHandle ) override; + /// @copydoc COMPOSITOR::Begin() + virtual void Begin() override; + + // @copydoc COMPOSITOR::Present() + virtual void Present() override; + // Constant used by glBindFramebuffer to turn off rendering to framebuffers static const unsigned int DIRECT_RENDERING = 0; +public: + VECTOR2U GetScreenSize() const; + GLenum GetBufferTexture( unsigned int aBufferHandle ); + void DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle ); + unsigned int CreateBuffer( VECTOR2U aDimensions ); + protected: // Buffers are simply textures storing a result of certain target rendering. typedef struct { + VECTOR2U dimensions; GLuint textureTarget; ///< Main texture handle GLuint attachmentPoint; ///< Point to which an image from texture is attached } OPENGL_BUFFER; @@ -93,6 +108,8 @@ protected: /// Store the used FBO name in case there was more than one compositor used GLuint m_curFbo; + std::unique_ptr< OPENGL_PRESENTOR > m_antialiasing; + /// Binds a specific Framebuffer Object. void bindFb( unsigned int aFb ); diff --git a/include/math/vector2d.h b/include/math/vector2d.h index e919ba9f9b..df2cfda261 100644 --- a/include/math/vector2d.h +++ b/include/math/vector2d.h @@ -576,8 +576,9 @@ std::ostream& operator<<( std::ostream& aStream, const VECTOR2& aVector ) /* Default specializations */ -typedef VECTOR2 VECTOR2D; -typedef VECTOR2 VECTOR2I; +typedef VECTOR2 VECTOR2D; +typedef VECTOR2 VECTOR2I; +typedef VECTOR2 VECTOR2U; /* Compatibility typedefs */ // FIXME should be removed to avoid multiple typedefs for the same type