Refactor COMPOSITOR/OPENGL_COMPOSITOR to enable customization of scene rendering and presentation

This commit is contained in:
decimad 2016-12-22 18:58:29 +01:00 committed by Maciej Suminski
parent 77f9cd0cb0
commit 02bb410cdb
10 changed files with 215 additions and 33 deletions

View File

@ -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

View File

@ -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()
{

View File

@ -0,0 +1,56 @@
#include <gal/opengl/antialiasing.h>
#include <gal/opengl/opengl_compositor.h>
#include <gal/opengl/utils.h>
#include <tuple>
#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() );
}
}

View File

@ -0,0 +1,46 @@
#ifndef OPENGL_ANTIALIASING_H__
#define OPENGL_ANTIALIASING_H__
#include <memory>
#include <gal/opengl/shader.h>
#include <math/vector2d.h>
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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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)

View File

@ -32,11 +32,13 @@
#define OPENGL_COMPOSITOR_H_
#include <gal/compositor.h>
#include <gal/opengl/antialiasing.h>
#include <GL/glew.h>
#include <deque>
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 );

View File

@ -576,8 +576,9 @@ std::ostream& operator<<( std::ostream& aStream, const VECTOR2<T>& aVector )
/* Default specializations */
typedef VECTOR2<double> VECTOR2D;
typedef VECTOR2<int> VECTOR2I;
typedef VECTOR2<double> VECTOR2D;
typedef VECTOR2<int> VECTOR2I;
typedef VECTOR2<unsigned int> VECTOR2U;
/* Compatibility typedefs */
// FIXME should be removed to avoid multiple typedefs for the same type