2020-12-21 14:03:34 +00:00
# ifdef QB64_MACOSX
# include <sys/sysctl.h>
# endif
2020-01-08 12:06:28 +00:00
// trigger recompilation = 3
2015-10-30 12:18:44 +00:00
2018-06-30 15:16:59 +00:00
int32 displayorder_screen = 1 ;
int32 displayorder_hardware = 2 ;
int32 displayorder_glrender = 3 ;
int32 displayorder_hardware1 = 4 ;
//sub__displayorder( 1 , 2 , 4 , 3 );
//id.specialformat = "[{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}[,{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}[,{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}[,{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}]]]]"
void sub__displayorder ( int32 method1 , int32 method2 , int32 method3 , int32 method4 ) {
2015-02-20 13:15:27 +00:00
//check no value has been used twice
if ( method1 ! = 0 ) if ( method1 = = method2 | | method1 = = method3 | | method1 = = method4 ) { error ( 5 ) ; return ; }
if ( method2 ! = 0 ) if ( method2 = = method1 | | method2 = = method3 | | method2 = = method4 ) { error ( 5 ) ; return ; }
if ( method3 ! = 0 ) if ( method3 = = method1 | | method3 = = method2 | | method3 = = method4 ) { error ( 5 ) ; return ; }
if ( method4 ! = 0 ) if ( method4 = = method1 | | method4 = = method2 | | method4 = = method3 ) { error ( 5 ) ; return ; }
displayorder_screen = 0 ;
displayorder_hardware = 0 ;
displayorder_hardware1 = 0 ;
displayorder_glrender = 0 ;
static int32 i , method ;
2020-12-21 14:03:34 +00:00
for ( i = 1 ; i < = 4 ; i + + ) {
2018-06-30 15:16:59 +00:00
if ( i = = 1 ) method = method1 ;
if ( i = = 2 ) method = method2 ;
if ( i = = 3 ) method = method3 ;
if ( i = = 4 ) method = method4 ;
if ( method = = 1 ) displayorder_screen = i ;
if ( method = = 2 ) displayorder_hardware = i ;
if ( method = = 3 ) displayorder_hardware1 = i ;
if ( method = = 4 ) displayorder_glrender = i ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
}
2015-02-20 13:15:27 +00:00
2018-06-30 15:16:59 +00:00
//int32 gl_render_method=2; //1=behind, 2=ontop[default], 3=only
void sub__glrender ( int32 method ) {
2015-02-20 13:15:27 +00:00
//gl_render_method=method;
if ( method = = 1 ) sub__displayorder ( 4 , 1 , 2 , 3 ) ;
if ( method = = 2 ) sub__displayorder ( 1 , 2 , 4 , 3 ) ;
if ( method = = 3 ) sub__displayorder ( 4 , 0 , 0 , 0 ) ;
2018-06-30 15:16:59 +00:00
}
2015-02-20 13:15:27 +00:00
# ifndef QB64_GUI //begin stubs
2018-06-30 15:16:59 +00:00
# else //end stubs
void GLUT_RESHAPE_FUNC ( int width , int height ) {
resize_event_x = width ; resize_event_y = height ;
resize_event = - 1 ;
display_x_prev = display_x , display_y_prev = display_y ;
display_x = width ; display_y = height ;
resize_pending = 0 ;
os_resize_event = 1 ;
set_view ( VIEW_MODE__UNKNOWN ) ;
//***glutReshapeWindow(...) has no effect if called
// within GLUT_RESHAPE_FUNC***
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
//displaycall is the window of time to update our display
# ifdef DEPENDENCY_GL
extern void SUB__GL ( ) ;
# endif
# define GL_BGR 0x80E0
# define GL_BGRA 0x80E1
/* reference
struct hardware_img_struct {
int32 w ;
int32 h ;
int32 texture_handle ;
int32 dest_context_handle ; //used when rendering other images onto this image
int32 temp ; //if =1, delete immediately after use
}
list * hardware_img_handles = NULL ;
*/
2020-12-21 14:03:34 +00:00
void free_hardware_img ( int32 handle , int32 caller_id ) {
2018-06-30 15:16:59 +00:00
hardware_img_struct * hardware_img ;
hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , handle ) ;
if ( hardware_img = = NULL ) {
alert ( " free_hardware_img: image does not exist " ) ;
}
if ( hardware_img - > dest_context_handle ) {
GLuint context = ( GLuint ) hardware_img - > dest_context_handle ;
glDeleteFramebuffersEXT ( 1 , & context ) ;
}
if ( hardware_img - > depthbuffer_handle ) {
GLuint depthbuffer_handle = ( GLuint ) hardware_img - > depthbuffer_handle ;
glDeleteFramebuffersEXT ( 1 , & depthbuffer_handle ) ;
}
GLuint texture = ( GLuint ) hardware_img - > texture_handle ;
2020-12-21 14:03:34 +00:00
glDeleteTextures ( 1 , & texture ) ;
2018-06-30 15:16:59 +00:00
//test reasset of hardware+img
//hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,handle);
//if (hardware_img==NULL) alert("free_hardware_img: image does not exist");
//if image has not been used, it may still have buffered pixel content
if ( hardware_img - > software_pixel_buffer ! = NULL ) {
free ( hardware_img - > software_pixel_buffer ) ;
}
list_remove ( hardware_img_handles , handle ) ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
/*
int32 new_hardware_frame ( int32 x , int32 y ) {
int32 handle = new_hardware_frame_handle ( ) ;
glBindTexture ( GL_TEXTURE_2D , handle ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , x , y , 0 , GL_BGRA , GL_UNSIGNED_BYTE , NULL ) ;
return handle ;
}
void free_hardware_frame ( int32 handle ) {
GLuint texture = ( GLuint ) handle ;
glDeleteTextures ( 1 , & texture ) ;
}
*/
void prepare_environment_2d ( ) { //called prior to rendering 2D content
//precalculate critical dimensions, offsets & ratios
static int32 can_scale ; //can the screen be scaled on the window
can_scale = 0 ;
static int32 need_square_pixels ; //do we need square_pixels? if not we can stretch the screen
need_square_pixels = 0 ;
environment_2d__screen_smooth = 0 ;
environment_2d__letterbox = 0 ;
if ( full_screen > 0 ) { //in full screen
//reference: ---int32 full_screen_set=-1;//0(windowed),1(stretched/closest),2(1:1)---
can_scale = 1 ;
if ( full_screen = = 2 ) need_square_pixels = 1 ;
//note: 'letter-boxing' is only requred where the size of the window cannot be controlled, and the only place where this is the
// case is full screen mode _SQUAREPIXELS
environment_2d__screen_smooth = fullscreen_smooth ;
} else { //windowed
if ( resize_auto > 0 ) { //1=STRETCH,2=SMOOTH
can_scale = 1 ;
if ( resize_auto = = 2 ) environment_2d__screen_smooth = 1 ;
//note: screen will fix its aspect ratio automatically, so there is no need to enforce squarepixels
2020-12-21 14:03:34 +00:00
}
2018-06-30 15:16:59 +00:00
}
if ( environment_2d__screen_width = = environment__window_width & &
environment_2d__screen_height = = environment__window_height ) {
//screen size matches window
environment_2d__screen_x1 = 0 ;
environment_2d__screen_y1 = 0 ;
environment_2d__screen_x2 = environment_2d__screen_width - 1 ;
environment_2d__screen_y2 = environment_2d__screen_height - 1 ;
environment_2d__screen_x_scale = 1.0f ;
environment_2d__screen_y_scale = 1.0f ;
environment_2d__screen_scaled_width = environment_2d__screen_width ;
environment_2d__screen_scaled_height = environment_2d__screen_height ;
environment_2d__screen_smooth = 0 ; //no smoothing required
} else {
//screen size does not match
//calculate ratios
static float window_ratio ;
static float screen_ratio ;
window_ratio = ( float ) environment__window_width / ( float ) environment__window_height ;
screen_ratio = ( float ) environment_2d__screen_width / ( float ) environment_2d__screen_height ;
if ( can_scale = = 0 ) {
//screen will appear in the top-left of the window with blank space on the bottom & right
environment_2d__screen_x1 = 0 ;
environment_2d__screen_y1 = 0 ;
environment_2d__screen_x2 = environment_2d__screen_width - 1 ;
environment_2d__screen_y2 = environment_2d__screen_height - 1 ;
goto cant_scale ;
}
if ( need_square_pixels = = 0 | | ( window_ratio = = screen_ratio ) ) {
//can stretch, no 'letter-box' required
environment_2d__screen_x1 = 0 ;
environment_2d__screen_y1 = 0 ;
environment_2d__screen_x2 = environment__window_width - 1 ;
environment_2d__screen_y2 = environment__window_height - 1 ;
} else {
//'letter-box' required
//this section needs revision
static float x_scale , y_scale ;
static int32 x1 , y1 , x2 , y2 , z , x_limit , y_limit , x_offset , y_offset ;
//x_scale=(float)environment_2d__screen_width/(float)environment__window_width;
//y_scale=(float)environment_2d__screen_height/(float)environment__window_height;
//x_offset=0; y_offset=0;
x1 = 0 ; y1 = 0 ; x2 = environment__window_width - 1 ; y2 = environment__window_height - 1 ;
//x_limit=x2; y_limit=y2;
if ( window_ratio > screen_ratio ) {
//pad sides
z = ( float ) environment__window_height * screen_ratio ; //new width
x1 = environment__window_width / 2 - z / 2 ;
x2 = x1 + z - 1 ;
environment_2d__letterbox = 1 ; //vertical black stripes required
//x_offset=-x1; x_scale=(float)environment_2d__screen_width/(float)z; x_limit=z-1;
} else {
//pad top/bottom
z = ( float ) environment__window_width / screen_ratio ; //new height
y1 = environment__window_height / 2 - z / 2 ;
y2 = y1 + z - 1 ;
environment_2d__letterbox = 2 ; //horizontal black stripes required
//y_offset=-y1; y_scale=(float)environment_2d__screen_height/(float)z; y_limit=z-1;
}
environment_2d__screen_x1 = x1 ;
environment_2d__screen_y1 = y1 ;
environment_2d__screen_x2 = x2 ;
environment_2d__screen_y2 = y2 ;
}
cant_scale :
environment_2d__screen_scaled_width = environment_2d__screen_x2 - environment_2d__screen_x1 + 1 ;
environment_2d__screen_scaled_height = environment_2d__screen_y2 - environment_2d__screen_y1 + 1 ;
environment_2d__screen_x_scale = ( float ) environment_2d__screen_scaled_width / ( float ) environment_2d__screen_width ;
environment_2d__screen_y_scale = ( float ) environment_2d__screen_scaled_height / ( float ) environment_2d__screen_height ;
2020-12-21 14:03:34 +00:00
}
2018-06-30 15:16:59 +00:00
} //prepare_environment_2d
int32 environment_2d__get_window_x1_coord ( int32 x ) {
return qbr_float_to_long ( ( ( float ) x ) * environment_2d__screen_x_scale ) + environment_2d__screen_x1 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
int32 environment_2d__get_window_y1_coord ( int32 y ) {
return qbr_float_to_long ( ( float ) y * environment_2d__screen_y_scale ) + environment_2d__screen_y1 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
int32 environment_2d__get_window_x2_coord ( int32 x ) {
return qbr_float_to_long ( ( ( float ) x + 1.0f ) * environment_2d__screen_x_scale - 1.0f ) + environment_2d__screen_x1 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
int32 environment_2d__get_window_y2_coord ( int32 y ) {
return qbr_float_to_long ( ( ( float ) y + 1.0f ) * environment_2d__screen_y_scale - 1.0f ) + environment_2d__screen_y1 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
struct environment_2d__window_rect_struct {
int32 x1 ;
int32 y1 ;
int32 x2 ;
int32 y2 ;
} ;
//this functions returns a constant rect dimensions to stop warping of image
environment_2d__window_rect_struct tmp_rect ;
environment_2d__window_rect_struct * environment_2d__screen_to_window_rect ( int32 x1 , int32 y1 , int32 x2 , int32 y2 ) {
tmp_rect . x1 = qbr_float_to_long ( ( ( float ) x1 ) * environment_2d__screen_x_scale ) + environment_2d__screen_x1 ;
tmp_rect . y1 = qbr_float_to_long ( ( ( float ) y1 ) * environment_2d__screen_y_scale ) + environment_2d__screen_y1 ;
static int32 w , h ;
w = abs ( x2 - x1 ) + 1 ; h = abs ( y2 - y1 ) + 1 ;
//force round upwards to correct gaps when tiling
w = ( ( float ) w ) * environment_2d__screen_x_scale + 0.99f ;
h = ( ( float ) h ) * environment_2d__screen_y_scale + 0.99f ;
tmp_rect . x2 = w - 1 + tmp_rect . x1 ;
tmp_rect . y2 = h - 1 + tmp_rect . y1 ;
//(code which doesn't support tiling)
//tmp_rect.x2=qbr_float_to_long(((float)w)*environment_2d__screen_x_scale-1.0f)+tmp_rect.x1;
//tmp_rect.y2=qbr_float_to_long(((float)h)*environment_2d__screen_y_scale-1.0f)+tmp_rect.y1;
return & tmp_rect ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
float * hardware_buffer_vertices = ( float * ) malloc ( sizeof ( float ) * 1 ) ;
int32 hardware_buffer_vertices_max = 1 ;
int32 hardware_buffer_vertices_count = 0 ;
float * hardware_buffer_texcoords = ( float * ) malloc ( sizeof ( float ) * 1 ) ;
int32 hardware_buffer_texcoords_max = 1 ;
int32 hardware_buffer_texcoords_count = 0 ;
void hardware_buffer_flush ( ) {
if ( hardware_buffer_vertices_count ) {
//ref: http://stackoverflow.com/questions/5009014/draw-square-with-opengl-es-for-ios
if ( hardware_buffer_vertices_count = = hardware_buffer_texcoords_count ) {
glVertexPointer ( 2 , GL_FLOAT , 2 * sizeof ( GL_FLOAT ) , hardware_buffer_vertices ) ; //http://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml
glTexCoordPointer ( 2 , GL_FLOAT , 2 * sizeof ( GL_FLOAT ) , hardware_buffer_texcoords ) ; //http://www.opengl.org/sdk/docs/man2/xhtml/glTexCoordPointer.xml
glDrawArrays ( GL_TRIANGLES , 0 , hardware_buffer_vertices_count / 2 ) ; //start index, number of indexes
} else {
glVertexPointer ( 3 , GL_FLOAT , 3 * sizeof ( GL_FLOAT ) , hardware_buffer_vertices ) ; //http://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml
glTexCoordPointer ( 2 , GL_FLOAT , 2 * sizeof ( GL_FLOAT ) , hardware_buffer_texcoords ) ; //http://www.opengl.org/sdk/docs/man2/xhtml/glTexCoordPointer.xml
glDrawArrays ( GL_TRIANGLES , 0 , hardware_buffer_vertices_count / 3 ) ; //start index, number of indexes
}
hardware_buffer_vertices_count = 0 ;
hardware_buffer_texcoords_count = 0 ;
}
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_smooth ( int32 new_mode_shrunk , int32 new_mode_stretched ) {
static int32 current_mode_shrunk ;
current_mode_shrunk = render_state . source - > smooth_shrunk ;
static int32 current_mode_stretched ;
current_mode_stretched = render_state . source - > smooth_stretched ;
if ( new_mode_shrunk = = current_mode_shrunk & & new_mode_stretched = = current_mode_stretched ) return ;
hardware_buffer_flush ( ) ;
if ( new_mode_shrunk = = SMOOTH_MODE__DONT_SMOOTH ) {
if ( render_state . source - > PO2_fix = = PO2_FIX__MIPMAPPED ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2020-12-21 14:03:34 +00:00
} else {
2018-06-30 15:16:59 +00:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ; //Use _MAPTRIANGLE's _SMOOTHSHRUNK to apply linear filtering here
}
}
if ( new_mode_shrunk = = SMOOTH_MODE__SMOOTH ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
}
if ( new_mode_stretched = = SMOOTH_MODE__DONT_SMOOTH ) {
if ( render_state . source - > PO2_fix = = PO2_FIX__MIPMAPPED ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
} else {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
}
}
if ( new_mode_stretched = = SMOOTH_MODE__SMOOTH ) {
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
}
render_state . source - > smooth_shrunk = new_mode_shrunk ;
render_state . source - > smooth_stretched = new_mode_stretched ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_texture_wrap ( int32 new_mode ) {
static int32 current_mode ;
current_mode = render_state . source - > texture_wrap ;
if ( new_mode = = current_mode ) return ;
hardware_buffer_flush ( ) ;
if ( new_mode = = TEXTURE_WRAP_MODE__DONT_WRAP ) {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
}
if ( new_mode = = TEXTURE_WRAP_MODE__WRAP ) {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
}
render_state . source - > texture_wrap = new_mode ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_alpha ( int32 new_mode ) {
static int32 current_mode ;
current_mode = render_state . use_alpha ;
if ( new_mode = = current_mode ) return ;
hardware_buffer_flush ( ) ;
if ( new_mode = = ALPHA_MODE__DONT_BLEND ) {
glDisable ( GL_BLEND ) ;
}
if ( new_mode = = ALPHA_MODE__BLEND ) {
glEnable ( GL_BLEND ) ;
if ( framebufferobjects_supported ) {
# ifndef QB64_GLES
//glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendFuncSeparateEXT ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , GL_ONE , GL_ONE ) ;
# else
glBlendFuncSeparateOES ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , GL_ONE , GL_ONE ) ;
# endif
} else {
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
}
}
render_state . use_alpha = new_mode ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_depthbuffer ( int32 new_mode ) {
static int32 current_mode ;
current_mode = render_state . depthbuffer_mode ;
if ( new_mode = = current_mode ) return ;
hardware_buffer_flush ( ) ;
if ( new_mode = = DEPTHBUFFER_MODE__OFF ) {
glDisable ( GL_DEPTH_TEST ) ;
glAlphaFunc ( GL_ALWAYS , 0 ) ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
if ( new_mode = = DEPTHBUFFER_MODE__ON ) {
glEnable ( GL_DEPTH_TEST ) ;
2020-12-21 14:03:34 +00:00
glDepthMask ( GL_TRUE ) ;
2018-06-30 15:16:59 +00:00
glAlphaFunc ( GL_GREATER , 0.001 ) ;
glEnable ( GL_ALPHA_TEST ) ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
if ( new_mode = = DEPTHBUFFER_MODE__LOCKED ) {
glEnable ( GL_DEPTH_TEST ) ;
glDepthMask ( GL_FALSE ) ;
glAlphaFunc ( GL_ALWAYS , 0 ) ;
}
render_state . depthbuffer_mode = new_mode ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_cull_mode ( int32 new_mode ) {
static int32 current_mode ;
current_mode = render_state . cull_mode ;
if ( new_mode = = current_mode ) return ;
hardware_buffer_flush ( ) ;
if ( new_mode = = CULL_MODE__NONE ) {
glDisable ( GL_CULL_FACE ) ;
}
if ( new_mode = = CULL_MODE__CLOCKWISE_ONLY ) {
2020-12-21 14:03:34 +00:00
glFrontFace ( GL_CW ) ;
2018-06-30 15:16:59 +00:00
if ( current_mode ! = CULL_MODE__ANTICLOCKWISE_ONLY ) glEnable ( GL_CULL_FACE ) ;
}
if ( new_mode = = CULL_MODE__ANTICLOCKWISE_ONLY ) {
glFrontFace ( GL_CCW ) ;
if ( current_mode ! = CULL_MODE__CLOCKWISE_ONLY ) glEnable ( GL_CULL_FACE ) ;
}
render_state . cull_mode = new_mode ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_view ( int32 new_mode ) { //set view can only be called after the correct destination is chosen
static int32 current_mode ;
current_mode = render_state . view_mode ;
if ( new_mode = = current_mode ) return ;
hardware_buffer_flush ( ) ;
if ( new_mode = = VIEW_MODE__RESET ) {
glDisable ( GL_TEXTURE_2D ) ;
glDisable ( GL_ALPHA_TEST ) ;
glDisable ( GL_BLEND ) ;
glDisable ( GL_COLOR_MATERIAL ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( GL_TRUE ) ;
glDisable ( GL_LIGHTING ) ;
glFrontFace ( GL_CCW ) ;
glCullFace ( GL_BACK ) ;
glDisable ( GL_CULL_FACE ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glAlphaFunc ( GL_ALWAYS , 0 ) ;
if ( framebufferobjects_supported ) glBindFramebufferEXT ( GL_FRAMEBUFFER , 0 ) ;
2020-12-21 14:03:34 +00:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2018-06-30 15:16:59 +00:00
glClear ( GL_DEPTH_BUFFER_BIT ) ;
glColor4f ( 1.f , 1.f , 1.f , 1.f ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
//invalidate current states
set_alpha ( ALPHA_MODE__UNKNOWN ) ;
set_depthbuffer ( DEPTHBUFFER_MODE__UNKNOWN ) ;
set_cull_mode ( CULL_MODE__UNKNOWN ) ;
set_render_source ( INVALID_HARDWARE_HANDLE ) ;
set_render_dest ( INVALID_HARDWARE_HANDLE ) ;
2020-12-21 14:03:34 +00:00
new_mode = VIEW_MODE__UNKNOWN ; //resets are performed before unknown operations are executed
2018-06-30 15:16:59 +00:00
}
if ( new_mode = = VIEW_MODE__2D ) {
if ( current_mode ! = VIEW_MODE__3D ) {
2020-12-21 14:03:34 +00:00
glColor4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
2018-06-30 15:16:59 +00:00
glDisable ( GL_COLOR_MATERIAL ) ;
glDisable ( GL_LIGHTING ) ;
set_alpha ( ALPHA_MODE__BLEND ) ;
glEnable ( GL_TEXTURE_2D ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glCullFace ( GL_BACK ) ;
}
if ( render_state . dest_handle = = 0 ) {
2020-03-12 02:10:19 +00:00
static int32 dst_w , dst_h ;
static int32 scale_factor = 0 ;
# ifdef QB64_MACOSX
if ( scale_factor = = 0 ) {
2020-12-21 14:03:34 +00:00
// by default scale_factor should be 1, but in macOS Catalina (10.15.*) scale_factor must be setted in 2
// * in cases where the app is executed on system with Retina Display
scale_factor = 1 ; // by default
// lookup for retina/5k output from system_profiler (storing all outpun in stream)
bool b_isRetina , b_is5k ;
FILE * consoleStream = popen ( " system_profiler SPDisplaysDataType " , " r " ) ;
if ( consoleStream ) {
char buffer [ 128 ] ;
while ( ! feof ( consoleStream ) ) {
if ( fgets ( buffer , 128 , consoleStream ) ! = NULL ) {
string szBuffer ( buffer ) ;
if ( ! b_isRetina ) b_isRetina = ( szBuffer . rfind ( " Retina " ) ! = ULONG_MAX ) ;
if ( ! b_is5k ) b_is5k = ( szBuffer . rfind ( " 5K " ) ! = ULONG_MAX ) ;
}
}
}
pclose ( consoleStream ) ;
if ( b_isRetina | | b_is5k ) {
// apply only factor = 2 if macOS is Catalina (11.15.* // kern.osrelease 19.*)
char str [ 256 ] ;
size_t size = sizeof ( str ) ;
int ret = sysctlbyname ( " kern.osrelease " , str , & size , NULL , 0 ) ;
string sz_osrelease ( str ) ;
if ( sz_osrelease . rfind ( " 19. " ) = = 0 ) scale_factor = 2 ;
}
2020-03-12 02:10:19 +00:00
}
# else
scale_factor = 1 ;
# endif
2020-01-06 15:09:15 +00:00
2018-06-30 15:16:59 +00:00
dst_w = environment__window_width ;
dst_h = environment__window_height ;
//alert(dst_w);
//alert(dst_h);
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glOrtho ( 0.0 , dst_w , 0.0 , dst_h , - 1.0 , 1.0 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glScalef ( 1 , - 1 , 1 ) ; //flip vertically
glTranslatef ( 0 , - dst_h , 0 ) ; //move to new vertical position
2020-01-06 15:09:15 +00:00
glViewport ( 0 , 0 , dst_w * scale_factor , dst_h * scale_factor ) ;
2018-06-30 15:16:59 +00:00
} else {
static hardware_img_struct * hardware_img ;
hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , render_state . dest_handle ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
gluOrtho2D ( 0 , hardware_img - > w , 0 , hardware_img - > h ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glViewport ( 0 , 0 , hardware_img - > w , hardware_img - > h ) ;
}
}
if ( new_mode = = VIEW_MODE__3D ) {
if ( current_mode ! = VIEW_MODE__2D ) {
glColor4f ( 1.f , 1.f , 1.f , 1.f ) ;
glDisable ( GL_COLOR_MATERIAL ) ;
glDisable ( GL_LIGHTING ) ;
set_alpha ( ALPHA_MODE__BLEND ) ;
glEnable ( GL_TEXTURE_2D ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glCullFace ( GL_BACK ) ;
}
if ( render_state . dest_handle = = 0 ) {
static int32 dst_w , dst_h ;
dst_w = environment__window_width ;
dst_h = environment__window_height ;
glViewport ( 0 , 0 , ( GLsizei ) dst_w , ( GLsizei ) dst_h ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
//note: the max FOV is 90-degrees (this maximum applies to the longest screen dimension)
float fov ;
if ( environment_2d__screen_scaled_width > environment_2d__screen_scaled_height ) {
fov = 90.0f * ( ( float ) environment__window_width / ( float ) environment_2d__screen_scaled_width ) ;
//convert fov from horizontal to vertical
fov = fov * ( ( float ) dst_h / ( float ) dst_w ) ;
} else {
fov = 90.0f * ( ( float ) environment__window_height / ( float ) environment_2d__screen_scaled_height ) ;
}
2020-12-21 14:03:34 +00:00
gluPerspective ( fov , ( GLfloat ) dst_w / ( GLfloat ) dst_h , 0.1 , 10000.0 ) ; // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
2018-06-30 15:16:59 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
} else {
static hardware_img_struct * hardware_img ;
hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , render_state . dest_handle ) ;
static int32 dst_w , dst_h ;
dst_w = hardware_img - > w ;
dst_h = hardware_img - > h ;
glViewport ( 0 , 0 , ( GLsizei ) dst_w , ( GLsizei ) dst_h ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glScalef ( 1.0 , - 1.0 , 1.0 ) ;
//note: the max FOV is 90-degrees (this maximum applies to the longest screen dimension)
float fov ;
if ( dst_w > dst_h ) {
fov = 90.0f ;
//convert fov from horizontal to vertical
fov = fov * ( ( float ) dst_h / ( float ) dst_w ) ;
} else {
fov = 90.0f ;
}
2020-12-21 14:03:34 +00:00
gluPerspective ( fov , ( GLfloat ) dst_w / ( GLfloat ) dst_h , 0.1 , 10000.0 ) ; // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
2018-06-30 15:16:59 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
//alert("3D rendering onto FBO not supported yet");
}
}
render_state . view_mode = new_mode ;
} //change_render_state
void set_render_source ( int32 new_handle ) {
if ( new_handle = = INVALID_HARDWARE_HANDLE ) {
hardware_buffer_flush ( ) ;
render_state . source_handle = INVALID_HARDWARE_HANDLE ;
return ;
}
int32 current_handle ;
current_handle = render_state . source_handle ;
if ( current_handle = = new_handle ) return ;
hardware_buffer_flush ( ) ;
hardware_img_struct * hardware_img ;
hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , new_handle ) ;
if ( hardware_img - > texture_handle = = 0 ) hardware_img_buffer_to_texture ( new_handle ) ;
glBindTexture ( GL_TEXTURE_2D , hardware_img - > texture_handle ) ;
render_state . source_handle = new_handle ;
render_state . source = & hardware_img - > source_state ;
//note: some older systems require calling glTexParameterf after textures are rebound
if ( framebufferobjects_supported = = 0 ) {
render_state . source - > smooth_shrunk = SMOOTH_MODE__UNKNOWN ;
render_state . source - > smooth_stretched = SMOOTH_MODE__UNKNOWN ;
}
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void set_render_dest ( int32 new_handle ) {
if ( new_handle = = INVALID_HARDWARE_HANDLE ) {
hardware_buffer_flush ( ) ;
render_state . dest_handle = INVALID_HARDWARE_HANDLE ;
set_view ( VIEW_MODE__UNKNOWN ) ;
return ;
}
//0=primary surface
static int32 current_handle ;
current_handle = render_state . dest_handle ;
if ( new_handle = = current_handle ) return ;
hardware_buffer_flush ( ) ;
set_view ( VIEW_MODE__UNKNOWN ) ;
if ( new_handle = = 0 ) {
if ( framebufferobjects_supported ) glBindFramebufferEXT ( GL_FRAMEBUFFER , 0 ) ;
render_state . dest = & dest_render_state0 ;
} else {
static hardware_img_struct * hardware_img ;
hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , new_handle ) ;
//convert to regular texture first if necessary
if ( hardware_img - > texture_handle = = 0 ) hardware_img_buffer_to_texture ( new_handle ) ;
//does it have a dest context/FBO? if not create one
if ( hardware_img - > dest_context_handle = = 0 ) {
static GLuint framebuffer_handle ;
framebuffer_handle = 0 ;
glGenFramebuffersEXT ( 1 , & framebuffer_handle ) ;
glBindFramebufferEXT ( GL_FRAMEBUFFER , framebuffer_handle ) ;
hardware_img - > dest_context_handle = framebuffer_handle ;
2020-12-21 14:03:34 +00:00
glFramebufferTexture2DEXT ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , hardware_img - > texture_handle , 0 ) ;
2018-06-30 15:16:59 +00:00
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//glClear(GL_COLOR_BUFFER_BIT);
glColor4f ( 1.f , 1.f , 1.f , 1.f ) ;
set_render_source ( INVALID_HARDWARE_HANDLE ) ;
} else {
glBindFramebufferEXT ( GL_FRAMEBUFFER , hardware_img - > dest_context_handle ) ;
}
render_state . dest = & hardware_img - > dest_state ;
}
render_state . dest_handle = new_handle ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void hardware_img_put ( int32 dst_x1 , int32 dst_y1 , int32 dst_x2 , int32 dst_y2 ,
int32 src_img , int32 dst_img ,
int32 src_x1 , int32 src_y1 , int32 src_x2 , int32 src_y2 ,
int32 use_alpha ,
int32 smooth
) {
if ( dst_img < 0 ) dst_img = 0 ; //both layers render to the primary context
//ensure dst_x1/y1 represent top-left co-ordinate of destination
static int32 swap_tmp ;
if ( dst_x2 < dst_x1 ) {
swap_tmp = dst_x2 ; dst_x2 = dst_x1 ; dst_x1 = swap_tmp ;
swap_tmp = src_x2 ; src_x2 = src_x1 ; src_x1 = swap_tmp ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
if ( dst_y2 < dst_y1 ) {
swap_tmp = dst_y2 ; dst_y2 = dst_y1 ; dst_y1 = swap_tmp ;
swap_tmp = src_y2 ; src_y2 = src_y1 ; src_y1 = swap_tmp ;
}
set_render_dest ( dst_img ) ;
set_view ( VIEW_MODE__2D ) ;
if ( dst_img ) {
//static hardware_img_struct* dst_hardware_img;
//dst_hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,dst_img);
//(no specific action required here --area reserved for future use)
} else { //dest is 0
environment_2d__window_rect_struct * rect ;
rect = environment_2d__screen_to_window_rect ( dst_x1 , dst_y1 , dst_x2 , dst_y2 ) ;
dst_x1 = rect - > x1 ;
dst_y1 = rect - > y1 ;
dst_x2 = rect - > x2 ;
dst_y2 = rect - > y2 ;
}
set_render_source ( src_img ) ;
static hardware_img_struct * src_hardware_img ;
static int32 src_h , src_w ;
src_hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , src_img ) ;
src_h = src_hardware_img - > h ;
src_w = src_hardware_img - > w ;
if ( smooth ) {
set_smooth ( SMOOTH_MODE__SMOOTH , SMOOTH_MODE__SMOOTH ) ;
} else {
set_smooth ( SMOOTH_MODE__DONT_SMOOTH , SMOOTH_MODE__DONT_SMOOTH ) ;
}
if ( use_alpha ) {
set_alpha ( ALPHA_MODE__BLEND ) ;
} else {
set_alpha ( ALPHA_MODE__DONT_BLEND ) ;
}
set_depthbuffer ( DEPTHBUFFER_MODE__OFF ) ;
set_cull_mode ( CULL_MODE__NONE ) ;
set_texture_wrap ( TEXTURE_WRAP_MODE__DONT_WRAP ) ;
//adjust for render (x2 & y2 need to be one greater than the destination offset)
dst_x2 + + ; dst_y2 + + ;
if ( src_hardware_img - > source_state . PO2_fix ) {
src_w = src_hardware_img - > PO2_w ;
src_h = src_hardware_img - > PO2_h ;
2020-12-21 14:03:34 +00:00
}
2018-06-30 15:16:59 +00:00
//calc source texture co-ordinates
static float x1f , y1f , x2f , y2f ;
if ( src_x1 < = src_x2 ) {
x1f = ( ( float ) src_x1 + 0.01f ) / ( float ) src_w ;
x2f = ( ( float ) src_x2 + 0.99f ) / ( float ) src_w ;
} else {
x2f = ( ( float ) src_x2 + 0.01f ) / ( float ) src_w ;
x1f = ( ( float ) src_x1 + 0.99f ) / ( float ) src_w ;
}
if ( src_y1 < = src_y2 ) {
y1f = ( ( float ) src_y1 + 0.01f ) / ( float ) src_h ;
y2f = ( ( float ) src_y2 + 0.99f ) / ( float ) src_h ;
} else {
y2f = ( ( float ) src_y2 + 0.01f ) / ( float ) src_h ;
y1f = ( ( float ) src_y1 + 0.99f ) / ( float ) src_h ;
}
//expand buffers if necessary
if ( ( hardware_buffer_vertices_count + 18 ) > hardware_buffer_vertices_max ) {
hardware_buffer_vertices_max = hardware_buffer_vertices_max * 2 + 18 ;
hardware_buffer_vertices = ( float * ) realloc ( hardware_buffer_vertices , hardware_buffer_vertices_max * sizeof ( float ) ) ;
}
if ( ( hardware_buffer_texcoords_count + 12 ) > hardware_buffer_texcoords_max ) {
hardware_buffer_texcoords_max = hardware_buffer_texcoords_max * 2 + 12 ;
hardware_buffer_texcoords = ( float * ) realloc ( hardware_buffer_texcoords , hardware_buffer_texcoords_max * sizeof ( float ) ) ;
}
//clockwise
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x1 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y1 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x2 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y1 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x1 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y2 ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x1f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y1f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x2f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y1f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x1f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y2f ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x1 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y2 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x2 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y1 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x2 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y2 ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x1f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y2f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x2f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y1f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x2f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y2f ;
//hardware_buffer_flush(); //uncomment for debugging only
}
void hardware_img_tri2d ( float dst_x1 , float dst_y1 , float dst_x2 , float dst_y2 , float dst_x3 , float dst_y3 ,
int32 src_img , int32 dst_img ,
float src_x1 , float src_y1 , float src_x2 , float src_y2 , float src_x3 , float src_y3 ,
int32 use_alpha ,
int32 smooth
) {
if ( dst_img < 0 ) dst_img = 0 ; //both layers render to the primary context
set_render_dest ( dst_img ) ;
set_view ( VIEW_MODE__2D ) ;
if ( dst_img ) {
static hardware_img_struct * dst_hardware_img ;
dst_hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , dst_img ) ;
static int32 dst_w , dst_h ;
dst_w = dst_hardware_img - > w ;
dst_h = dst_hardware_img - > h ;
//SEAMLESS adjustments:
//reduce texture co-ordinates (maintaining top-left)
//(todo)
//NON-SEAMLESS adjustments:
//Extend rhs/bottom row to fill extra pixel space
//calculate extents
int32 rx1 ;
int32 rx2 ;
rx1 = dst_x1 ;
if ( dst_x2 < rx1 ) {
rx1 = dst_x2 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
if ( dst_x3 < rx1 ) {
rx1 = dst_x3 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
rx2 = dst_x1 ;
if ( dst_x2 > rx2 ) {
rx2 = dst_x2 ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
if ( dst_x3 > rx2 ) {
rx2 = dst_x3 ;
}
float xr ; //the multiplier for where we should be (1=no change)
if ( rx1 = = rx2 ) {
xr = 1.0f ;
} else {
xr = ( ( float ) rx2 - ( float ) rx1 + 1.0 ) / ( ( float ) rx2 - ( float ) rx1 ) ;
}
int32 ry1 ;
int32 ry2 ;
ry1 = dst_y1 ;
if ( dst_y2 < ry1 ) {
ry1 = dst_y2 ;
}
if ( dst_y3 < ry1 ) {
ry1 = dst_y3 ;
}
ry2 = dst_y1 ;
if ( dst_y2 > ry2 ) {
ry2 = dst_y2 ;
}
if ( dst_y3 > ry2 ) {
ry2 = dst_y3 ;
}
float yr ; //the multiplier for where we should be (1=no change)
if ( ry1 = = ry2 ) {
yr = 1.0f ;
} else {
yr = ( ( float ) ry2 - ( float ) ry1 + 1.0f ) / ( ( float ) ry2 - ( float ) ry1 ) ;
}
//apply multipliers so right-most and bottom-most rows will be filled
static int32 basex ;
basex = rx1 ;
dst_x1 = qbr_float_to_long (
( ( float ) ( dst_x1 - rx1 ) ) * xr + ( float ) basex
) ;
dst_x2 = qbr_float_to_long (
( ( float ) ( dst_x2 - rx1 ) ) * xr + ( float ) basex
) ;
dst_x3 = qbr_float_to_long (
( ( float ) ( dst_x3 - rx1 ) ) * xr + ( float ) basex
) ;
static int32 basey ;
basey = ry1 ;
dst_y1 = qbr_float_to_long (
( ( float ) ( dst_y1 - ry1 ) ) * yr + ( float ) basey
) ;
dst_y2 = qbr_float_to_long (
( ( float ) ( dst_y2 - ry1 ) ) * yr + ( float ) basey
) ;
dst_y3 = qbr_float_to_long (
( ( float ) ( dst_y3 - ry1 ) ) * yr + ( float ) basey
) ;
} else { //dest is 0
static int32 dst_w , dst_h ;
dst_w = environment__window_width ;
dst_h = environment__window_height ;
//SEAMLESS adjustments:
//reduce texture co-ordinates (maintaining top-left)
//(todo)
//NON-SEAMLESS adjustments:
//Extend rhs/bottom row to fill extra pixel space
//calculate extents
int32 rx1 ;
int32 rx2 ;
rx1 = dst_x1 ;
if ( dst_x2 < rx1 ) {
rx1 = dst_x2 ;
}
if ( dst_x3 < rx1 ) {
rx1 = dst_x3 ;
}
rx2 = dst_x1 ;
if ( dst_x2 > rx2 ) {
rx2 = dst_x2 ;
}
if ( dst_x3 > rx2 ) {
rx2 = dst_x3 ;
}
float xr ; //the multiplier for where we should be (1=no change)
if ( rx1 = = rx2 ) {
xr = 1.0f ;
} else {
xr = ( ( float ) rx2 - ( float ) rx1 + 1.0 ) / ( ( float ) rx2 - ( float ) rx1 ) ;
}
int32 ry1 ;
int32 ry2 ;
ry1 = dst_y1 ;
if ( dst_y2 < ry1 ) {
ry1 = dst_y2 ;
}
if ( dst_y3 < ry1 ) {
ry1 = dst_y3 ;
}
ry2 = dst_y1 ;
if ( dst_y2 > ry2 ) {
ry2 = dst_y2 ;
}
if ( dst_y3 > ry2 ) {
ry2 = dst_y3 ;
}
float yr ; //the multiplier for where we should be (1=no change)
if ( ry1 = = ry2 ) {
yr = 1.0f ;
} else {
yr = ( ( float ) ry2 - ( float ) ry1 + 1.0f ) / ( ( float ) ry2 - ( float ) ry1 ) ;
}
//apply multipliers so right-most and bottom-most rows will be filled
static int32 basex ;
basex =
qbr_float_to_long (
( ( float ) ( rx1 ) ) * environment_2d__screen_x_scale + ( float ) environment_2d__screen_x1
) ;
dst_x1 =
basex +
qbr_float_to_long (
( ( float ) ( dst_x1 - rx1 ) ) * environment_2d__screen_x_scale * xr
) ;
dst_x2 =
basex +
qbr_float_to_long (
( ( float ) ( dst_x2 - rx1 ) ) * environment_2d__screen_x_scale * xr
) ;
dst_x3 =
basex +
qbr_float_to_long (
( ( float ) ( dst_x3 - rx1 ) ) * environment_2d__screen_x_scale * xr
) ;
static int32 basey ;
basey =
qbr_float_to_long (
( ( float ) ( ry1 ) ) * environment_2d__screen_y_scale + ( float ) environment_2d__screen_y1
) ;
dst_y1 =
basey +
qbr_float_to_long (
( ( float ) ( dst_y1 - ry1 ) ) * environment_2d__screen_y_scale * yr
) ;
dst_y2 =
basey +
qbr_float_to_long (
( ( float ) ( dst_y2 - ry1 ) ) * environment_2d__screen_y_scale * yr
) ;
dst_y3 =
basey +
qbr_float_to_long (
( ( float ) ( dst_y3 - ry1 ) ) * environment_2d__screen_y_scale * yr
) ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
set_render_source ( src_img ) ;
static hardware_img_struct * src_hardware_img ;
static int32 src_h , src_w ;
src_hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , src_img ) ;
src_h = src_hardware_img - > h ;
src_w = src_hardware_img - > w ;
if ( smooth = = 0 ) {
set_smooth ( SMOOTH_MODE__DONT_SMOOTH , SMOOTH_MODE__DONT_SMOOTH ) ;
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
if ( smooth = = 1 ) {
set_smooth ( SMOOTH_MODE__SMOOTH , SMOOTH_MODE__SMOOTH ) ;
}
if ( smooth = = 2 ) {
set_smooth ( SMOOTH_MODE__SMOOTH , SMOOTH_MODE__DONT_SMOOTH ) ;
}
if ( smooth = = 3 ) {
set_smooth ( SMOOTH_MODE__DONT_SMOOTH , SMOOTH_MODE__SMOOTH ) ;
}
set_texture_wrap ( TEXTURE_WRAP_MODE__WRAP ) ;
if ( use_alpha ) {
set_alpha ( ALPHA_MODE__BLEND ) ;
} else {
set_alpha ( ALPHA_MODE__DONT_BLEND ) ;
}
set_depthbuffer ( DEPTHBUFFER_MODE__OFF ) ;
set_cull_mode ( CULL_MODE__NONE ) ;
if ( src_hardware_img - > source_state . PO2_fix ) {
src_w = src_hardware_img - > PO2_w ;
src_h = src_hardware_img - > PO2_h ;
2020-12-21 14:03:34 +00:00
}
2018-06-30 15:16:59 +00:00
//calc source texture co-ordinates
static float x1f , y1f , x2f , y2f , x3f , y3f ;
x1f = ( ( float ) src_x1 + 0.5f ) / ( float ) src_w ;
x2f = ( ( float ) src_x2 + 0.5f ) / ( float ) src_w ;
x3f = ( ( float ) src_x3 + 0.5f ) / ( float ) src_w ;
y1f = ( ( float ) src_y1 + 0.5f ) / ( float ) src_h ;
y2f = ( ( float ) src_y2 + 0.5f ) / ( float ) src_h ;
y3f = ( ( float ) src_y3 + 0.5f ) / ( float ) src_h ;
//expand buffers if necessary
if ( ( hardware_buffer_vertices_count + 9 ) > hardware_buffer_vertices_max ) {
hardware_buffer_vertices_max = hardware_buffer_vertices_max * 2 + 9 ;
hardware_buffer_vertices = ( float * ) realloc ( hardware_buffer_vertices , hardware_buffer_vertices_max * sizeof ( float ) ) ;
}
if ( ( hardware_buffer_texcoords_count + 6 ) > hardware_buffer_texcoords_max ) {
hardware_buffer_texcoords_max = hardware_buffer_texcoords_max * 2 + 6 ;
hardware_buffer_texcoords = ( float * ) realloc ( hardware_buffer_texcoords , hardware_buffer_texcoords_max * sizeof ( float ) ) ;
}
//clockwise
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x1 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y1 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x2 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y2 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x3 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y3 ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x1f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y1f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x2f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y2f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x3f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y3f ;
//hardware_buffer_flush(); //uncomment for debugging only
}
void clear_depthbuffer ( int32 dst_img ) {
2015-10-30 12:18:44 +00:00
hardware_buffer_flush ( ) ;
2018-06-30 15:16:59 +00:00
if ( dst_img < 0 ) dst_img = 0 ; //both layers render to the primary context
set_render_dest ( dst_img ) ;
if ( dst_img > 0 ) {
hardware_img_requires_depthbuffer ( ( hardware_img_struct * ) list_get ( hardware_img_handles , dst_img ) ) ;
}
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2015-10-30 12:18:44 +00:00
}
2018-06-30 15:16:59 +00:00
void hardware_img_tri3d ( float dst_x1 , float dst_y1 , float dst_z1 , float dst_x2 , float dst_y2 , float dst_z2 , float dst_x3 , float dst_y3 , float dst_z3 ,
int32 src_img , int32 dst_img ,
float src_x1 , float src_y1 , float src_x2 , float src_y2 , float src_x3 , float src_y3 ,
int32 use_alpha ,
int32 smooth ,
int32 cull_mode ,
int32 depthbuffer_mode
) {
if ( dst_img < 0 ) dst_img = 0 ; //both layers render to the primary context
set_render_dest ( dst_img ) ;
set_view ( VIEW_MODE__3D ) ;
if ( dst_img ) {
static hardware_img_struct * dst_hardware_img ;
dst_hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , dst_img ) ;
hardware_img_requires_depthbuffer ( dst_hardware_img ) ;
2020-12-21 14:03:34 +00:00
} else { //dest is 0
2018-06-30 15:16:59 +00:00
}
set_render_source ( src_img ) ;
static hardware_img_struct * src_hardware_img ;
static int32 src_h , src_w ;
src_hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , src_img ) ;
src_h = src_hardware_img - > h ;
src_w = src_hardware_img - > w ;
if ( smooth = = 0 ) {
set_smooth ( SMOOTH_MODE__DONT_SMOOTH , SMOOTH_MODE__DONT_SMOOTH ) ;
}
if ( smooth = = 1 ) {
set_smooth ( SMOOTH_MODE__SMOOTH , SMOOTH_MODE__SMOOTH ) ;
}
if ( smooth = = 2 ) {
set_smooth ( SMOOTH_MODE__SMOOTH , SMOOTH_MODE__DONT_SMOOTH ) ;
}
if ( smooth = = 3 ) {
set_smooth ( SMOOTH_MODE__DONT_SMOOTH , SMOOTH_MODE__SMOOTH ) ;
}
set_texture_wrap ( TEXTURE_WRAP_MODE__WRAP ) ;
if ( use_alpha ) {
set_alpha ( ALPHA_MODE__BLEND ) ;
} else {
set_alpha ( ALPHA_MODE__DONT_BLEND ) ;
}
set_depthbuffer ( depthbuffer_mode ) ;
//on frame buffers the 3D perspective is flipped vertically reversing the cull direction
if ( dst_img > 0 ) {
if ( cull_mode = = CULL_MODE__CLOCKWISE_ONLY ) {
cull_mode = CULL_MODE__ANTICLOCKWISE_ONLY ;
} else {
if ( cull_mode = = CULL_MODE__ANTICLOCKWISE_ONLY ) cull_mode = CULL_MODE__CLOCKWISE_ONLY ;
}
}
set_cull_mode ( cull_mode ) ;
if ( src_hardware_img - > source_state . PO2_fix ) {
src_w = src_hardware_img - > PO2_w ;
src_h = src_hardware_img - > PO2_h ;
2020-12-21 14:03:34 +00:00
}
2018-06-30 15:16:59 +00:00
//calc source texture co-ordinates
static float x1f , y1f , x2f , y2f , x3f , y3f ;
x1f = ( ( float ) src_x1 + 0.5f ) / ( float ) src_w ;
x2f = ( ( float ) src_x2 + 0.5f ) / ( float ) src_w ;
x3f = ( ( float ) src_x3 + 0.5f ) / ( float ) src_w ;
y1f = ( ( float ) src_y1 + 0.5f ) / ( float ) src_h ;
y2f = ( ( float ) src_y2 + 0.5f ) / ( float ) src_h ;
y3f = ( ( float ) src_y3 + 0.5f ) / ( float ) src_h ;
//expand buffers if necessary
if ( ( hardware_buffer_vertices_count + 9 ) > hardware_buffer_vertices_max ) {
hardware_buffer_vertices_max = hardware_buffer_vertices_max * 2 + 9 ;
hardware_buffer_vertices = ( float * ) realloc ( hardware_buffer_vertices , hardware_buffer_vertices_max * sizeof ( float ) ) ;
}
if ( ( hardware_buffer_texcoords_count + 6 ) > hardware_buffer_texcoords_max ) {
hardware_buffer_texcoords_max = hardware_buffer_texcoords_max * 2 + 6 ;
hardware_buffer_texcoords = ( float * ) realloc ( hardware_buffer_texcoords , hardware_buffer_texcoords_max * sizeof ( float ) ) ;
}
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x1 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y1 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_z1 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x2 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y2 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_z2 ;
hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_x3 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_y3 ; hardware_buffer_vertices [ hardware_buffer_vertices_count + + ] = dst_z3 ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x1f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y1f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x2f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y2f ;
hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = x3f ; hardware_buffer_texcoords [ hardware_buffer_texcoords_count + + ] = y3f ;
//hardware_buffer_flush(); //uncomment for debugging only
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
static int32 software_screen_hardware_frame = 0 ;
static int32 in_GLUT_DISPLAY_REQUEST = 0 ;
void GLUT_DISPLAY_REQUEST ( ) {
if ( in_GLUT_DISPLAY_REQUEST ) {
return ;
}
in_GLUT_DISPLAY_REQUEST = 1 ;
2019-04-01 02:38:36 +00:00
# ifdef QB64_MACOSX
if ( temp_window_title_set = = 1 ) {
glutSetWindowTitle ( ( char * ) window_title ) ;
temp_window_title_set = 0 ;
2020-12-21 14:03:34 +00:00
}
2019-04-01 02:38:36 +00:00
# endif
2018-06-30 15:16:59 +00:00
//general use variables
static int32 i , i2 , i3 ;
static int32 x , y , x2 , y2 ;
//determine which software frame to display
static int32 last_i ; //the last software frame displayed
last_i = - 1 ;
for ( i2 = 0 ; i2 < = 2 ; i2 + + ) {
if ( display_frame [ i2 ] . state = = DISPLAY_FRAME_STATE__DISPLAYING ) {
last_i = i2 ;
}
}
i = - 1 ;
static int64 highest_order ;
highest_order = 0 ;
if ( last_i ! = - 1 ) highest_order = display_frame [ last_i ] . order ; //avoid any frames below the current one
for ( i2 = 0 ; i2 < = 2 ; i2 + + ) {
if ( display_frame [ i2 ] . state = = DISPLAY_FRAME_STATE__READY & & display_frame [ i2 ] . order > highest_order ) {
highest_order = display_frame [ i2 ] . order ;
i = i2 ;
}
}
if ( i = = - 1 ) i = last_i ;
if ( i = = - 1 ) {
in_GLUT_DISPLAY_REQUEST = 0 ;
return ; //no frames exist yet, so screen size cannot be determined, therefore no action possible
}
2020-12-21 14:03:34 +00:00
if ( i ! = last_i ) {
2018-06-30 15:16:59 +00:00
for ( i2 = 0 ; i2 < = 2 ; i2 + + ) {
if ( display_frame [ i2 ] . order < display_frame [ i ] . order & & ( display_frame [ i2 ] . state = = DISPLAY_FRAME_STATE__DISPLAYING | | display_frame [ i2 ] . state = = DISPLAY_FRAME_STATE__READY ) ) display_frame [ i2 ] . state = DISPLAY_FRAME_STATE__EMPTY ;
}
display_frame [ i ] . state = DISPLAY_FRAME_STATE__DISPLAYING ;
}
static int64 order ;
order = last_hardware_display_frame_order ;
static int32 first_command_prev_order = 0 ;
static int32 rerender_prev_hardware_frame = 0 ;
rerender_prev_hardware_frame = 0 ;
//if no new software frame, only proceed if there is _GL content to render
if ( last_rendered_hardware_display_frame_order = = last_hardware_display_frame_order ) {
if ( i = = last_i ) {
if ( full_screen_set = = - 1 ) { //no pending full-screen changes
if ( os_resize_event = = 0 ) { //no resize events
2020-12-21 14:03:34 +00:00
# ifndef DEPENDENCY_GL //we aren't using SUB _GL
2018-06-30 15:16:59 +00:00
in_GLUT_DISPLAY_REQUEST = 0 ;
return ;
# endif
if ( displayorder_glrender = = 0 ) {
in_GLUT_DISPLAY_REQUEST = 0 ;
return ;
}
if ( first_command_prev_order ) {
rerender_prev_hardware_frame = 1 ;
//reset next command to prev hardware frame's handle (if any)
last_hardware_command_rendered = first_command_prev_order ;
}
}
}
}
}
first_command_prev_order = 0 ;
//set environment variables
environment_2d__screen_width = display_frame [ i ] . w ;
environment_2d__screen_height = display_frame [ i ] . h ;
os_resize_event = 0 ; //turn off flag which forces a render to take place even if no content has changed
if ( ( full_screen = = 0 ) & & ( full_screen_set = = - 1 ) ) { //not in (or attempting to enter) full screen
display_required_x = display_frame [ i ] . w ; display_required_y = display_frame [ i ] . h ;
static int32 framesize_changed ;
framesize_changed = 0 ;
if ( ( display_required_x ! = resize_snapback_x ) | | ( display_required_y ! = resize_snapback_y ) ) framesize_changed = 1 ;
resize_auto_ideal_aspect = ( float ) display_frame [ i ] . w / ( float ) display_frame [ i ] . h ;
resize_snapback_x = display_required_x ; resize_snapback_y = display_required_y ;
if ( resize_auto ) {
//maintain aspect ratio
static float ar ;
ar = ( float ) display_x / ( float ) display_y ;
if ( ( ar ! = resize_auto_accept_aspect ) & & ( ar ! = resize_auto_ideal_aspect ) ) {
//set new size
static int32 x , y ;
if ( display_x_prev = = display_x ) {
y = display_y ;
x = ( float ) y * resize_auto_ideal_aspect ;
}
if ( display_y_prev = = display_y ) {
x = display_x ;
y = ( float ) x / resize_auto_ideal_aspect ;
}
if ( ( display_y_prev ! = display_y ) & & ( display_x_prev ! = display_x ) ) {
if ( abs ( display_y_prev - display_y ) < abs ( display_x_prev - display_x ) ) {
x = display_x ;
y = ( float ) x / resize_auto_ideal_aspect ;
} else {
y = display_y ;
x = ( float ) y * resize_auto_ideal_aspect ;
}
}
resize_auto_accept_aspect = ( float ) x / ( float ) y ;
resize_pending = 1 ;
glutReshapeWindow ( x , y ) ;
glutPostRedisplay ( ) ;
2020-12-21 14:03:34 +00:00
goto auto_resized ;
2018-06-30 15:16:59 +00:00
}
} //resize_auto
if ( ( display_required_x ! = display_x ) | | ( display_required_y ! = display_y ) ) {
if ( resize_snapback | | framesize_changed ) {
glutReshapeWindow ( display_required_x , display_required_y ) ;
glutPostRedisplay ( ) ;
resize_pending = 1 ;
}
}
auto_resized : ;
} //not in (or attempting to enter) full screen
//Pseudo-Fullscreen
if ( ! resize_pending ) { //avoid switching to fullscreen before resize operations take effect
2020-12-21 14:03:34 +00:00
if ( full_screen_set ! = - 1 ) { //full screen mode change requested
2018-06-30 15:16:59 +00:00
if ( full_screen_set = = 0 ) {
if ( full_screen ! = 0 ) {
//exit full screen
resize_pending = 1 ;
glutReshapeWindow ( display_frame [ i ] . w , display_frame [ i ] . h ) ;
glutPostRedisplay ( ) ;
}
full_screen = 0 ;
full_screen_set = - 1 ;
} else {
if ( full_screen = = 0 ) {
glutFullScreen ( ) ;
}
full_screen = full_screen_set ;
full_screen_set = - 1 ;
} //enter full screen
} //full_screen_set check
} //size pending check
//This code is deprecated but kept for reference purposes
// 1) It was found to be unstable
// 2) Switching modes means a high chance of losing pre-loaded OpenGL hardware textures/surfaces
/*
static int32 glut_window ;
//fullscreen
if ( ! resize_pending ) { //avoid switching to fullscreen before resize operations take effect
2020-12-21 14:03:34 +00:00
if ( full_screen_set ! = - 1 ) { //full screen mode change requested
2018-06-30 15:16:59 +00:00
if ( full_screen_set = = 0 ) {
//exit full screen
glutLeaveGameMode ( ) ;
glutSetWindow ( glut_window ) ;
reinit_glut_callbacks ( ) ;
full_screen = 0 ;
full_screen_set = - 1 ;
return ;
} else {
static char game_mode_string [ 1000 ] ;
static int32 game_mode_string_i ;
game_mode_string_i = 0 ;
game_mode_string_i + = sprintf ( & game_mode_string [ game_mode_string_i ] , " %d " , display_frame [ i ] . w ) ;
game_mode_string [ game_mode_string_i + + ] = 120 ; //"x"
game_mode_string_i + = sprintf ( & game_mode_string [ game_mode_string_i ] , " %d " , display_frame [ i ] . h ) ;
game_mode_string [ game_mode_string_i + + ] = 58 ; //":"
game_mode_string_i + = sprintf ( & game_mode_string [ game_mode_string_i ] , " %d " , 32 ) ;
glutGameModeString ( game_mode_string ) ;
if ( glutGameModeGet ( GLUT_GAME_MODE_POSSIBLE ) ) {
//full screen using native dimensions which match the frame size
if ( full_screen = = 0 ) glut_window = glutGetWindow ( ) ;
glutEnterGameMode ( ) ;
fullscreen_width = display_frame [ i ] . w ; fullscreen_height = display_frame [ i ] . h ;
reinit_glut_callbacks ( ) ;
full_screen = full_screen_set ; //it's currently irrelavent if it is stretched or 1:1
full_screen_set = - 1 ;
return ;
} else { //native dimensions not possible
//attempt full screen using desktop dimensions
static int32 w ; w = glutGet ( GLUT_SCREEN_WIDTH ) ;
static int32 h ; h = glutGet ( GLUT_SCREEN_HEIGHT ) ;
game_mode_string_i = 0 ;
game_mode_string_i + = sprintf ( & game_mode_string [ game_mode_string_i ] , " %d " , w ) ;
game_mode_string [ game_mode_string_i + + ] = 120 ; //"x"
game_mode_string_i + = sprintf ( & game_mode_string [ game_mode_string_i ] , " %d " , h ) ;
game_mode_string [ game_mode_string_i + + ] = 58 ; //":"
game_mode_string_i + = sprintf ( & game_mode_string [ game_mode_string_i ] , " %d " , 32 ) ;
glutGameModeString ( game_mode_string ) ;
if ( glutGameModeGet ( GLUT_GAME_MODE_POSSIBLE ) ) {
2020-12-21 14:03:34 +00:00
//full screen using desktop dimensions
2018-06-30 15:16:59 +00:00
if ( full_screen = = 0 ) glut_window = glutGetWindow ( ) ;
glutEnterGameMode ( ) ;
fullscreen_width = w ; fullscreen_height = h ;
reinit_glut_callbacks ( ) ;
screen_scale = full_screen_set ;
full_screen = full_screen_set ;
full_screen_set = - 1 ;
2020-12-21 14:03:34 +00:00
return ;
2018-06-30 15:16:59 +00:00
} else {
//cannot enter full screen
full_screen = 0 ;
full_screen_set = - 1 ;
}
}
} //enter full screen
} //full_screen_set check
} //size pending check
*/
//set window environment variables
environment__window_width = display_x ;
environment__window_height = display_y ;
prepare_environment_2d ( ) ;
//need a few variables here
static int32 first_hardware_layer_rendered ;
static int32 first_hardware_layer_command ;
first_hardware_layer_rendered = 0 ;
first_hardware_layer_command = 0 ;
static int32 level ; for ( level = 0 ; level < = 5 ; level + + ) {
static int32 x1 , y1 , x2 , y2 ;
if ( level = = 0 ) {
set_render_dest ( 0 ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
} else {
if ( level = = displayorder_glrender ) {
# ifdef DEPENDENCY_GL
set_view ( VIEW_MODE__RESET ) ;
if ( close_program | | dont_call_sub_gl | | suspend_program | | stop_program ) goto abort_gl ;
display_lock_request + + ;
while ( display_lock_confirmed < display_lock_request ) {
if ( close_program | | dont_call_sub_gl | | suspend_program | | stop_program ) goto abort_gl ;
qbevent = 1 ; Sleep ( 0 ) ;
}
sub_gl_called = 1 ;
SUB__GL ( ) ;
sub_gl_called = 0 ;
abort_gl : ;
display_lock_released = display_lock_confirmed ;
# endif //DEPENDENCY_GL
} //level==displayorder_glrender
if ( level = = displayorder_screen ) { //defaults to 1
if ( software_screen_hardware_frame ! = 0 & & i ! = last_i ) {
free_hardware_img ( software_screen_hardware_frame , 847001 ) ;
}
if ( i ! = last_i | | software_screen_hardware_frame = = 0 ) {
2020-12-21 14:03:34 +00:00
software_screen_hardware_frame = new_hardware_img ( display_frame [ i ] . w , display_frame [ i ] . h , display_frame [ i ] . bgra , NULL ) ;
2018-06-30 15:16:59 +00:00
}
static hardware_img_struct * f1 ;
f1 = ( hardware_img_struct * ) list_get ( hardware_img_handles , software_screen_hardware_frame ) ;
if ( software_screen_hardware_frame = = 0 ) {
alert ( " Invalid software_screen_hardware_frame!! " ) ;
}
if ( f1 = = NULL ) alert ( " Invalid software_screen_hardware_frame! " ) ;
static int32 use_alpha ;
2020-12-21 14:03:34 +00:00
use_alpha = 0 ; if ( level > 1 ) use_alpha = 1 ;
2018-06-30 15:16:59 +00:00
2020-12-21 14:03:34 +00:00
//put the software screen
2018-06-30 15:16:59 +00:00
hardware_img_put ( 0 , 0 , environment_2d__screen_width - 1 , environment_2d__screen_height - 1 ,
software_screen_hardware_frame , 0 ,
0 , 0 , f1 - > w - 1 , f1 - > h - 1 ,
use_alpha , environment_2d__screen_smooth ) ;
hardware_buffer_flush ( ) ;
} //level==displayorder_screen
if ( level = = displayorder_hardware | | level = = displayorder_hardware1 ) {
static int32 dst ;
dst = 0 ; if ( level = = displayorder_hardware1 ) dst = - 1 ;
static int32 command ;
command = 0 ;
static int32 caller_flag ;
caller_flag = 0 ;
if ( first_hardware_layer_rendered = = 0 ) {
if ( first_hardware_command ) {
if ( last_hardware_command_rendered ) {
if ( rerender_prev_hardware_frame ) {
command = last_hardware_command_rendered ;
caller_flag = 100 ;
} else {
hardware_graphics_command_struct * last_hgc = ( hardware_graphics_command_struct * ) list_get ( hardware_graphics_command_handles , last_hardware_command_rendered ) ;
if ( last_hgc = = NULL ) alert ( " Rendering: Last HGC is NULL! " ) ;
command = last_hgc - > next_command ;
caller_flag = 200 ;
}
} else {
command = first_hardware_command ;
caller_flag = 300 ;
}
//process/skip pending hardware puts before this frame's order value
while ( command ) {
hardware_graphics_command_struct * hgc = ( hardware_graphics_command_struct * ) list_get ( hardware_graphics_command_handles , command ) ;
if ( hgc - > order < order ) {
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__FREEIMAGE ) {
free_hardware_img ( hgc - > src_img , 847002 + caller_flag ) ;
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__PUTIMAGE ) {
if ( hgc - > dst_img > 0 ) { //note: rendering to the old default surface is pointless, but renders onto maintained hardware images are still required
hardware_img_put ( hgc - > dst_x1 , hgc - > dst_y1 , hgc - > dst_x2 , hgc - > dst_y2 ,
hgc - > src_img , hgc - > dst_img ,
hgc - > src_x1 , hgc - > src_y1 , hgc - > src_x2 , hgc - > src_y2 ,
hgc - > use_alpha , hgc - > smooth ) ;
}
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__MAPTRIANGLE ) {
if ( hgc - > dst_img > 0 ) { //note: rendering to the old default surface is pointless, but renders onto maintained hardware images are still required
hardware_img_tri2d ( hgc - > dst_x1 , hgc - > dst_y1 , hgc - > dst_x2 , hgc - > dst_y2 , hgc - > dst_x3 , hgc - > dst_y3 ,
hgc - > src_img , hgc - > dst_img ,
hgc - > src_x1 , hgc - > src_y1 , hgc - > src_x2 , hgc - > src_y2 , hgc - > src_x3 , hgc - > src_y3 ,
hgc - > use_alpha , hgc - > smooth ) ;
}
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__MAPTRIANGLE3D ) {
if ( hgc - > dst_img > 0 ) { //note: rendering to the old default surface is pointless, but renders onto maintained hardware images are still required
hardware_img_tri3d ( hgc - > dst_x1 , hgc - > dst_y1 , hgc - > dst_z1 , hgc - > dst_x2 , hgc - > dst_y2 , hgc - > dst_z2 , hgc - > dst_x3 , hgc - > dst_y3 , hgc - > dst_z3 ,
hgc - > src_img , hgc - > dst_img ,
hgc - > src_x1 , hgc - > src_y1 , hgc - > src_x2 , hgc - > src_y2 , hgc - > src_x3 , hgc - > src_y3 ,
hgc - > use_alpha , hgc - > smooth , hgc - > cull_mode , hgc - > depthbuffer_mode ) ;
}
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__CLEAR_DEPTHBUFFER ) {
if ( hgc - > dst_img > 0 ) { //note: rendering to the old default surface is pointless, but renders onto maintained hardware images are still required
clear_depthbuffer ( hgc - > dst_img ) ;
}
}
last_hardware_command_rendered = command ;
if ( next_hardware_command_to_remove = = 0 ) next_hardware_command_to_remove = command ;
command = hgc - > next_command ;
hgc - > remove = 1 ;
} else {
goto found_command_from_current_order ;
}
}
found_command_from_current_order : ;
} //first_hardware_command
first_hardware_layer_command = command ;
} else {
command = first_hardware_layer_command ;
}
//process pending hardware puts for this frame's order value
while ( command ) {
hardware_graphics_command_struct * hgc = ( hardware_graphics_command_struct * ) list_get ( hardware_graphics_command_handles , command ) ;
if ( hgc = = NULL ) {
hardware_graphics_command_struct * hgcx = ( hardware_graphics_command_struct * ) list_get ( hardware_graphics_command_handles , next_hardware_command_to_remove ) ;
alert ( order ) ;
alert ( hgcx - > order ) ;
alert ( command ) ;
alert ( " Renderer: Command does not exist. " ) ;
}
if ( hgc - > order = = order ) {
if ( first_command_prev_order = = 0 ) first_command_prev_order = command ;
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__FREEIMAGE & & rerender_prev_hardware_frame = = 0 & & first_hardware_layer_rendered = = 0 ) {
free_hardware_img ( hgc - > src_img , 847003 ) ;
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__PUTIMAGE ) {
if ( rerender_prev_hardware_frame = = 0 | | hgc - > dst_img < = 0 ) {
if ( ( hgc - > dst_img > 0 & & first_hardware_layer_rendered = = 0 ) | | hgc - > dst_img = = dst ) {
hardware_img_put ( hgc - > dst_x1 , hgc - > dst_y1 , hgc - > dst_x2 , hgc - > dst_y2 ,
hgc - > src_img , hgc - > dst_img ,
2020-12-21 14:03:34 +00:00
hgc - > src_x1 , hgc - > src_y1 , hgc - > src_x2 , hgc - > src_y2 ,
2018-06-30 15:16:59 +00:00
hgc - > use_alpha , hgc - > smooth ) ;
}
}
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__MAPTRIANGLE ) {
if ( rerender_prev_hardware_frame = = 0 | | hgc - > dst_img < = 0 ) {
if ( ( hgc - > dst_img > 0 & & first_hardware_layer_rendered = = 0 ) | | hgc - > dst_img = = dst ) {
hardware_img_tri2d ( hgc - > dst_x1 , hgc - > dst_y1 , hgc - > dst_x2 , hgc - > dst_y2 , hgc - > dst_x3 , hgc - > dst_y3 ,
hgc - > src_img , hgc - > dst_img ,
hgc - > src_x1 , hgc - > src_y1 , hgc - > src_x2 , hgc - > src_y2 , hgc - > src_x3 , hgc - > src_y3 ,
hgc - > use_alpha , hgc - > smooth ) ;
}
}
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__MAPTRIANGLE3D ) {
if ( rerender_prev_hardware_frame = = 0 | | hgc - > dst_img < = 0 ) {
if ( ( hgc - > dst_img > 0 & & first_hardware_layer_rendered = = 0 ) | | hgc - > dst_img = = dst ) {
hardware_img_tri3d ( hgc - > dst_x1 , hgc - > dst_y1 , hgc - > dst_z1 , hgc - > dst_x2 , hgc - > dst_y2 , hgc - > dst_z2 , hgc - > dst_x3 , hgc - > dst_y3 , hgc - > dst_z3 ,
hgc - > src_img , hgc - > dst_img ,
hgc - > src_x1 , hgc - > src_y1 , hgc - > src_x2 , hgc - > src_y2 , hgc - > src_x3 , hgc - > src_y3 ,
hgc - > use_alpha , hgc - > smooth , hgc - > cull_mode , hgc - > depthbuffer_mode ) ;
}
}
}
if ( hgc - > command = = HARDWARE_GRAPHICS_COMMAND__CLEAR_DEPTHBUFFER ) {
if ( rerender_prev_hardware_frame = = 0 | | hgc - > dst_img < = 0 ) {
if ( ( hgc - > dst_img > 0 & & first_hardware_layer_rendered = = 0 ) | | hgc - > dst_img = = dst ) {
clear_depthbuffer ( hgc - > dst_img ) ;
}
}
}
last_hardware_command_rendered = command ;
if ( next_hardware_command_to_remove = = 0 ) next_hardware_command_to_remove = command ; //!!!! should be prev to this command
command = hgc - > next_command ;
hgc - > remove = 1 ;
} else {
goto finished_all_commands_for_current_frame ;
}
}
finished_all_commands_for_current_frame : ;
first_hardware_layer_rendered = 1 ;
hardware_buffer_flush ( ) ;
} //level==displayorder_hardware||level==displayorder_hardware1
if ( level = = 5 ) {
if ( environment_2d__letterbox ) {
//create a black texture (if not yet created)
static uint32 black_pixel = 0x00000000 ;
static int32 black_texture = 0 ;
if ( black_texture = = 0 ) {
black_texture = new_hardware_img ( 1 , 1 , & black_pixel , NULL ) ;
}
if ( environment_2d__letterbox = = 1 ) {
//vertical stripes
hardware_img_put ( ( ( float ) - environment_2d__screen_x1 ) / environment_2d__screen_x_scale - 1.0f , 0 , - 1 , environment_2d__screen_height - 1 ,
black_texture , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 ) ;
hardware_img_put ( environment_2d__screen_width , 0 , ( ( ( float ) - environment_2d__screen_x1 ) + ( float ) environment__window_width - 1.0f ) / environment_2d__screen_x_scale + 1.0f , environment_2d__screen_height - 1 ,
black_texture , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 ) ;
} else {
//horizontal stripes
hardware_img_put ( 0 , ( ( float ) - environment_2d__screen_y1 ) / environment_2d__screen_y_scale - 1.0f , environment_2d__screen_width - 1 , - 1 ,
black_texture , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 ) ;
hardware_img_put ( 0 , environment_2d__screen_height , environment_2d__screen_width - 1 , ( ( ( float ) - environment_2d__screen_y1 ) + ( float ) environment__window_height - 1.0f ) / environment_2d__screen_y_scale + 1.0f ,
black_texture , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 ) ;
}
hardware_buffer_flush ( ) ;
} //letterbox
} //level==5
} //level!=0
} //level loop
if ( requestedKeyboardOverlayImage ) {
int32 src = requestedKeyboardOverlayImage - HARDWARE_IMG_HANDLE_OFFSET ;
hardware_img_struct * src_hardware_img ;
src_hardware_img = ( hardware_img_struct * ) list_get ( hardware_img_handles , src ) ;
/*
hardware_img_put ( 0 , 0 , src_hardware_img - > w - 1 , src_hardware_img - > h - 1 ,
src , 0 ,
0 , 0 , src_hardware_img - > w - 1 , src_hardware_img - > h - 1 ,
1 , 0 ) ;
*/
hardware_img_put ( 0 , 0 , environment_2d__screen_width - 1 , environment_2d__screen_height - 1 ,
src , 0 ,
0 , 0 , src_hardware_img - > w - 1 , src_hardware_img - > h - 1 ,
1 , 0 ) ;
hardware_buffer_flush ( ) ;
}
last_rendered_hardware_display_frame_order = last_hardware_display_frame_order ;
if ( suspend_program ) { //Otherwise skipped SUB__GL content becomes "invisible"
//...
} else {
glutSwapBuffers ( ) ;
}
in_GLUT_DISPLAY_REQUEST = 0 ;
} //GLUT_DISPLAY_REQUEST
void GLUT_MouseButton_Up ( int button , int x , int y ) {
# ifdef QB64_GLUT
int32 i ;
int32 handle ;
handle = mouse_message_queue_first ;
mouse_message_queue_struct * queue = ( mouse_message_queue_struct * ) list_get ( mouse_message_queue_handles , handle ) ;
i = queue - > last + 1 ; if ( i > queue - > lastIndex ) i = 0 ;
if ( i = = queue - > current ) {
int32 nextIndex = queue - > last + 1 ; if ( nextIndex > queue - > lastIndex ) nextIndex = 0 ;
queue - > current = nextIndex ;
}
queue - > queue [ i ] . x = x ;
queue - > queue [ i ] . y = y ;
queue - > queue [ i ] . movementx = 0 ;
queue - > queue [ i ] . movementy = 0 ;
queue - > queue [ i ] . buttons = queue - > queue [ queue - > last ] . buttons ;
if ( queue - > queue [ i ] . buttons & ( 1 < < ( button - 1 ) ) ) queue - > queue [ i ] . buttons ^ = ( 1 < < ( button - 1 ) ) ;
queue - > last = i ;
if ( device_last ) { //core devices required?
if ( ( button > = 1 ) & & ( button < = 3 ) ) {
button - - ;
static device_struct * d ;
d = & devices [ 2 ] ; //mouse
int32 eventIndex = createDeviceEvent ( d ) ;
setDeviceEventButtonValue ( d , eventIndex , button , 0 ) ;
commitDeviceEvent ( d ) ;
} //valid range
} //core devices required
# endif
2015-10-30 12:18:44 +00:00
}
2018-06-30 15:16:59 +00:00
void GLUT_MouseButton_Down ( int button , int x , int y ) {
# ifdef QB64_GLUT
int32 i ;
int32 handle ;
handle = mouse_message_queue_first ;
mouse_message_queue_struct * queue = ( mouse_message_queue_struct * ) list_get ( mouse_message_queue_handles , handle ) ;
i = queue - > last + 1 ; if ( i > queue - > lastIndex ) i = 0 ;
if ( i = = queue - > current ) {
int32 nextIndex = queue - > last + 1 ; if ( nextIndex > queue - > lastIndex ) nextIndex = 0 ;
queue - > current = nextIndex ;
}
queue - > queue [ i ] . x = x ;
queue - > queue [ i ] . y = y ;
queue - > queue [ i ] . movementx = 0 ;
queue - > queue [ i ] . movementy = 0 ;
queue - > queue [ i ] . buttons = queue - > queue [ queue - > last ] . buttons ;
queue - > queue [ i ] . buttons | = ( 1 < < ( button - 1 ) ) ;
queue - > last = i ;
if ( device_last ) { //core devices required?
if ( ( button > = 1 ) & & ( button < = 3 ) ) {
button - - ;
static device_struct * d ;
d = & devices [ 2 ] ; //mouse
int32 eventIndex = createDeviceEvent ( d ) ;
setDeviceEventButtonValue ( d , eventIndex , button , 1 ) ;
commitDeviceEvent ( d ) ;
//1-3
} else {
//not 1-3
//mouse wheel?
if ( ( button > = 4 ) & & ( button < = 5 ) ) {
static float f ;
if ( button = = 4 ) f = - 1 ; else f = 1 ;
static device_struct * d ;
d = & devices [ 2 ] ; //mouse
int32 eventIndex = createDeviceEvent ( d ) ;
setDeviceEventWheelValue ( d , eventIndex , 2 , f ) ;
commitDeviceEvent ( d ) ;
eventIndex = createDeviceEvent ( d ) ;
setDeviceEventWheelValue ( d , eventIndex , 2 , 0 ) ;
commitDeviceEvent ( d ) ;
} //4-5
} //not 1-3
} //core devices required
# endif
2015-10-30 12:18:44 +00:00
}
2018-06-30 15:16:59 +00:00
void GLUT_MOUSE_FUNC ( int glut_button , int state , int x , int y ) {
# ifdef QB64_GLUT
if ( state = = GLUT_DOWN ) GLUT_MouseButton_Down ( glut_button + 1 , x , y ) ;
if ( state = = GLUT_UP ) GLUT_MouseButton_Up ( glut_button + 1 , x , y ) ;
# endif
2015-02-20 13:15:27 +00:00
}
2018-06-30 15:16:59 +00:00
void GLUT_MOTION_FUNC ( int x , int y ) {
2021-01-11 14:32:01 +00:00
int32 i , last_i ;
2018-06-30 15:16:59 +00:00
int32 handle ;
2021-01-11 14:32:01 +00:00
int32 xrel , yrel ;
2018-06-30 15:16:59 +00:00
handle = mouse_message_queue_first ;
mouse_message_queue_struct * queue = ( mouse_message_queue_struct * ) list_get ( mouse_message_queue_handles , handle ) ;
//message #1
last_i = queue - > last ;
2021-01-11 14:32:01 +00:00
i = queue - > last + 1 ; if ( i > queue - > lastIndex ) i = 0 ; //wrap around
2018-06-30 15:16:59 +00:00
if ( i = = queue - > current ) {
2021-01-11 14:32:01 +00:00
int32 nextIndex = queue - > last + 1 ;
if ( nextIndex > queue - > lastIndex ) nextIndex = 0 ;
2018-06-30 15:16:59 +00:00
queue - > current = nextIndex ;
}
2021-01-11 14:32:01 +00:00
# ifdef QB64_WINDOWS
// Windows calculates relative movement by intercepting WM_INPUT events instead
xrel = 0 ;
yrel = 0 ;
# else
xrel = x - queue - > queue [ queue - > last ] . x ;
yrel = y - queue - > queue [ queue - > last ] . y ;
# endif
2018-06-30 15:16:59 +00:00
queue - > queue [ i ] . x = x ;
queue - > queue [ i ] . y = y ;
queue - > queue [ i ] . movementx = xrel ;
queue - > queue [ i ] . movementy = yrel ;
queue - > queue [ i ] . buttons = queue - > queue [ last_i ] . buttons ;
queue - > last = i ;
//message #2 (clears movement values to avoid confusion)
last_i = queue - > last ;
i = queue - > last + 1 ; if ( i > queue - > lastIndex ) i = 0 ;
if ( i = = queue - > current ) {
int32 nextIndex = queue - > last + 1 ; if ( nextIndex > queue - > lastIndex ) nextIndex = 0 ;
queue - > current = nextIndex ;
}
queue - > queue [ i ] . x = x ;
queue - > queue [ i ] . y = y ;
queue - > queue [ i ] . movementx = 0 ;
queue - > queue [ i ] . movementy = 0 ;
queue - > queue [ i ] . buttons = queue - > queue [ last_i ] . buttons ;
queue - > last = i ;
if ( device_last ) { //core devices required?
if ( ! device_mouse_relative ) {
static device_struct * d ;
d = & devices [ 2 ] ; //mouse
int32 eventIndex = createDeviceEvent ( d ) ;
static float fx , fy ;
static int32 z ;
fx = x ;
fx - = x_offset ;
z = x_monitor - x_offset * 2 ;
if ( fx < 0 ) fx = 0 ;
if ( fx > = z ) fx = z - 1 ;
fx = fx / ( float ) ( z - 1 ) ; //0 to 1
fx * = 2.0 ; //0 to 2
fx - = 1.0 ; //-1 to 1
fy = y ;
fy - = y_offset ;
z = y_monitor - y_offset * 2 ;
if ( fy < 0 ) fy = 0 ;
if ( fy > = z ) fy = z - 1 ;
fy = fy / ( float ) ( z - 1 ) ; //0 to 1
fy * = 2.0 ; //0 to 2
fy - = 1.0 ; //-1 to 1
setDeviceEventAxisValue ( d , eventIndex , 0 , fx ) ;
2020-12-21 14:03:34 +00:00
setDeviceEventAxisValue ( d , eventIndex , 1 , fy ) ;
2018-06-30 15:16:59 +00:00
commitDeviceEvent ( d ) ;
} else {
static device_struct * d ;
d = & devices [ 2 ] ; //mouse
int32 eventIndex = createDeviceEvent ( d ) ;
static float fx , fy ;
static int32 z ;
fx = xrel ;
fy = yrel ;
setDeviceEventWheelValue ( d , eventIndex , 0 , fx ) ;
2020-12-21 14:03:34 +00:00
setDeviceEventWheelValue ( d , eventIndex , 1 , fy ) ;
2018-06-30 15:16:59 +00:00
commitDeviceEvent ( d ) ;
eventIndex = createDeviceEvent ( d ) ;
fx = 0 ;
fy = 0 ;
setDeviceEventWheelValue ( d , eventIndex , 0 , fx ) ;
setDeviceEventWheelValue ( d , eventIndex , 1 , fy ) ;
commitDeviceEvent ( d ) ;
}
} //core devices required
2015-10-30 12:18:44 +00:00
}
2018-06-30 15:16:59 +00:00
void GLUT_PASSIVEMOTION_FUNC ( int x , int y ) {
GLUT_MOTION_FUNC ( x , y ) ;
}
void GLUT_MOUSEWHEEL_FUNC ( int wheel , int direction , int x , int y ) {
# ifdef QB64_GLUT
//Note: freeglut specific, limited documentation existed so the following research was done:
// qbs_print(qbs_str(wheel),NULL); <-- was always 0 [could 1 indicate horizontal wheel?]
// qbs_print(qbs_str(direction),NULL); <-- 1(up) or -1(down)
// qbs_print(qbs_str(x),NULL); <--mouse x,y co-ordinates
// qbs_print(qbs_str(y),1); <
if ( direction > 0 ) { GLUT_MouseButton_Down ( 4 , x , y ) ; GLUT_MouseButton_Up ( 4 , x , y ) ; }
if ( direction < 0 ) { GLUT_MouseButton_Down ( 5 , x , y ) ; GLUT_MouseButton_Up ( 5 , x , y ) ; }
# endif
}
2015-02-20 13:15:27 +00:00
# endif