2011-11-16 22:17:37 +00:00
/*
2014-09-07 15:22:23 +00:00
* Copyright ( C ) 2011 - 2014 Gregory hainaut
2011-11-16 22:17:37 +00:00
* Copyright ( C ) 2007 - 2009 Gabest
*
* This Program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* This Program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with GNU Make ; see the file COPYING . If not , write to
2012-09-09 18:16:11 +00:00
* the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA USA .
2011-11-16 22:17:37 +00:00
* http : //www.gnu.org/copyleft/gpl.html
*
*/
2013-01-10 13:13:59 +00:00
# include "stdafx.h"
2011-11-16 22:17:37 +00:00
# include "GSDeviceOGL.h"
2013-08-05 20:25:25 +00:00
# include "GLState.h"
2014-11-09 14:27:24 +00:00
# include <fstream>
2011-11-16 22:17:37 +00:00
2013-07-07 16:13:11 +00:00
# include "res/glsl_source.h"
2013-05-18 09:17:30 +00:00
2012-01-12 07:29:31 +00:00
//#define LOUD_DEBUGGING
2012-01-04 23:19:17 +00:00
//#define PRINT_FRAME_NUMBER
//#define ONLY_LINES
2011-12-29 14:24:26 +00:00
static uint32 g_draw_count = 0 ;
2014-09-07 15:22:23 +00:00
static uint32 g_frame_count = 1 ;
2014-03-24 14:03:02 +00:00
# ifdef ENABLE_OGL_DEBUG_MEM_BW
uint32 g_texture_upload_byte = 0 ;
uint32 g_vertex_upload_byte = 0 ;
# endif
2011-12-29 14:24:26 +00:00
2013-04-19 19:16:26 +00:00
static const uint32 g_merge_cb_index = 10 ;
static const uint32 g_interlace_cb_index = 11 ;
static const uint32 g_shadeboost_cb_index = 12 ;
2014-11-09 14:27:24 +00:00
static const uint32 g_fx_cb_index = 14 ;
2011-12-29 14:24:26 +00:00
2011-11-16 22:17:37 +00:00
GSDeviceOGL : : GSDeviceOGL ( )
2011-11-21 22:36:03 +00:00
: m_free_window ( false )
, m_window ( NULL )
2011-12-10 19:19:44 +00:00
, m_fbo ( 0 )
2012-01-08 21:59:42 +00:00
, m_fbo_read ( 0 )
2014-10-02 07:33:41 +00:00
, m_va ( NULL )
2013-07-06 10:08:52 +00:00
, m_shader ( NULL )
2011-11-16 22:17:37 +00:00
{
2012-01-08 21:59:42 +00:00
memset ( & m_merge_obj , 0 , sizeof ( m_merge_obj ) ) ;
2011-11-21 22:36:03 +00:00
memset ( & m_interlace , 0 , sizeof ( m_interlace ) ) ;
memset ( & m_convert , 0 , sizeof ( m_convert ) ) ;
2014-11-09 14:27:24 +00:00
memset ( & m_fxaa , 0 , sizeof ( m_fxaa ) ) ;
memset ( & m_shaderfx , 0 , sizeof ( m_shaderfx ) ) ;
2011-11-21 22:36:03 +00:00
memset ( & m_date , 0 , sizeof ( m_date ) ) ;
memset ( & m_state , 0 , sizeof ( m_state ) ) ;
2013-08-05 20:25:25 +00:00
GLState : : Clear ( ) ;
2012-01-31 17:08:05 +00:00
// Reset the debug file
2013-01-16 18:25:53 +00:00
# ifdef ENABLE_OGL_DEBUG
2012-01-31 17:08:05 +00:00
FILE * f = fopen ( " Debug.txt " , " w " ) ;
fclose ( f ) ;
2012-05-11 20:52:50 +00:00
# endif
2011-11-16 22:17:37 +00:00
}
2011-11-21 22:36:03 +00:00
GSDeviceOGL : : ~ GSDeviceOGL ( )
{
2013-07-06 10:08:52 +00:00
// If the create function wasn't called nothing to do.
if ( m_shader = = NULL )
return ;
2011-12-15 18:27:58 +00:00
// Clean vertex buffer state
2014-10-02 07:33:41 +00:00
delete ( m_va ) ;
2011-12-15 18:27:58 +00:00
2012-01-08 21:59:42 +00:00
// Clean m_merge_obj
2014-01-12 11:38:50 +00:00
for ( size_t i = 0 ; i < countof ( m_merge_obj . ps ) ; i + + )
2013-07-06 10:08:52 +00:00
m_shader - > Delete ( m_merge_obj . ps [ i ] ) ;
2012-01-08 21:59:42 +00:00
delete ( m_merge_obj . cb ) ;
delete ( m_merge_obj . bs ) ;
2013-07-06 10:08:52 +00:00
2011-11-26 11:46:51 +00:00
// Clean m_interlace
2014-01-12 11:38:50 +00:00
for ( size_t i = 0 ; i < countof ( m_interlace . ps ) ; i + + )
2013-07-06 10:08:52 +00:00
m_shader - > Delete ( m_interlace . ps [ i ] ) ;
2011-11-26 11:46:51 +00:00
delete ( m_interlace . cb ) ;
// Clean m_convert
2013-07-06 10:08:52 +00:00
m_shader - > Delete ( m_convert . vs ) ;
2014-01-12 11:38:50 +00:00
for ( size_t i = 0 ; i < countof ( m_convert . ps ) ; i + + )
2013-07-06 10:08:52 +00:00
m_shader - > Delete ( m_convert . ps [ i ] ) ;
2011-11-26 11:46:51 +00:00
delete m_convert . dss ;
delete m_convert . bs ;
2013-06-14 21:22:44 +00:00
// Clean m_fxaa
delete m_fxaa . cb ;
2013-07-06 10:08:52 +00:00
m_shader - > Delete ( m_fxaa . ps ) ;
2013-06-14 21:22:44 +00:00
2014-11-09 14:27:24 +00:00
// Clean m_shaderfx
delete m_shaderfx . cb ;
m_shader - > Delete ( m_shaderfx . ps ) ;
2011-11-26 11:46:51 +00:00
// Clean m_date
delete m_date . dss ;
delete m_date . bs ;
2013-06-30 11:18:46 +00:00
// Clean shadeboost
delete m_shadeboost . cb ;
2013-07-06 10:08:52 +00:00
m_shader - > Delete ( m_shadeboost . ps ) ;
2013-06-30 11:18:46 +00:00
2011-11-26 11:46:51 +00:00
// Clean various opengl allocation
2013-05-19 09:19:20 +00:00
gl_DeleteFramebuffers ( 1 , & m_fbo ) ;
gl_DeleteFramebuffers ( 1 , & m_fbo_read ) ;
2011-12-21 19:08:31 +00:00
// Delete HW FX
delete m_vs_cb ;
delete m_ps_cb ;
2013-06-09 16:41:58 +00:00
gl_DeleteSamplers ( 1 , & m_palette_ss ) ;
2013-08-28 08:44:16 +00:00
m_shader - > Delete ( m_apitrace ) ;
2011-12-21 19:08:31 +00:00
2013-07-06 10:08:52 +00:00
for ( uint32 key = 0 ; key < VSSelector : : size ( ) ; key + + ) m_shader - > Delete ( m_vs [ key ] ) ;
2013-08-14 10:18:38 +00:00
m_shader - > Delete ( m_gs ) ;
2013-07-06 10:08:52 +00:00
for ( auto it = m_ps . begin ( ) ; it ! = m_ps . end ( ) ; it + + ) m_shader - > Delete ( it - > second ) ;
2013-06-30 11:18:46 +00:00
m_ps . clear ( ) ;
2013-05-17 20:14:10 +00:00
2013-06-26 20:09:07 +00:00
gl_DeleteSamplers ( PSSamplerSelector : : size ( ) , m_ps_ss ) ;
for ( uint32 key = 0 ; key < OMDepthStencilSelector : : size ( ) ; key + + ) delete m_om_dss [ key ] ;
2013-06-30 11:18:46 +00:00
for ( auto it = m_om_bs . begin ( ) ; it ! = m_om_bs . end ( ) ; it + + ) delete it - > second ;
2011-12-21 19:08:31 +00:00
m_om_bs . clear ( ) ;
2013-07-07 16:13:11 +00:00
2013-08-03 08:29:01 +00:00
PboPool : : Destroy ( ) ;
2013-07-07 16:13:11 +00:00
// Must be done after the destruction of all shader/program objects
delete m_shader ;
m_shader = NULL ;
2011-11-21 22:36:03 +00:00
}
2011-11-16 22:17:37 +00:00
GSTexture * GSDeviceOGL : : CreateSurface ( int type , int w , int h , bool msaa , int format )
{
// A wrapper to call GSTextureOGL, with the different kind of parameter
2011-11-21 22:36:03 +00:00
GSTextureOGL * t = NULL ;
2013-07-19 19:25:50 +00:00
t = new GSTextureOGL ( type , w , h , format , m_fbo_read ) ;
2011-11-21 22:36:03 +00:00
switch ( type )
{
case GSTexture : : RenderTarget :
ClearRenderTarget ( t , 0 ) ;
break ;
case GSTexture : : DepthStencil :
ClearDepth ( t , 0 ) ;
2013-07-19 19:25:50 +00:00
// No need to clear the stencil now.
2011-11-21 22:36:03 +00:00
break ;
}
return t ;
2011-11-16 22:17:37 +00:00
}
GSTexture * GSDeviceOGL : : FetchSurface ( int type , int w , int h , bool msaa , int format )
{
2013-07-19 19:25:50 +00:00
return GSDevice : : FetchSurface ( type , w , h , false , format ) ;
2011-11-16 22:17:37 +00:00
}
bool GSDeviceOGL : : Create ( GSWnd * wnd )
{
2011-11-21 22:36:03 +00:00
if ( m_window = = NULL ) {
2014-09-30 20:04:42 +00:00
if ( ! GLLoader : : check_gl_version ( 3 , 3 ) ) return false ;
2011-12-21 23:09:36 +00:00
2013-01-14 09:15:39 +00:00
if ( ! GLLoader : : check_gl_supported_extension ( ) ) return false ;
2011-11-21 22:36:03 +00:00
}
2011-12-08 16:39:14 +00:00
m_window = wnd ;
2011-11-26 11:46:51 +00:00
2014-09-27 16:57:17 +00:00
// ****************************************************************
// Debug helper
// ****************************************************************
2014-09-30 19:56:36 +00:00
# ifndef ENABLE_GLES
2014-09-27 16:57:17 +00:00
# ifdef ENABLE_OGL_DEBUG
2014-10-12 08:40:40 +00:00
gl_DebugMessageCallback ( ( GLDEBUGPROC ) DebugOutputToFile , NULL ) ;
2014-09-27 16:57:17 +00:00
glEnable ( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ) ;
2014-09-30 19:56:36 +00:00
# endif
2014-09-27 16:57:17 +00:00
# endif
2011-11-21 22:36:03 +00:00
// ****************************************************************
// Various object
// ****************************************************************
2014-09-27 16:57:17 +00:00
m_shader = new GSShaderOGL ( ! ! theApp . GetConfig ( " debug_glsl_shader " , 0 ) ) ;
2011-11-21 22:36:03 +00:00
2013-05-19 09:19:20 +00:00
gl_GenFramebuffers ( 1 , & m_fbo ) ;
gl_GenFramebuffers ( 1 , & m_fbo_read ) ;
2011-12-10 19:19:44 +00:00
2011-11-21 22:36:03 +00:00
// ****************************************************************
2011-12-15 18:27:58 +00:00
// Vertex buffer state
2011-11-21 22:36:03 +00:00
// ****************************************************************
2014-10-02 07:33:41 +00:00
ASSERT ( sizeof ( GSVertexPT1 ) = = sizeof ( GSVertex ) ) ;
GSInputLayoutOGL il_convert [ ] =
2011-11-21 22:36:03 +00:00
{
2014-10-02 07:33:41 +00:00
{ 2 , GL_FLOAT , GL_FALSE , sizeof ( GSVertexPT1 ) , ( const GLvoid * ) ( 0 ) } ,
{ 2 , GL_FLOAT , GL_FALSE , sizeof ( GSVertexPT1 ) , ( const GLvoid * ) ( 16 ) } ,
{ 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof ( GSVertex ) , ( const GLvoid * ) ( 8 ) } ,
{ 1 , GL_FLOAT , GL_FALSE , sizeof ( GSVertex ) , ( const GLvoid * ) ( 12 ) } ,
{ 2 , GL_UNSIGNED_SHORT , GL_FALSE , sizeof ( GSVertex ) , ( const GLvoid * ) ( 16 ) } ,
{ 1 , GL_UNSIGNED_INT , GL_FALSE , sizeof ( GSVertex ) , ( const GLvoid * ) ( 20 ) } ,
{ 2 , GL_UNSIGNED_SHORT , GL_FALSE , sizeof ( GSVertex ) , ( const GLvoid * ) ( 24 ) } ,
{ 4 , GL_UNSIGNED_BYTE , GL_TRUE , sizeof ( GSVertex ) , ( const GLvoid * ) ( 28 ) } ,
2011-11-21 22:36:03 +00:00
} ;
2014-10-02 07:33:41 +00:00
m_va = new GSVertexBufferStateOGL ( sizeof ( GSVertexPT1 ) , il_convert , countof ( il_convert ) ) ;
2011-11-21 22:36:03 +00:00
2013-08-02 16:38:12 +00:00
// ****************************************************************
// Texture unit state
// ****************************************************************
// By default use unit 3 for texture modification
// unit 0-2 will allocated to shader input
gl_ActiveTexture ( GL_TEXTURE0 + 3 ) ;
2013-08-17 08:57:52 +00:00
// ****************************************************************
// Pre Generate the different sampler object
// ****************************************************************
for ( uint32 key = 0 ; key < PSSamplerSelector : : size ( ) ; key + + )
m_ps_ss [ key ] = CreateSampler ( PSSamplerSelector ( key ) ) ;
2013-08-02 16:38:12 +00:00
2011-12-15 18:27:58 +00:00
// ****************************************************************
// convert
// ****************************************************************
2013-07-06 10:08:52 +00:00
m_convert . vs = m_shader - > Compile ( " convert.glsl " , " vs_main " , GL_VERTEX_SHADER , convert_glsl ) ;
2013-06-29 12:02:03 +00:00
for ( size_t i = 0 ; i < countof ( m_convert . ps ) ; i + + )
2013-07-06 10:08:52 +00:00
m_convert . ps [ i ] = m_shader - > Compile ( " convert.glsl " , format ( " ps_main%d " , i ) , GL_FRAGMENT_SHADER , convert_glsl ) ;
2011-11-21 22:36:03 +00:00
// Note the following object are initialized to 0 so disabled.
// Note: maybe enable blend with a factor of 1
// m_convert.dss, m_convert.bs
2013-08-17 08:57:52 +00:00
PSSamplerSelector point ;
m_convert . pt = GetSamplerID ( point ) ;
PSSamplerSelector bilinear ;
bilinear . ltf = true ;
m_convert . ln = GetSamplerID ( bilinear ) ;
2011-11-21 22:36:03 +00:00
2011-11-26 11:46:51 +00:00
m_convert . dss = new GSDepthStencilOGL ( ) ;
m_convert . bs = new GSBlendStateOGL ( ) ;
2011-11-21 22:36:03 +00:00
// ****************************************************************
// merge
// ****************************************************************
2013-04-19 19:16:26 +00:00
m_merge_obj . cb = new GSUniformBufferOGL ( g_merge_cb_index , sizeof ( MergeConstantBuffer ) ) ;
2011-11-21 22:36:03 +00:00
2013-06-29 12:02:03 +00:00
for ( size_t i = 0 ; i < countof ( m_merge_obj . ps ) ; i + + )
2013-07-06 10:08:52 +00:00
m_merge_obj . ps [ i ] = m_shader - > Compile ( " merge.glsl " , format ( " ps_main%d " , i ) , GL_FRAGMENT_SHADER , merge_glsl ) ;
2011-11-21 22:36:03 +00:00
2012-01-08 21:59:42 +00:00
m_merge_obj . bs = new GSBlendStateOGL ( ) ;
m_merge_obj . bs - > EnableBlend ( ) ;
m_merge_obj . bs - > SetRGB ( GL_FUNC_ADD , GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2011-11-21 22:36:03 +00:00
// ****************************************************************
// interlace
// ****************************************************************
2013-04-19 19:16:26 +00:00
m_interlace . cb = new GSUniformBufferOGL ( g_interlace_cb_index , sizeof ( InterlaceConstantBuffer ) ) ;
2011-11-21 22:36:03 +00:00
2013-06-29 12:02:03 +00:00
for ( size_t i = 0 ; i < countof ( m_interlace . ps ) ; i + + )
2013-07-06 10:08:52 +00:00
m_interlace . ps [ i ] = m_shader - > Compile ( " interlace.glsl " , format ( " ps_main%d " , i ) , GL_FRAGMENT_SHADER , interlace_glsl ) ;
2012-04-26 21:42:16 +00:00
// ****************************************************************
// Shade boost
// ****************************************************************
2013-04-19 19:16:26 +00:00
m_shadeboost . cb = new GSUniformBufferOGL ( g_shadeboost_cb_index , sizeof ( ShadeBoostConstantBuffer ) ) ;
2012-04-26 21:42:16 +00:00
int ShadeBoost_Contrast = theApp . GetConfig ( " ShadeBoost_Contrast " , 50 ) ;
int ShadeBoost_Brightness = theApp . GetConfig ( " ShadeBoost_Brightness " , 50 ) ;
int ShadeBoost_Saturation = theApp . GetConfig ( " ShadeBoost_Saturation " , 50 ) ;
2013-07-12 21:12:34 +00:00
std : : string shade_macro = format ( " #define SB_SATURATION %d.0 \n " , ShadeBoost_Saturation )
+ format ( " #define SB_BRIGHTNESS %d.0 \n " , ShadeBoost_Brightness )
+ format ( " #define SB_CONTRAST %d.0 \n " , ShadeBoost_Contrast ) ;
2012-04-26 21:42:16 +00:00
2013-07-06 10:08:52 +00:00
m_shadeboost . ps = m_shader - > Compile ( " shadeboost.glsl " , " ps_main " , GL_FRAGMENT_SHADER , shadeboost_glsl , shade_macro ) ;
2011-11-21 22:36:03 +00:00
// ****************************************************************
// rasterization configuration
// ****************************************************************
2013-07-12 21:12:34 +00:00
# ifndef ENABLE_GLES
2011-11-21 22:36:03 +00:00
glPolygonMode ( GL_FRONT_AND_BACK , GL_FILL ) ;
2013-07-12 21:12:34 +00:00
# endif
2011-11-21 22:36:03 +00:00
glDisable ( GL_CULL_FACE ) ;
glEnable ( GL_SCISSOR_TEST ) ;
// FIXME enable it when multisample code will be here
// DX: rd.MultisampleEnable = true;
2013-07-12 21:12:34 +00:00
# ifndef ENABLE_GLES
2011-11-21 22:36:03 +00:00
glDisable ( GL_MULTISAMPLE ) ;
2013-07-12 21:12:34 +00:00
# endif
2012-01-04 23:19:17 +00:00
# ifdef ONLY_LINES
glLineWidth ( 5.0 ) ;
glPolygonMode ( GL_FRONT_AND_BACK , GL_LINE ) ;
# endif
2011-11-21 22:36:03 +00:00
// Hum I don't know for those options but let's hope there are not activated
#if 0
rd . FrontCounterClockwise = false ;
rd . DepthBias = false ;
rd . DepthBiasClamp = 0 ;
rd . SlopeScaledDepthBias = 0 ;
rd . DepthClipEnable = false ; // ???
rd . AntialiasedLineEnable = false ;
# endif
2011-12-21 19:08:31 +00:00
// ****************************************************************
2013-06-14 11:34:44 +00:00
// DATE
2011-12-21 19:08:31 +00:00
// ****************************************************************
m_date . dss = new GSDepthStencilOGL ( ) ;
2012-01-03 13:11:40 +00:00
m_date . dss - > EnableStencil ( ) ;
m_date . dss - > SetStencil ( GL_ALWAYS , GL_REPLACE ) ;
2011-12-21 19:08:31 +00:00
m_date . bs = new GSBlendStateOGL ( ) ;
2013-08-28 08:44:16 +00:00
// FIXME impact image load?
//#ifndef ENABLE_OGL_STENCIL_DEBUG
// // Only keep stencil data
// m_date.bs->SetMask(false, false, false, false);
//#endif
2011-12-21 19:08:31 +00:00
2014-09-27 17:39:17 +00:00
// ****************************************************************
// Use DX coordinate convention
// ****************************************************************
// VS gl_position.z => [-1,-1]
// FS depth => [0, 1]
// because of -1 we loose lot of precision for small GS value
// This extension allow FS depth to range from -1 to 1. So
// gl_position.z could range from [0, 1]
# ifndef ENABLE_GLES
if ( GLLoader : : found_GL_ARB_clip_control ) {
// Change depth convention
gl_ClipControl ( GL_LOWER_LEFT , GL_ZERO_TO_ONE ) ;
}
# endif
2011-12-21 19:08:31 +00:00
// ****************************************************************
// HW renderer shader
// ****************************************************************
CreateTextureFX ( ) ;
2011-11-26 11:46:51 +00:00
2013-08-03 08:29:01 +00:00
// ****************************************************************
// Pbo Pool allocation
// ****************************************************************
PboPool : : Init ( ) ;
2011-11-26 11:46:51 +00:00
// ****************************************************************
// Finish window setup and backbuffer
// ****************************************************************
if ( ! GSDevice : : Create ( wnd ) )
return false ;
2011-11-21 22:36:03 +00:00
GSVector4i rect = wnd - > GetClientRect ( ) ;
Reset ( rect . z , rect . w ) ;
2011-12-21 19:08:31 +00:00
return true ;
2011-11-16 22:17:37 +00:00
}
bool GSDeviceOGL : : Reset ( int w , int h )
{
2011-11-21 22:36:03 +00:00
if ( ! GSDevice : : Reset ( w , h ) )
return false ;
// TODO
// Opengl allocate the backbuffer with the window. The render is done in the backbuffer when
2011-11-26 11:46:51 +00:00
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
2011-11-21 22:36:03 +00:00
// in the backbuffer
2013-07-19 19:25:50 +00:00
m_backbuffer = new GSTextureOGL ( GSTextureOGL : : Backbuffer , w , h , 0 , m_fbo_read ) ;
2011-11-21 22:36:03 +00:00
return true ;
2011-11-16 22:17:37 +00:00
}
2012-10-21 18:10:13 +00:00
void GSDeviceOGL : : SetVSync ( bool enable )
{
m_wnd - > SetVSync ( enable ) ;
}
2011-11-21 22:36:03 +00:00
void GSDeviceOGL : : Flip ( )
{
2011-11-26 11:46:51 +00:00
// FIXME: disable it when code is working
2013-01-16 18:25:53 +00:00
# ifdef ENABLE_OGL_DEBUG
2011-11-26 11:46:51 +00:00
CheckDebugLog ( ) ;
2012-05-11 20:52:50 +00:00
# endif
2012-03-30 19:02:37 +00:00
2011-12-07 22:05:46 +00:00
m_wnd - > Flip ( ) ;
2012-03-30 19:02:37 +00:00
2012-01-04 23:19:17 +00:00
# ifdef PRINT_FRAME_NUMBER
fprintf ( stderr , " Draw %d (Frame %d) \n " , g_draw_count , g_frame_count ) ;
# endif
2013-05-18 16:09:09 +00:00
# if defined(ENABLE_OGL_DEBUG) || defined(PRINT_FRAME_NUMBER)
2013-05-18 09:17:30 +00:00
g_frame_count + + ;
2011-12-29 14:24:26 +00:00
# endif
2011-11-21 22:36:03 +00:00
}
2013-10-24 20:54:27 +00:00
void GSDeviceOGL : : AttachContext ( )
{
if ( m_window )
m_window - > AttachContext ( ) ;
}
void GSDeviceOGL : : DetachContext ( )
{
if ( m_window )
m_window - > DetachContext ( ) ;
}
2013-04-19 19:16:26 +00:00
void GSDeviceOGL : : BeforeDraw ( )
2012-01-15 17:25:49 +00:00
{
2013-07-06 10:08:52 +00:00
m_shader - > UseProgram ( ) ;
2013-08-02 16:38:12 +00:00
2013-10-24 20:54:27 +00:00
# ifdef _DEBUG
ASSERT ( gl_CheckFramebufferStatus ( GL_DRAW_FRAMEBUFFER ) = = GL_FRAMEBUFFER_COMPLETE ) ;
# endif
2013-07-28 14:40:43 +00:00
//#ifdef ENABLE_OGL_STENCIL_DEBUG
// if (m_date.t)
// static_cast<GSTextureOGL*>(m_date.t)->Save(format("/tmp/date_before_%04ld.csv", g_draw_count));
//#endif
2013-04-19 19:16:26 +00:00
}
2012-01-15 17:25:49 +00:00
2013-04-19 19:16:26 +00:00
void GSDeviceOGL : : AfterDraw ( )
{
2013-07-28 14:40:43 +00:00
//#ifdef ENABLE_OGL_STENCIL_DEBUG
// if (m_date.t)
// static_cast<GSTextureOGL*>(m_date.t)->Save(format("/tmp/date_after_%04ld.csv", g_draw_count));
//#endif
2013-08-02 16:38:12 +00:00
# if defined(ENABLE_OGL_DEBUG) || defined(PRINT_FRAME_NUMBER) || defined(ENABLE_OGL_STENCIL_DEBUG)
2011-12-29 14:24:26 +00:00
g_draw_count + + ;
# endif
2011-11-21 22:36:03 +00:00
}
2013-04-19 19:16:26 +00:00
void GSDeviceOGL : : DrawPrimitive ( )
2012-01-15 17:25:49 +00:00
{
2013-04-19 19:16:26 +00:00
BeforeDraw ( ) ;
2014-10-02 07:33:41 +00:00
m_va - > DrawPrimitive ( ) ;
2013-04-19 19:16:26 +00:00
AfterDraw ( ) ;
}
2012-01-15 17:25:49 +00:00
2013-04-19 19:16:26 +00:00
void GSDeviceOGL : : DrawIndexedPrimitive ( )
{
BeforeDraw ( ) ;
2014-10-02 07:33:41 +00:00
m_va - > DrawIndexedPrimitive ( ) ;
2013-04-19 19:16:26 +00:00
AfterDraw ( ) ;
2011-11-21 22:36:03 +00:00
}
2012-02-11 10:22:02 +00:00
void GSDeviceOGL : : DrawIndexedPrimitive ( int offset , int count )
{
2013-07-03 18:42:05 +00:00
ASSERT ( offset + count < = ( int ) m_index . count ) ;
2012-02-11 10:22:02 +00:00
2013-04-19 19:16:26 +00:00
BeforeDraw ( ) ;
2014-10-02 07:33:41 +00:00
m_va - > DrawIndexedPrimitive ( offset , count ) ;
2013-04-19 19:16:26 +00:00
AfterDraw ( ) ;
2012-02-11 10:22:02 +00:00
}
2011-11-21 22:36:03 +00:00
void GSDeviceOGL : : ClearRenderTarget ( GSTexture * t , const GSVector4 & c )
{
2013-08-02 16:38:12 +00:00
if ( GLLoader : : found_GL_ARB_clear_texture ) {
2013-10-24 20:54:27 +00:00
if ( static_cast < GSTextureOGL * > ( t ) - > IsBackbuffer ( ) ) {
glDisable ( GL_SCISSOR_TEST ) ;
OMSetFBO ( 0 ) ;
// glDrawBuffer(GL_BACK); // this is the default when there is no FB
// 0 will select the first drawbuffer ie GL_BACK
gl_ClearBufferfv ( GL_COLOR , 0 , c . v ) ;
glEnable ( GL_SCISSOR_TEST ) ;
} else {
static_cast < GSTextureOGL * > ( t ) - > Clear ( ( const void * ) & c ) ;
}
2011-12-07 22:05:46 +00:00
} else {
2013-08-02 16:38:12 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
if ( static_cast < GSTextureOGL * > ( t ) - > IsBackbuffer ( ) ) {
OMSetFBO ( 0 ) ;
// glDrawBuffer(GL_BACK); // this is the default when there is no FB
// 0 will select the first drawbuffer ie GL_BACK
gl_ClearBufferfv ( GL_COLOR , 0 , c . v ) ;
} else {
OMSetFBO ( m_fbo ) ;
2013-08-05 20:25:25 +00:00
OMAttachRt ( static_cast < GSTextureOGL * > ( t ) - > GetID ( ) ) ;
2013-08-02 16:38:12 +00:00
gl_ClearBufferfv ( GL_COLOR , 0 , c . v ) ;
}
glEnable ( GL_SCISSOR_TEST ) ;
2011-12-07 22:05:46 +00:00
}
2011-11-21 22:36:03 +00:00
}
2011-11-16 22:17:37 +00:00
2011-11-21 22:36:03 +00:00
void GSDeviceOGL : : ClearRenderTarget ( GSTexture * t , uint32 c )
{
GSVector4 color = GSVector4 : : rgba32 ( c ) * ( 1.0f / 255 ) ;
2011-12-07 22:05:46 +00:00
ClearRenderTarget ( t , color ) ;
2011-11-21 22:36:03 +00:00
}
2013-07-28 14:40:43 +00:00
void GSDeviceOGL : : ClearRenderTarget_ui ( GSTexture * t , uint32 c )
{
2013-08-02 16:38:12 +00:00
if ( GLLoader : : found_GL_ARB_clear_texture ) {
static_cast < GSTextureOGL * > ( t ) - > Clear ( ( const void * ) & c ) ;
} else {
uint32 col [ 4 ] = { c , c , c , c } ;
2013-07-28 14:40:43 +00:00
2013-08-02 16:38:12 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
2013-07-28 14:40:43 +00:00
2013-08-02 16:38:12 +00:00
OMSetFBO ( m_fbo ) ;
2013-08-05 20:25:25 +00:00
OMAttachRt ( static_cast < GSTextureOGL * > ( t ) - > GetID ( ) ) ;
2013-07-28 14:40:43 +00:00
2013-08-02 16:38:12 +00:00
gl_ClearBufferuiv ( GL_COLOR , 0 , col ) ;
2013-07-28 14:40:43 +00:00
2013-08-02 16:38:12 +00:00
glEnable ( GL_SCISSOR_TEST ) ;
}
2013-07-28 14:40:43 +00:00
}
2011-11-21 22:36:03 +00:00
void GSDeviceOGL : : ClearDepth ( GSTexture * t , float c )
{
2013-10-24 20:54:27 +00:00
// TODO is it possible with GL44 ClearTexture? no the API is garbage!
2014-09-27 17:33:52 +00:00
// It can't be used here because it will clear both depth and stencil
2013-10-24 20:54:27 +00:00
if ( 0 & & GLLoader : : found_GL_ARB_clear_texture ) {
2014-03-29 10:24:39 +00:00
# ifndef ENABLE_GLES
2014-10-24 18:46:34 +00:00
ASSERT ( c = = 0.0f ) ;
gl_ClearTexImage ( static_cast < GSTextureOGL * > ( t ) - > GetID ( ) , GL_TEX_LEVEL_0 , GL_DEPTH_STENCIL , GL_FLOAT_32_UNSIGNED_INT_24_8_REV , NULL ) ;
2014-03-29 10:24:39 +00:00
# endif
2012-08-08 17:49:23 +00:00
} else {
2013-08-02 16:38:12 +00:00
OMSetFBO ( m_fbo ) ;
2013-08-05 20:25:25 +00:00
OMAttachDs ( static_cast < GSTextureOGL * > ( t ) - > GetID ( ) ) ;
2013-08-02 16:38:12 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
2013-08-05 20:25:25 +00:00
if ( GLState : : depth_mask ) {
2013-08-02 16:38:12 +00:00
gl_ClearBufferfv ( GL_DEPTH , 0 , & c ) ;
} else {
glDepthMask ( true ) ;
gl_ClearBufferfv ( GL_DEPTH , 0 , & c ) ;
glDepthMask ( false ) ;
}
glEnable ( GL_SCISSOR_TEST ) ;
2012-08-08 17:49:23 +00:00
}
2011-11-21 22:36:03 +00:00
}
void GSDeviceOGL : : ClearStencil ( GSTexture * t , uint8 c )
{
2013-10-24 20:54:27 +00:00
// TODO is it possible with GL44 ClearTexture? no the API is garbage!
2014-09-27 17:33:52 +00:00
// It can't be used here because it will clear both depth and stencil
if ( 0 & & GLLoader : : found_GL_ARB_clear_texture ) {
2014-03-29 10:24:39 +00:00
# ifndef ENABLE_GLES
2014-10-24 18:46:34 +00:00
ASSERT ( c = = 0 ) ;
gl_ClearTexImage ( static_cast < GSTextureOGL * > ( t ) - > GetID ( ) , GL_TEX_LEVEL_0 , GL_DEPTH_STENCIL , GL_FLOAT_32_UNSIGNED_INT_24_8_REV , NULL ) ;
2014-03-29 10:24:39 +00:00
# endif
2013-08-02 16:38:12 +00:00
} else {
OMSetFBO ( m_fbo ) ;
2013-08-05 20:25:25 +00:00
OMAttachDs ( static_cast < GSTextureOGL * > ( t ) - > GetID ( ) ) ;
2013-08-02 16:38:12 +00:00
GLint color = c ;
2013-06-01 09:29:57 +00:00
2013-08-02 16:38:12 +00:00
glDisable ( GL_SCISSOR_TEST ) ;
gl_ClearBufferiv ( GL_STENCIL , 0 , & color ) ;
glEnable ( GL_SCISSOR_TEST ) ;
}
2011-11-21 22:36:03 +00:00
}
2013-08-17 08:57:52 +00:00
GLuint GSDeviceOGL : : CreateSampler ( PSSamplerSelector sel )
{
return CreateSampler ( sel . ltf , sel . tau , sel . tav ) ;
}
2013-06-26 20:09:07 +00:00
GLuint GSDeviceOGL : : CreateSampler ( bool bilinear , bool tau , bool tav )
2013-06-09 16:41:58 +00:00
{
2013-06-26 20:09:07 +00:00
GLuint sampler ;
2013-06-09 16:41:58 +00:00
gl_GenSamplers ( 1 , & sampler ) ;
if ( bilinear ) {
gl_SamplerParameteri ( sampler , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
gl_SamplerParameteri ( sampler , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
} else {
gl_SamplerParameteri ( sampler , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
gl_SamplerParameteri ( sampler , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
}
// FIXME ensure U -> S, V -> T and W->R
if ( tau )
gl_SamplerParameteri ( sampler , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
else
gl_SamplerParameteri ( sampler , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
if ( tav )
gl_SamplerParameteri ( sampler , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
else
gl_SamplerParameteri ( sampler , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
gl_SamplerParameteri ( sampler , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
// FIXME which value for GL_TEXTURE_MIN_LOD
gl_SamplerParameterf ( sampler , GL_TEXTURE_MAX_LOD , FLT_MAX ) ;
// FIXME: seems there is 2 possibility in opengl
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
// gl_SamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
2014-09-07 15:26:12 +00:00
#if 0
// Message:Program undefined behavior warning: Sampler object 5 has depth compare enabled. It is being used with non-depth texture 7, by a program that samples it with a regular sampler. This is undefined behavior.
2013-06-09 16:41:58 +00:00
gl_SamplerParameteri ( sampler , GL_TEXTURE_COMPARE_MODE , GL_COMPARE_REF_TO_TEXTURE ) ;
gl_SamplerParameteri ( sampler , GL_TEXTURE_COMPARE_FUNC , GL_NEVER ) ;
2014-09-07 15:26:12 +00:00
# endif
2013-06-09 16:41:58 +00:00
// FIXME: need ogl extension sd.MaxAnisotropy = 16;
2013-06-26 20:09:07 +00:00
return sampler ;
2013-06-09 16:41:58 +00:00
}
2013-07-28 14:40:43 +00:00
void GSDeviceOGL : : InitPrimDateTexture ( int w , int h )
{
// Create a texture to avoid the useless clean@0
if ( m_date . t = = NULL )
2013-08-28 08:44:16 +00:00
m_date . t = CreateTexture ( w , h , GL_R32I ) ;
2013-07-28 14:40:43 +00:00
2013-08-28 08:44:16 +00:00
ClearRenderTarget_ui ( m_date . t , 0x0FFFFFFF ) ;
2013-07-28 14:40:43 +00:00
# ifdef ENABLE_OGL_STENCIL_DEBUG
2013-08-02 16:38:12 +00:00
gl_ActiveTexture ( GL_TEXTURE0 + 5 ) ;
glBindTexture ( GL_TEXTURE_2D , static_cast < GSTextureOGL * > ( m_date . t ) - > GetID ( ) ) ;
// Get back to the expected active texture unit
gl_ActiveTexture ( GL_TEXTURE0 + 3 ) ;
2013-07-28 14:40:43 +00:00
# endif
2013-08-02 16:38:12 +00:00
BindDateTexture ( ) ;
}
void GSDeviceOGL : : BindDateTexture ( )
{
// TODO: multibind?
// GLuint textures[1] = {static_cast<GSTextureOGL*>(m_date.t)->GetID()};
2013-10-24 20:54:27 +00:00
// gl_BindImageTextures(2, 1, textures);
//gl_BindImageTexture(2, 0, 0, true, 0, GL_READ_WRITE, GL_R32I);
2013-08-02 16:38:12 +00:00
2014-03-29 10:24:39 +00:00
# ifndef ENABLE_GLES
2013-10-24 20:54:27 +00:00
gl_BindImageTexture ( 2 , static_cast < GSTextureOGL * > ( m_date . t ) - > GetID ( ) , 0 , false , 0 , GL_READ_WRITE , GL_R32I ) ;
2014-03-29 10:24:39 +00:00
# endif
2013-07-28 14:40:43 +00:00
}
void GSDeviceOGL : : RecycleDateTexture ( )
{
if ( m_date . t ) {
# ifdef ENABLE_OGL_STENCIL_DEBUG
//static_cast<GSTextureOGL*>(m_date.t)->Save(format("/tmp/date_adv_%04ld.csv", g_draw_count));
# endif
// FIXME invalidate data
Recycle ( m_date . t ) ;
m_date . t = NULL ;
}
}
2013-08-02 16:38:12 +00:00
void GSDeviceOGL : : Barrier ( GLbitfield b )
{
2014-03-29 10:24:39 +00:00
# ifndef ENABLE_GLES
2013-08-02 16:38:12 +00:00
gl_MemoryBarrier ( b ) ;
//#ifdef ENABLE_OGL_STENCIL_DEBUG
// if (m_date.t)
// static_cast<GSTextureOGL*>(m_date.t)->Save(format("/tmp/barrier_%04ld.csv", g_draw_count));
//#endif
2014-03-29 10:24:39 +00:00
# endif
2013-08-02 16:38:12 +00:00
}
2013-08-10 19:43:59 +00:00
/* Note: must be here because tfx_glsl is static */
2013-07-07 16:13:11 +00:00
GLuint GSDeviceOGL : : CompileVS ( VSSelector sel )
{
std : : string macro = format ( " #define VS_BPPZ %d \n " , sel . bppz )
+ format ( " #define VS_LOGZ %d \n " , sel . logz )
+ format ( " #define VS_TME %d \n " , sel . tme )
2013-08-14 10:18:38 +00:00
+ format ( " #define VS_FST %d \n " , sel . fst )
2015-04-13 16:34:43 +00:00
+ format ( " #define VS_WILDHACK %d \n " , sel . wildhack )
2013-08-14 10:18:38 +00:00
;
2013-07-07 16:13:11 +00:00
return m_shader - > Compile ( " tfx.glsl " , " vs_main " , GL_VERTEX_SHADER , tfx_glsl , macro ) ;
}
2013-08-10 19:43:59 +00:00
/* Note: must be here because tfx_glsl is static */
2013-08-14 10:18:38 +00:00
GLuint GSDeviceOGL : : CompileGS ( )
2013-07-07 16:13:11 +00:00
{
2013-07-13 11:39:45 +00:00
# ifdef ENABLE_GLES
return 0 ;
# else
2013-08-14 10:18:38 +00:00
return m_shader - > Compile ( " tfx.glsl " , " gs_main " , GL_GEOMETRY_SHADER , tfx_glsl , " " ) ;
2013-07-13 11:39:45 +00:00
# endif
2013-07-07 16:13:11 +00:00
}
2013-08-10 19:43:59 +00:00
/* Note: must be here because tfx_glsl is static */
2013-07-07 16:13:11 +00:00
GLuint GSDeviceOGL : : CompilePS ( PSSelector sel )
{
std : : string macro = format ( " #define PS_FST %d \n " , sel . fst )
+ format ( " #define PS_WMS %d \n " , sel . wms )
+ format ( " #define PS_WMT %d \n " , sel . wmt )
+ format ( " #define PS_FMT %d \n " , sel . fmt )
+ format ( " #define PS_AEM %d \n " , sel . aem )
+ format ( " #define PS_TFX %d \n " , sel . tfx )
+ format ( " #define PS_TCC %d \n " , sel . tcc )
+ format ( " #define PS_ATST %d \n " , sel . atst )
+ format ( " #define PS_FOG %d \n " , sel . fog )
+ format ( " #define PS_CLR1 %d \n " , sel . clr1 )
+ format ( " #define PS_FBA %d \n " , sel . fba )
+ format ( " #define PS_AOUT %d \n " , sel . aout )
+ format ( " #define PS_LTF %d \n " , sel . ltf )
+ format ( " #define PS_COLCLIP %d \n " , sel . colclip )
+ format ( " #define PS_DATE %d \n " , sel . date )
+ format ( " #define PS_SPRITEHACK %d \n " , sel . spritehack )
+ format ( " #define PS_TCOFFSETHACK %d \n " , sel . tcoffsethack )
2013-08-14 10:18:38 +00:00
+ format ( " #define PS_POINT_SAMPLER %d \n " , sel . point_sampler )
+ format ( " #define PS_IIP %d \n " , sel . iip )
;
2013-07-07 16:13:11 +00:00
return m_shader - > Compile ( " tfx.glsl " , " ps_main " , GL_FRAGMENT_SHADER , tfx_glsl , macro ) ;
}
2011-11-21 22:36:03 +00:00
GSTexture * GSDeviceOGL : : CreateRenderTarget ( int w , int h , bool msaa , int format )
{
return GSDevice : : CreateRenderTarget ( w , h , msaa , format ? format : GL_RGBA8 ) ;
}
GSTexture * GSDeviceOGL : : CreateDepthStencil ( int w , int h , bool msaa , int format )
{
return GSDevice : : CreateDepthStencil ( w , h , msaa , format ? format : GL_DEPTH32F_STENCIL8 ) ;
}
2011-11-16 22:17:37 +00:00
2011-11-21 22:36:03 +00:00
GSTexture * GSDeviceOGL : : CreateTexture ( int w , int h , int format )
{
return GSDevice : : CreateTexture ( w , h , format ? format : GL_RGBA8 ) ;
}
2011-11-16 22:17:37 +00:00
2011-11-21 22:36:03 +00:00
GSTexture * GSDeviceOGL : : CreateOffscreen ( int w , int h , int format )
{
return GSDevice : : CreateOffscreen ( w , h , format ? format : GL_RGBA8 ) ;
}
2011-11-16 22:17:37 +00:00
// blit a texture into an offscreen buffer
GSTexture * GSDeviceOGL : : CopyOffscreen ( GSTexture * src , const GSVector4 & sr , int w , int h , int format )
{
2013-07-19 19:25:50 +00:00
ASSERT ( src ) ;
ASSERT ( format = = GL_RGBA8 | | format = = GL_R16UI ) ;
2011-11-16 22:17:37 +00:00
2011-12-23 12:32:40 +00:00
if ( format = = 0 ) format = GL_RGBA8 ;
2011-11-16 22:17:37 +00:00
2013-07-19 19:25:50 +00:00
if ( format ! = GL_RGBA8 & & format ! = GL_R16UI ) return NULL ;
2011-11-16 22:17:37 +00:00
2013-07-19 19:25:50 +00:00
GSTexture * dst = CreateOffscreen ( w , h , format ) ;
GSVector4 dr ( 0 , 0 , w , h ) ;
2012-03-05 20:16:26 +00:00
2013-07-19 19:25:50 +00:00
StretchRect ( src , sr , dst , dr , m_convert . ps [ format = = GL_R16UI ? 1 : 0 ] ) ;
2011-11-16 22:17:37 +00:00
2012-03-05 20:16:26 +00:00
return dst ;
2011-11-16 22:17:37 +00:00
}
// Copy a sub part of a texture into another
// Several question to answer did texture have same size?
// From a sub-part to the same sub-part
// From a sub-part to a full texture
void GSDeviceOGL : : CopyRect ( GSTexture * st , GSTexture * dt , const GSVector4i & r )
{
2013-07-19 19:25:50 +00:00
ASSERT ( st & & dt ) ;
2011-11-16 22:17:37 +00:00
2013-08-03 08:29:01 +00:00
if ( GLLoader : : found_GL_ARB_copy_image ) {
2013-07-13 11:39:45 +00:00
# ifndef ENABLE_GLES
2013-07-19 19:25:50 +00:00
gl_CopyImageSubData ( static_cast < GSTextureOGL * > ( st ) - > GetID ( ) , GL_TEXTURE_2D ,
2013-05-27 16:53:38 +00:00
0 , r . x , r . y , 0 ,
2013-07-19 19:25:50 +00:00
static_cast < GSTextureOGL * > ( dt ) - > GetID ( ) , GL_TEXTURE_2D ,
2013-05-27 16:53:38 +00:00
0 , r . x , r . y , 0 ,
r . width ( ) , r . height ( ) , 1 ) ;
# endif
} else {
2013-05-27 18:02:27 +00:00
GSTextureOGL * st_ogl = ( GSTextureOGL * ) st ;
GSTextureOGL * dt_ogl = ( GSTextureOGL * ) dt ;
gl_BindFramebuffer ( GL_READ_FRAMEBUFFER , m_fbo_read ) ;
2013-07-19 19:25:50 +00:00
gl_FramebufferTexture2D ( GL_READ_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , static_cast < GSTextureOGL * > ( st_ogl ) - > GetID ( ) , 0 ) ;
glReadBuffer ( GL_COLOR_ATTACHMENT0 ) ;
2013-08-02 16:38:12 +00:00
dt_ogl - > EnableUnit ( ) ;
2013-07-19 19:25:50 +00:00
glCopyTexSubImage2D ( GL_TEXTURE_2D , 0 , r . x , r . y , r . x , r . y , r . width ( ) , r . height ( ) ) ;
2013-05-27 18:02:27 +00:00
gl_BindFramebuffer ( GL_READ_FRAMEBUFFER , 0 ) ;
2013-05-27 16:53:38 +00:00
}
2011-11-16 22:17:37 +00:00
}
void GSDeviceOGL : : StretchRect ( GSTexture * st , const GSVector4 & sr , GSTexture * dt , const GSVector4 & dr , int shader , bool linear )
{
2011-12-11 19:11:01 +00:00
StretchRect ( st , sr , dt , dr , m_convert . ps [ shader ] , linear ) ;
2011-11-16 22:17:37 +00:00
}
2011-11-21 22:36:03 +00:00
2011-12-11 19:11:01 +00:00
void GSDeviceOGL : : StretchRect ( GSTexture * st , const GSVector4 & sr , GSTexture * dt , const GSVector4 & dr , GLuint ps , bool linear )
2011-11-16 22:17:37 +00:00
{
2011-12-11 19:11:01 +00:00
StretchRect ( st , sr , dt , dr , ps , m_convert . bs , linear ) ;
2011-11-16 22:17:37 +00:00
}
2011-12-11 19:11:01 +00:00
void GSDeviceOGL : : StretchRect ( GSTexture * st , const GSVector4 & sr , GSTexture * dt , const GSVector4 & dr , GLuint ps , GSBlendStateOGL * bs , bool linear )
2011-11-16 22:17:37 +00:00
{
2011-12-07 22:05:46 +00:00
2011-11-16 22:17:37 +00:00
if ( ! st | | ! dt )
{
ASSERT ( 0 ) ;
return ;
}
2011-12-10 19:19:44 +00:00
// ************************************
// Init
// ************************************
2011-11-16 22:17:37 +00:00
BeginScene ( ) ;
GSVector2i ds = dt - > GetSize ( ) ;
2013-08-10 19:43:59 +00:00
// WARNING: setup of the program must be done first. So you can setup
// 1/ subroutine uniform
// 2/ bindless texture uniform
// 3/ others uniform?
m_shader - > VS ( m_convert . vs ) ;
m_shader - > GS ( 0 ) ;
m_shader - > PS ( ps ) ;
2011-12-10 19:19:44 +00:00
// ************************************
2011-11-16 22:17:37 +00:00
// om
2011-12-10 19:19:44 +00:00
// ************************************
2011-11-16 22:17:37 +00:00
OMSetDepthStencilState ( m_convert . dss , 0 ) ;
OMSetBlendState ( bs , 0 ) ;
OMSetRenderTargets ( dt , NULL ) ;
2011-12-10 19:19:44 +00:00
// ************************************
2011-11-16 22:17:37 +00:00
// ia
2011-12-10 19:19:44 +00:00
// ************************************
2011-11-16 22:17:37 +00:00
2011-12-11 19:09:08 +00:00
2013-06-11 11:14:26 +00:00
// Original code from DX
2011-11-16 22:17:37 +00:00
float left = dr . x * 2 / ds . x - 1.0f ;
float right = dr . z * 2 / ds . x - 1.0f ;
2013-06-11 11:14:26 +00:00
#if 0
float top = 1.0f - dr . y * 2 / ds . y ;
2011-11-16 22:17:37 +00:00
float bottom = 1.0f - dr . w * 2 / ds . y ;
2013-06-11 11:14:26 +00:00
# else
// Opengl get some issues with the coordinate
// I flip top/bottom to fix scaling of the internal resolution
float top = - 1.0f + dr . y * 2 / ds . y ;
float bottom = - 1.0f + dr . w * 2 / ds . y ;
# endif
2011-11-16 22:17:37 +00:00
2011-12-11 19:09:08 +00:00
// Flip y axis only when we render in the backbuffer
// By default everything is render in the wrong order (ie dx).
// 1/ consistency between several pass rendering (interlace)
// 2/ in case some GSdx code expect thing in dx order.
// Only flipping the backbuffer is transparent (I hope)...
GSVector4 flip_sr = sr ;
2011-12-21 23:09:36 +00:00
if ( static_cast < GSTextureOGL * > ( dt ) - > IsBackbuffer ( ) ) {
2013-06-11 11:14:26 +00:00
flip_sr . y = sr . w ;
flip_sr . w = sr . y ;
2011-12-11 19:09:08 +00:00
}
2014-10-01 19:46:20 +00:00
GSVertexPT1 vertices [ ] =
2011-11-16 22:17:37 +00:00
{
2014-10-01 19:46:20 +00:00
{ GSVector4 ( left , top , 0.0f , 0.0f ) , GSVector2 ( flip_sr . x , flip_sr . y ) } ,
{ GSVector4 ( right , top , 0.0f , 0.0f ) , GSVector2 ( flip_sr . z , flip_sr . y ) } ,
{ GSVector4 ( left , bottom , 0.0f , 0.0f ) , GSVector2 ( flip_sr . x , flip_sr . w ) } ,
{ GSVector4 ( right , bottom , 0.0f , 0.0f ) , GSVector2 ( flip_sr . z , flip_sr . w ) } ,
2011-11-16 22:17:37 +00:00
} ;
2011-12-15 18:27:58 +00:00
IASetVertexBuffer ( vertices , 4 ) ;
IASetPrimitiveTopology ( GL_TRIANGLE_STRIP ) ;
2011-11-16 22:17:37 +00:00
2011-12-10 19:19:44 +00:00
// ************************************
2013-08-10 19:43:59 +00:00
// Texture
2011-12-10 19:19:44 +00:00
// ************************************
2011-11-16 22:17:37 +00:00
2013-08-17 08:57:52 +00:00
if ( GLLoader : : found_GL_ARB_bindless_texture ) {
GLuint64 handle [ 2 ] = { static_cast < GSTextureOGL * > ( st ) - > GetHandle ( linear ? m_convert . ln : m_convert . pt ) , 0 } ;
m_shader - > PS_ressources ( handle ) ;
} else {
PSSetShaderResource ( static_cast < GSTextureOGL * > ( st ) - > GetID ( ) ) ;
PSSetSamplerState ( linear ? m_convert . ln : m_convert . pt ) ;
}
2011-11-16 22:17:37 +00:00
2011-12-10 19:19:44 +00:00
// ************************************
// Draw
// ************************************
2011-12-15 18:27:58 +00:00
DrawPrimitive ( ) ;
2011-11-16 22:17:37 +00:00
2011-12-10 19:19:44 +00:00
// ************************************
// End
// ************************************
2011-11-16 22:17:37 +00:00
EndScene ( ) ;
}
void GSDeviceOGL : : DoMerge ( GSTexture * st [ 2 ] , GSVector4 * sr , GSTexture * dt , GSVector4 * dr , bool slbg , bool mmod , const GSVector4 & c )
{
ClearRenderTarget ( dt , c ) ;
if ( st [ 1 ] & & ! slbg )
{
2012-01-08 21:59:42 +00:00
StretchRect ( st [ 1 ] , sr [ 1 ] , dt , dr [ 1 ] , m_merge_obj . ps [ 0 ] ) ;
2011-11-16 22:17:37 +00:00
}
if ( st [ 0 ] )
{
2012-01-08 21:59:42 +00:00
m_merge_obj . cb - > upload ( & c . v ) ;
2011-12-11 19:09:08 +00:00
2012-01-08 21:59:42 +00:00
StretchRect ( st [ 0 ] , sr [ 0 ] , dt , dr [ 0 ] , m_merge_obj . ps [ mmod ? 1 : 0 ] , m_merge_obj . bs ) ;
2011-11-16 22:17:37 +00:00
}
}
void GSDeviceOGL : : DoInterlace ( GSTexture * st , GSTexture * dt , int shader , bool linear , float yoffset )
{
GSVector4 s = GSVector4 ( dt - > GetSize ( ) ) ;
GSVector4 sr ( 0 , 0 , 1 , 1 ) ;
GSVector4 dr ( 0.0f , yoffset , s . x , s . y + yoffset ) ;
InterlaceConstantBuffer cb ;
cb . ZrH = GSVector2 ( 0 , 1.0f / s . y ) ;
cb . hH = s . y / 2 ;
2011-12-19 21:03:23 +00:00
m_interlace . cb - > upload ( & cb ) ;
2011-11-16 22:17:37 +00:00
2011-12-11 19:11:01 +00:00
StretchRect ( st , sr , dt , dr , m_interlace . ps [ shader ] , linear ) ;
2011-11-16 22:17:37 +00:00
}
2013-06-14 21:22:44 +00:00
void GSDeviceOGL : : DoFXAA ( GSTexture * st , GSTexture * dt )
{
2014-11-09 14:27:24 +00:00
// Lazy compile
if ( ! m_fxaa . ps ) {
std : : string fxaa_macro = " #define FXAA_GLSL_130 1 \n " ;
2014-11-09 16:23:17 +00:00
if ( GLLoader : : found_GL_ARB_gpu_shader5 ) { // GL4.0 extension
// Hardcoded in the new shader
//fxaa_macro += "#define FXAA_GATHER4_ALPHA 1\n";
2014-11-09 14:27:24 +00:00
fxaa_macro + = " #extension GL_ARB_gpu_shader5 : enable \n " ;
2014-11-09 16:23:17 +00:00
} else {
fprintf ( stderr , " FXAA requires the GL_ARB_gpu_shader5 extension. Please either disable FXAA or upgrade your GPU/driver. \n " ) ;
return ;
2014-11-09 14:27:24 +00:00
}
2014-11-09 16:23:17 +00:00
m_fxaa . ps = m_shader - > Compile ( " fxaa.fx " , " ps_main " , GL_FRAGMENT_SHADER , fxaa_fx , fxaa_macro ) ;
2014-11-09 14:27:24 +00:00
}
2013-06-14 21:22:44 +00:00
GSVector2i s = dt - > GetSize ( ) ;
GSVector4 sr ( 0 , 0 , 1 , 1 ) ;
GSVector4 dr ( 0 , 0 , s . x , s . y ) ;
StretchRect ( st , sr , dt , dr , m_fxaa . ps , true ) ;
}
2014-11-09 14:27:24 +00:00
void GSDeviceOGL : : DoExternalFX ( GSTexture * st , GSTexture * dt )
{
// Lazy compile
if ( ! m_shaderfx . ps ) {
2014-11-09 15:39:49 +00:00
std : : ifstream fconfig ( theApp . GetConfig ( " shaderfx_conf " , " dummy.ini " ) ) ;
2014-11-09 14:27:24 +00:00
std : : stringstream config ;
if ( fconfig . good ( ) )
config < < fconfig . rdbuf ( ) ;
2014-11-09 15:39:49 +00:00
std : : ifstream fshader ( theApp . GetConfig ( " shaderfx_glsl " , " dummy.glsl " ) ) ;
2014-11-09 14:27:24 +00:00
std : : stringstream shader ;
if ( ! fshader . good ( ) )
return ;
shader < < fshader . rdbuf ( ) ;
m_shaderfx . cb = new GSUniformBufferOGL ( g_fx_cb_index , sizeof ( ExternalFXConstantBuffer ) ) ;
m_shaderfx . ps = m_shader - > Compile ( " Extra " , " ps_main " , GL_FRAGMENT_SHADER , shader . str ( ) . c_str ( ) , config . str ( ) ) ;
}
GSVector2i s = dt - > GetSize ( ) ;
GSVector4 sr ( 0 , 0 , 1 , 1 ) ;
GSVector4 dr ( 0 , 0 , s . x , s . y ) ;
ExternalFXConstantBuffer cb ;
cb . xyFrame = GSVector2 ( s . x , s . y ) ;
cb . rcpFrame = GSVector4 ( 1.0f / s . x , 1.0f / s . y , 0.0f , 0.0f ) ;
cb . rcpFrameOpt = GSVector4 : : zero ( ) ;
m_shaderfx . cb - > upload ( & cb ) ;
StretchRect ( st , sr , dt , dr , m_shaderfx . ps , true ) ;
}
2012-04-26 21:42:16 +00:00
void GSDeviceOGL : : DoShadeBoost ( GSTexture * st , GSTexture * dt )
{
GSVector2i s = dt - > GetSize ( ) ;
GSVector4 sr ( 0 , 0 , 1 , 1 ) ;
GSVector4 dr ( 0 , 0 , s . x , s . y ) ;
ShadeBoostConstantBuffer cb ;
cb . rcpFrame = GSVector4 ( 1.0f / s . x , 1.0f / s . y , 0.0f , 0.0f ) ;
cb . rcpFrameOpt = GSVector4 : : zero ( ) ;
m_shadeboost . cb - > upload ( & cb ) ;
2013-06-16 07:05:57 +00:00
StretchRect ( st , sr , dt , dr , m_shadeboost . ps , true ) ;
2012-04-26 21:42:16 +00:00
}
2014-10-01 19:46:20 +00:00
void GSDeviceOGL : : SetupDATE ( GSTexture * rt , GSTexture * ds , const GSVertexPT1 * vertices , bool datm )
2011-12-19 21:03:23 +00:00
{
2013-06-14 11:34:44 +00:00
# ifdef ENABLE_OGL_STENCIL_DEBUG
2011-12-19 21:03:23 +00:00
const GSVector2i & size = rt - > GetSize ( ) ;
2013-07-19 19:25:50 +00:00
GSTexture * t = CreateRenderTarget ( size . x , size . y , false ) ;
2013-06-14 11:34:44 +00:00
# else
GSTexture * t = NULL ;
# endif
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
BeginScene ( ) ;
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
ClearStencil ( ds , 0 ) ;
2011-12-19 21:03:23 +00:00
2013-08-10 19:43:59 +00:00
// WARNING: setup of the program must be done first. So you can setup
// 1/ subroutine uniform
// 2/ bindless texture uniform
// 3/ others uniform?
m_shader - > VS ( m_convert . vs ) ;
m_shader - > GS ( 0 ) ;
m_shader - > PS ( m_convert . ps [ datm ? 2 : 3 ] ) ;
2013-06-14 11:34:44 +00:00
// om
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
OMSetDepthStencilState ( m_date . dss , 1 ) ;
OMSetBlendState ( m_date . bs , 0 ) ;
OMSetRenderTargets ( t , ds ) ;
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
// ia
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
IASetVertexBuffer ( vertices , 4 ) ;
IASetPrimitiveTopology ( GL_TRIANGLE_STRIP ) ;
2011-12-19 21:03:23 +00:00
2013-08-10 19:43:59 +00:00
// Texture
2011-12-19 21:03:23 +00:00
2013-08-17 08:57:52 +00:00
if ( GLLoader : : found_GL_ARB_bindless_texture ) {
GLuint64 handle [ 2 ] = { static_cast < GSTextureOGL * > ( rt ) - > GetHandle ( m_convert . pt ) , 0 } ;
m_shader - > PS_ressources ( handle ) ;
} else {
PSSetShaderResource ( static_cast < GSTextureOGL * > ( rt ) - > GetID ( ) ) ;
PSSetSamplerState ( m_convert . pt ) ;
}
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
//
2011-12-19 21:03:23 +00:00
2014-09-30 20:12:56 +00:00
# ifdef ENABLE_OGL_STENCIL_DEBUG
2013-06-14 11:34:44 +00:00
DrawPrimitive ( ) ;
2014-09-30 20:12:56 +00:00
# else
// normally ok without it if GL_ARB_framebuffer_no_attachments is supported (minus driver bug)
OMSetWriteBuffer ( GL_NONE ) ;
DrawPrimitive ( ) ;
OMSetWriteBuffer ( ) ;
# endif
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
EndScene ( ) ;
2011-12-19 21:03:23 +00:00
2013-06-14 11:34:44 +00:00
# ifdef ENABLE_OGL_STENCIL_DEBUG
2013-07-19 19:25:50 +00:00
// FIXME invalidate data
2013-06-14 11:34:44 +00:00
Recycle ( t ) ;
# endif
2011-11-16 22:17:37 +00:00
}
2011-12-15 18:27:58 +00:00
void GSDeviceOGL : : EndScene ( )
2011-12-10 19:19:44 +00:00
{
2014-10-02 07:33:41 +00:00
m_va - > EndScene ( ) ;
2011-12-10 19:19:44 +00:00
}
2011-12-15 18:27:58 +00:00
void GSDeviceOGL : : IASetVertexBuffer ( const void * vertices , size_t count )
2011-11-16 22:17:37 +00:00
{
2014-10-02 07:33:41 +00:00
m_va - > UploadVB ( vertices , count ) ;
2012-01-15 17:25:49 +00:00
}
void GSDeviceOGL : : IASetIndexBuffer ( const void * index , size_t count )
{
2014-10-02 07:33:41 +00:00
m_va - > UploadIB ( index , count ) ;
2011-11-16 22:17:37 +00:00
}
void GSDeviceOGL : : IASetPrimitiveTopology ( GLenum topology )
{
2014-10-02 07:33:41 +00:00
m_va - > SetTopology ( topology ) ;
2011-11-16 22:17:37 +00:00
}
2013-08-10 19:43:59 +00:00
void GSDeviceOGL : : PSSetShaderResource ( GLuint sr )
2011-11-16 22:17:37 +00:00
{
2013-08-10 19:43:59 +00:00
if ( GLState : : tex_unit [ 0 ] ! = sr ) {
GLState : : tex_unit [ 0 ] = sr ;
2013-08-02 16:38:12 +00:00
2014-09-28 10:18:07 +00:00
gl_ActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , sr ) ;
2013-08-02 16:38:12 +00:00
2014-09-28 10:18:07 +00:00
// Get back to the expected active texture unit
gl_ActiveTexture ( GL_TEXTURE0 + 3 ) ;
2013-08-02 16:38:12 +00:00
}
}
2013-08-05 20:25:25 +00:00
void GSDeviceOGL : : PSSetShaderResources ( GLuint tex [ 2 ] )
2013-08-02 16:38:12 +00:00
{
2013-08-05 20:25:25 +00:00
if ( GLState : : tex_unit [ 0 ] ! = tex [ 0 ] | | GLState : : tex_unit [ 1 ] ! = tex [ 1 ] ) {
2013-08-10 19:43:59 +00:00
GLState : : tex_unit [ 0 ] = tex [ 0 ] ;
GLState : : tex_unit [ 1 ] = tex [ 1 ] ;
2014-09-28 10:18:07 +00:00
gl_ActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , tex [ 0 ] ) ;
2013-08-10 19:43:59 +00:00
2014-09-28 10:18:07 +00:00
gl_ActiveTexture ( GL_TEXTURE0 + 1 ) ;
glBindTexture ( GL_TEXTURE_2D , tex [ 1 ] ) ;
2013-08-10 19:43:59 +00:00
2014-09-28 10:18:07 +00:00
// Get back to the expected active texture unit
gl_ActiveTexture ( GL_TEXTURE0 + 3 ) ;
2013-08-02 16:38:12 +00:00
}
2011-11-16 22:17:37 +00:00
}
2013-08-02 16:38:12 +00:00
void GSDeviceOGL : : PSSetSamplerState ( GLuint ss )
2011-11-16 22:17:37 +00:00
{
2013-08-05 20:25:25 +00:00
if ( GLState : : ps_ss ! = ss ) {
GLState : : ps_ss = ss ;
2013-08-02 16:38:12 +00:00
gl_BindSampler ( 0 , ss ) ;
2011-11-16 22:17:37 +00:00
}
}
2013-08-05 20:25:25 +00:00
void GSDeviceOGL : : OMAttachRt ( GLuint rt )
2011-11-16 22:17:37 +00:00
{
2013-08-05 20:25:25 +00:00
if ( GLState : : rt ! = rt ) {
GLState : : rt = rt ;
gl_FramebufferTexture2D ( GL_DRAW_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , rt , 0 ) ;
2013-06-01 09:29:57 +00:00
}
2013-07-19 19:25:50 +00:00
}
2013-08-05 20:25:25 +00:00
void GSDeviceOGL : : OMAttachDs ( GLuint ds )
2013-07-19 19:25:50 +00:00
{
2013-08-05 20:25:25 +00:00
if ( GLState : : ds ! = ds ) {
GLState : : ds = ds ;
gl_FramebufferTexture2D ( GL_DRAW_FRAMEBUFFER , GL_DEPTH_STENCIL_ATTACHMENT , GL_TEXTURE_2D , ds , 0 ) ;
2011-11-16 22:17:37 +00:00
}
}
2013-07-19 19:25:50 +00:00
void GSDeviceOGL : : OMSetFBO ( GLuint fbo )
2011-12-08 11:17:59 +00:00
{
2013-08-05 20:25:25 +00:00
if ( GLState : : fbo ! = fbo ) {
GLState : : fbo = fbo ;
2013-05-19 09:19:20 +00:00
gl_BindFramebuffer ( GL_FRAMEBUFFER , fbo ) ;
2011-12-08 11:17:59 +00:00
}
2013-07-19 19:25:50 +00:00
}
2012-03-30 19:02:37 +00:00
2013-07-19 19:25:50 +00:00
void GSDeviceOGL : : OMSetWriteBuffer ( GLenum buffer )
{
2014-09-30 20:12:56 +00:00
GLenum target [ 1 ] = { buffer } ;
gl_DrawBuffers ( 1 , target ) ;
2011-12-08 11:17:59 +00:00
}
2011-11-16 22:17:37 +00:00
void GSDeviceOGL : : OMSetDepthStencilState ( GSDepthStencilOGL * dss , uint8 sref )
{
2013-08-05 20:25:25 +00:00
// State is checkd inside the object but worst case is 11 comparaisons !
2013-06-01 09:29:57 +00:00
if ( m_state . dss ! = dss ) {
2011-11-16 22:17:37 +00:00
m_state . dss = dss ;
2012-01-03 13:11:40 +00:00
dss - > SetupDepth ( ) ;
2013-06-14 11:34:44 +00:00
dss - > SetupStencil ( ) ;
2011-11-16 22:17:37 +00:00
}
}
void GSDeviceOGL : : OMSetBlendState ( GSBlendStateOGL * bs , float bf )
{
2013-08-05 20:25:25 +00:00
// State is checkd inside the object but worst case is 15 comparaisons !
2013-06-01 09:29:57 +00:00
if ( m_state . bs ! = bs | | ( m_state . bf ! = bf & & bs - > HasConstantFactor ( ) ) )
2011-11-16 22:17:37 +00:00
{
m_state . bs = bs ;
m_state . bf = bf ;
2012-01-03 13:11:40 +00:00
bs - > SetupBlend ( bf ) ;
2011-11-16 22:17:37 +00:00
}
}
void GSDeviceOGL : : OMSetRenderTargets ( GSTexture * rt , GSTexture * ds , const GSVector4i * scissor )
{
2013-06-14 11:34:44 +00:00
if ( rt = = NULL | | ! static_cast < GSTextureOGL * > ( rt ) - > IsBackbuffer ( ) ) {
2014-09-07 15:22:23 +00:00
OMSetFBO ( m_fbo ) ;
2013-06-14 11:34:44 +00:00
if ( rt ) {
2013-08-05 20:25:25 +00:00
OMAttachRt ( static_cast < GSTextureOGL * > ( rt ) - > GetID ( ) ) ;
2011-12-29 14:24:26 +00:00
} else {
2014-02-07 19:53:01 +00:00
// Note: NULL rt is only used in DATE so far.
2014-09-07 15:22:23 +00:00
OMAttachRt ( 0 ) ;
2011-12-29 14:24:26 +00:00
}
2013-06-14 11:34:44 +00:00
// Note: it must be done after OMSetFBO
if ( ds )
2013-08-05 20:25:25 +00:00
OMAttachDs ( static_cast < GSTextureOGL * > ( ds ) - > GetID ( ) ) ;
2014-09-07 15:22:23 +00:00
else
OMAttachDs ( 0 ) ;
2013-06-14 11:34:44 +00:00
} else {
// Render in the backbuffer
OMSetFBO ( 0 ) ;
2011-11-21 22:36:03 +00:00
}
2011-11-16 22:17:37 +00:00
2013-06-14 11:34:44 +00:00
GSVector2i size = rt ? rt - > GetSize ( ) : ds - > GetSize ( ) ;
2013-08-05 20:25:25 +00:00
if ( GLState : : viewport ! = size )
2011-11-16 22:17:37 +00:00
{
2013-08-05 20:25:25 +00:00
GLState : : viewport = size ;
2013-06-14 11:34:44 +00:00
glViewport ( 0 , 0 , size . x , size . y ) ;
2011-11-16 22:17:37 +00:00
}
2013-06-14 11:34:44 +00:00
GSVector4i r = scissor ? * scissor : GSVector4i ( size ) . zwxy ( ) ;
2011-11-16 22:17:37 +00:00
2013-08-05 20:25:25 +00:00
if ( ! GLState : : scissor . eq ( r ) )
2011-11-16 22:17:37 +00:00
{
2013-08-05 20:25:25 +00:00
GLState : : scissor = r ;
2011-12-07 22:05:46 +00:00
glScissor ( r . x , r . y , r . width ( ) , r . height ( ) ) ;
2011-11-16 22:17:37 +00:00
}
2011-11-21 22:36:03 +00:00
}
2011-11-26 11:46:51 +00:00
void GSDeviceOGL : : CheckDebugLog ( )
{
2013-07-12 21:12:34 +00:00
# ifndef ENABLE_GLES
2013-06-09 16:41:58 +00:00
unsigned int count = 16 ; // max. num. of messages that will be read from the log
2011-11-26 11:46:51 +00:00
int bufsize = 2048 ;
2013-06-09 16:41:58 +00:00
unsigned int sources [ 16 ] = { } ;
unsigned int types [ 16 ] = { } ;
unsigned int ids [ 16 ] = { } ;
unsigned int severities [ 16 ] = { } ;
int lengths [ 16 ] = { } ;
2011-11-26 11:46:51 +00:00
char * messageLog = new char [ bufsize ] ;
2013-05-19 09:19:20 +00:00
unsigned int retVal = gl_GetDebugMessageLogARB ( count , bufsize , sources , types , ids , severities , lengths , messageLog ) ;
2011-11-26 11:46:51 +00:00
if ( retVal > 0 )
{
unsigned int pos = 0 ;
for ( unsigned int i = 0 ; i < retVal ; i + + )
{
2014-09-27 16:57:17 +00:00
DebugOutputToFile ( sources [ i ] , types [ i ] , ids [ i ] , severities [ i ] , lengths [ i ] , & messageLog [ pos ] , NULL ) ;
2011-11-26 11:46:51 +00:00
pos + = lengths [ i ] ;
}
}
2013-06-30 11:18:46 +00:00
delete [ ] messageLog ;
2013-07-12 21:12:34 +00:00
# endif
2011-11-26 11:46:51 +00:00
}
2014-09-27 16:57:17 +00:00
// Note: used as a callback of DebugMessageCallback. Don't change the signature
void GSDeviceOGL : : DebugOutputToFile ( GLenum gl_source , GLenum gl_type , GLuint id , GLenum gl_severity , GLsizei gl_length , const GLchar * gl_message , const void * userParam )
2011-11-26 11:46:51 +00:00
{
2013-07-13 11:39:45 +00:00
# ifndef ENABLE_GLES
2014-09-27 16:57:17 +00:00
std : : string message ( gl_message , gl_length ) ;
std : : string type , severity , source ;
2012-02-11 10:22:02 +00:00
static int sev_counter = 0 ;
2014-09-27 16:57:17 +00:00
switch ( gl_type ) {
case GL_DEBUG_TYPE_ERROR_ARB : type = " Error " ; break ;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB : type = " Deprecated bhv " ; break ;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB : type = " Undefined bhv " ; break ;
case GL_DEBUG_TYPE_PORTABILITY_ARB : type = " Portability " ; break ;
case GL_DEBUG_TYPE_PERFORMANCE_ARB : type = " Perf " ; break ;
case GL_DEBUG_TYPE_OTHER_ARB : type = " Others " ; break ;
default : type = " TTT " ; break ;
}
switch ( gl_severity ) {
case GL_DEBUG_SEVERITY_HIGH_ARB : severity = " High " ; sev_counter + + ; break ;
case GL_DEBUG_SEVERITY_MEDIUM_ARB : severity = " Mid " ; break ;
case GL_DEBUG_SEVERITY_LOW_ARB : severity = " Low " ; break ;
default : severity = " Info " ; break ;
}
switch ( gl_source ) {
case GL_DEBUG_SOURCE_API_ARB : source = " API " ; break ;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB : source = " WINDOW " ; break ;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB : source = " COMPILER " ; break ;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB : source = " 3rdparty " ; break ;
case GL_DEBUG_SOURCE_APPLICATION_ARB : source = " Application " ; break ;
case GL_DEBUG_SOURCE_OTHER_ARB : source = " Others " ; break ;
default : source = " ??? " ; break ;
2012-02-11 10:22:02 +00:00
}
2011-12-08 11:17:59 +00:00
2011-12-10 11:56:34 +00:00
# ifdef LOUD_DEBUGGING
2014-09-27 16:57:17 +00:00
fprintf ( stderr , " Type:%s \t ID:%d \t Severity:%s \t Message:%s \n " , type . c_str ( ) , g_draw_count , severity . c_str ( ) , message . c_str ( ) ) ;
2011-12-10 11:56:34 +00:00
# endif
2011-12-08 11:17:59 +00:00
FILE * f = fopen ( " Debug.txt " , " a " ) ;
2011-11-26 11:46:51 +00:00
if ( f )
{
2014-09-27 16:57:17 +00:00
fprintf ( f , " Type:%s \t ID:%d \t Severity:%s \t Message:%s \n " , type . c_str ( ) , g_draw_count , severity . c_str ( ) , message . c_str ( ) ) ;
2011-11-26 11:46:51 +00:00
fclose ( f ) ;
}
2014-09-27 16:57:17 +00:00
ASSERT ( sev_counter < 5 ) ;
2013-07-13 11:39:45 +00:00
# endif
2011-11-26 11:46:51 +00:00
}
2011-12-19 21:03:23 +00:00
// (A - B) * C + D
// A: Cs/Cd/0
// B: Cs/Cd/0
// C: As/Ad/FIX
// D: Cs/Cd/0
// bogus: 0100, 0110, 0120, 0200, 0210, 0220, 1001, 1011, 1021
// tricky: 1201, 1211, 1221
// Source.rgb = float3(1, 1, 1);
// 1201 Cd*(1 + As) => Source * Dest color + Dest * Source alpha
// 1211 Cd*(1 + Ad) => Source * Dest color + Dest * Dest alpha
// 1221 Cd*(1 + F) => Source * Dest color + Dest * Factor
// Copy Dx blend table and convert it to ogl
# define D3DBLENDOP_ADD GL_FUNC_ADD
# define D3DBLENDOP_SUBTRACT GL_FUNC_SUBTRACT
# define D3DBLENDOP_REVSUBTRACT GL_FUNC_REVERSE_SUBTRACT
# define D3DBLEND_ONE GL_ONE
# define D3DBLEND_ZERO GL_ZERO
# define D3DBLEND_INVDESTALPHA GL_ONE_MINUS_DST_ALPHA
# define D3DBLEND_DESTALPHA GL_DST_ALPHA
# define D3DBLEND_DESTCOLOR GL_DST_COLOR
# define D3DBLEND_BLENDFACTOR GL_CONSTANT_COLOR
# define D3DBLEND_INVBLENDFACTOR GL_ONE_MINUS_CONSTANT_COLOR
2012-01-03 16:12:34 +00:00
2013-07-13 11:39:45 +00:00
# ifdef ENABLE_GLES
# define D3DBLEND_SRCALPHA GL_SRC_ALPHA
# define D3DBLEND_INVSRCALPHA GL_ONE_MINUS_SRC_ALPHA
# else
2012-05-11 19:39:32 +00:00
# define D3DBLEND_SRCALPHA GL_SRC1_ALPHA
# define D3DBLEND_INVSRCALPHA GL_ONE_MINUS_SRC1_ALPHA
2013-07-13 11:39:45 +00:00
# endif
2014-09-07 15:22:23 +00:00
2011-12-19 21:03:23 +00:00
const GSDeviceOGL : : D3D9Blend GSDeviceOGL : : m_blendMapD3D9 [ 3 * 3 * 3 * 3 ] =
{
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 0000: (Cs - Cs)*As + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 0001: (Cs - Cs)*As + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 0002: (Cs - Cs)*As + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 0010: (Cs - Cs)*Ad + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 0011: (Cs - Cs)*Ad + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 0012: (Cs - Cs)*Ad + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 0020: (Cs - Cs)*F + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 0021: (Cs - Cs)*F + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 0022: (Cs - Cs)*F + 0 ==> 0
{ 1 , D3DBLENDOP_SUBTRACT , D3DBLEND_SRCALPHA , D3DBLEND_SRCALPHA } , //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
{ 0 , D3DBLENDOP_ADD , D3DBLEND_SRCALPHA , D3DBLEND_INVSRCALPHA } , // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_SRCALPHA , D3DBLEND_SRCALPHA } , // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
{ 1 , D3DBLENDOP_SUBTRACT , D3DBLEND_DESTALPHA , D3DBLEND_DESTALPHA } , //*0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
{ 0 , D3DBLENDOP_ADD , D3DBLEND_DESTALPHA , D3DBLEND_INVDESTALPHA } , // 0111: (Cs - Cd)*Ad + Cd ==> Cs*Ad + Cd*(1 - Ad)
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_DESTALPHA , D3DBLEND_DESTALPHA } , // 0112: (Cs - Cd)*Ad + 0 ==> Cs*Ad - Cd*Ad
{ 1 , D3DBLENDOP_SUBTRACT , D3DBLEND_BLENDFACTOR , D3DBLEND_BLENDFACTOR } , //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
{ 0 , D3DBLENDOP_ADD , D3DBLEND_BLENDFACTOR , D3DBLEND_INVBLENDFACTOR } , // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_BLENDFACTOR , D3DBLEND_BLENDFACTOR } , // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
{ 1 , D3DBLENDOP_ADD , D3DBLEND_SRCALPHA , D3DBLEND_ZERO } , //*0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
{ 0 , D3DBLENDOP_ADD , D3DBLEND_SRCALPHA , D3DBLEND_ONE } , // 0201: (Cs - 0)*As + Cd ==> Cs*As + Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_SRCALPHA , D3DBLEND_ZERO } , // 0202: (Cs - 0)*As + 0 ==> Cs*As
{ 1 , D3DBLENDOP_ADD , D3DBLEND_DESTALPHA , D3DBLEND_ZERO } , //*0210: (Cs - 0)*Ad + Cs ==> Cs*(Ad + 1)
{ 0 , D3DBLENDOP_ADD , D3DBLEND_DESTALPHA , D3DBLEND_ONE } , // 0211: (Cs - 0)*Ad + Cd ==> Cs*Ad + Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_DESTALPHA , D3DBLEND_ZERO } , // 0212: (Cs - 0)*Ad + 0 ==> Cs*Ad
{ 1 , D3DBLENDOP_ADD , D3DBLEND_BLENDFACTOR , D3DBLEND_ZERO } , //*0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
{ 0 , D3DBLENDOP_ADD , D3DBLEND_BLENDFACTOR , D3DBLEND_ONE } , // 0221: (Cs - 0)*F + Cd ==> Cs*F + Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_BLENDFACTOR , D3DBLEND_ZERO } , // 0222: (Cs - 0)*F + 0 ==> Cs*F
{ 0 , D3DBLENDOP_ADD , D3DBLEND_INVSRCALPHA , D3DBLEND_SRCALPHA } , // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
{ 1 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_SRCALPHA , D3DBLEND_SRCALPHA } , //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_SRCALPHA , D3DBLEND_SRCALPHA } , // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
{ 0 , D3DBLENDOP_ADD , D3DBLEND_INVDESTALPHA , D3DBLEND_DESTALPHA } , // 1010: (Cd - Cs)*Ad + Cs ==> Cd*Ad + Cs*(1 - Ad)
{ 1 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_DESTALPHA , D3DBLEND_DESTALPHA } , //*1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_DESTALPHA , D3DBLEND_DESTALPHA } , // 1012: (Cd - Cs)*Ad + 0 ==> Cd*Ad - Cs*Ad
{ 0 , D3DBLENDOP_ADD , D3DBLEND_INVBLENDFACTOR , D3DBLEND_BLENDFACTOR } , // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
{ 1 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_BLENDFACTOR , D3DBLEND_BLENDFACTOR } , //*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_BLENDFACTOR , D3DBLEND_BLENDFACTOR } , // 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 1100: (Cd - Cd)*As + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 1101: (Cd - Cd)*As + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 1102: (Cd - Cd)*As + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 1110: (Cd - Cd)*Ad + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 1111: (Cd - Cd)*Ad + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 1112: (Cd - Cd)*Ad + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 1120: (Cd - Cd)*F + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 1121: (Cd - Cd)*F + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 1122: (Cd - Cd)*F + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_SRCALPHA } , // 1200: (Cd - 0)*As + Cs ==> Cs + Cd*As
{ 2 , D3DBLENDOP_ADD , D3DBLEND_DESTCOLOR , D3DBLEND_SRCALPHA } , //#1201: (Cd - 0)*As + Cd ==> Cd*(1 + As) // ffxii main menu background glow effect
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_SRCALPHA } , // 1202: (Cd - 0)*As + 0 ==> Cd*As
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_DESTALPHA } , // 1210: (Cd - 0)*Ad + Cs ==> Cs + Cd*Ad
{ 2 , D3DBLENDOP_ADD , D3DBLEND_DESTCOLOR , D3DBLEND_DESTALPHA } , //#1211: (Cd - 0)*Ad + Cd ==> Cd*(1 + Ad)
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_DESTALPHA } , // 1212: (Cd - 0)*Ad + 0 ==> Cd*Ad
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_BLENDFACTOR } , // 1220: (Cd - 0)*F + Cs ==> Cs + Cd*F
{ 2 , D3DBLENDOP_ADD , D3DBLEND_DESTCOLOR , D3DBLEND_BLENDFACTOR } , //#1221: (Cd - 0)*F + Cd ==> Cd*(1 + F)
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_BLENDFACTOR } , // 1222: (Cd - 0)*F + 0 ==> Cd*F
{ 0 , D3DBLENDOP_ADD , D3DBLEND_INVSRCALPHA , D3DBLEND_ZERO } , // 2000: (0 - Cs)*As + Cs ==> Cs*(1 - As)
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_SRCALPHA , D3DBLEND_ONE } , // 2001: (0 - Cs)*As + Cd ==> Cd - Cs*As
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_SRCALPHA , D3DBLEND_ZERO } , // 2002: (0 - Cs)*As + 0 ==> 0 - Cs*As
{ 0 , D3DBLENDOP_ADD , D3DBLEND_INVDESTALPHA , D3DBLEND_ZERO } , // 2010: (0 - Cs)*Ad + Cs ==> Cs*(1 - Ad)
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_DESTALPHA , D3DBLEND_ONE } , // 2011: (0 - Cs)*Ad + Cd ==> Cd - Cs*Ad
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_DESTALPHA , D3DBLEND_ZERO } , // 2012: (0 - Cs)*Ad + 0 ==> 0 - Cs*Ad
{ 0 , D3DBLENDOP_ADD , D3DBLEND_INVBLENDFACTOR , D3DBLEND_ZERO } , // 2020: (0 - Cs)*F + Cs ==> Cs*(1 - F)
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_BLENDFACTOR , D3DBLEND_ONE } , // 2021: (0 - Cs)*F + Cd ==> Cd - Cs*F
{ 0 , D3DBLENDOP_REVSUBTRACT , D3DBLEND_BLENDFACTOR , D3DBLEND_ZERO } , // 2022: (0 - Cs)*F + 0 ==> 0 - Cs*F
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_ONE , D3DBLEND_SRCALPHA } , // 2100: (0 - Cd)*As + Cs ==> Cs - Cd*As
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_INVSRCALPHA } , // 2101: (0 - Cd)*As + Cd ==> Cd*(1 - As)
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_ZERO , D3DBLEND_SRCALPHA } , // 2102: (0 - Cd)*As + 0 ==> 0 - Cd*As
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_ONE , D3DBLEND_DESTALPHA } , // 2110: (0 - Cd)*Ad + Cs ==> Cs - Cd*Ad
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_INVDESTALPHA } , // 2111: (0 - Cd)*Ad + Cd ==> Cd*(1 - Ad)
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_ONE , D3DBLEND_DESTALPHA } , // 2112: (0 - Cd)*Ad + 0 ==> 0 - Cd*Ad
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_ONE , D3DBLEND_BLENDFACTOR } , // 2120: (0 - Cd)*F + Cs ==> Cs - Cd*F
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_INVBLENDFACTOR } , // 2121: (0 - Cd)*F + Cd ==> Cd*(1 - F)
{ 0 , D3DBLENDOP_SUBTRACT , D3DBLEND_ONE , D3DBLEND_BLENDFACTOR } , // 2122: (0 - Cd)*F + 0 ==> 0 - Cd*F
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 2200: (0 - 0)*As + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 2201: (0 - 0)*As + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 2202: (0 - 0)*As + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 2210: (0 - 0)*Ad + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 2211: (0 - 0)*Ad + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 2212: (0 - 0)*Ad + 0 ==> 0
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ONE , D3DBLEND_ZERO } , // 2220: (0 - 0)*F + Cs ==> Cs
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ONE } , // 2221: (0 - 0)*F + Cd ==> Cd
{ 0 , D3DBLENDOP_ADD , D3DBLEND_ZERO , D3DBLEND_ZERO } , // 2222: (0 - 0)*F + 0 ==> 0
} ;