mirror of
https://github.com/QB64Official/qb64.git
synced 2024-08-30 02:30:16 +00:00
The scroll wheel now behaves correctly on Linux. Reports suggest that the fix does not have any effect on OSX though. The licensing documentation is updated to reflect the fact that there are no GPL components included in a QB64 program. Some redundant code was removed from the Windows setup script. OSX setup and run scripts were missing the executable bit - hopefully the repository will preserve that change.
2174 lines
70 KiB
C++
2174 lines
70 KiB
C++
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){
|
|
|
|
//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;
|
|
for (i=1;i<=4;i++){
|
|
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;
|
|
}
|
|
}
|
|
|
|
//int32 gl_render_method=2; //1=behind, 2=ontop[default], 3=only
|
|
void sub__glrender(int32 method){
|
|
//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);
|
|
}
|
|
|
|
|
|
#ifndef QB64_GUI //begin stubs
|
|
|
|
|
|
|
|
|
|
#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***
|
|
}
|
|
|
|
|
|
|
|
|
|
//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;
|
|
*/
|
|
|
|
|
|
|
|
void free_hardware_img(int32 handle, int32 caller_id){
|
|
|
|
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;
|
|
glDeleteTextures(1, &texture);
|
|
|
|
//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);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
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
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
}//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;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float *hardware_buffer_vertices=(float*)malloc(sizeof(float)*1);
|
|
int32 *hardware_buffer_vertices_int;
|
|
|
|
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_INT, 2*sizeof(GL_INT), (int32*)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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
}else{
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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){
|
|
//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{
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
}
|
|
render_state.use_alpha=new_mode;
|
|
}
|
|
|
|
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);
|
|
}
|
|
if (new_mode==DEPTHBUFFER_MODE__ON){
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthMask(GL_TRUE);
|
|
glAlphaFunc(GL_GREATER, 0.001);
|
|
glEnable(GL_ALPHA_TEST);
|
|
}
|
|
if (new_mode==DEPTHBUFFER_MODE__LOCKED){
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthMask(GL_FALSE);
|
|
glAlphaFunc(GL_ALWAYS, 0);
|
|
}
|
|
render_state.depthbuffer_mode=new_mode;
|
|
}
|
|
|
|
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){
|
|
glFrontFace(GL_CW);
|
|
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;
|
|
}
|
|
|
|
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);
|
|
glBindTexture (GL_TEXTURE_2D, 0);
|
|
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);
|
|
new_mode=VIEW_MODE__UNKNOWN;//resets are performed before unknown operations are executed
|
|
}
|
|
if (new_mode==VIEW_MODE__2D){
|
|
if (current_mode!=VIEW_MODE__3D){
|
|
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;
|
|
|
|
//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
|
|
glViewport(0,0,dst_w,dst_h);
|
|
}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);
|
|
}
|
|
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
|
|
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;
|
|
}
|
|
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
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hardware_img->texture_handle, 0);
|
|
|
|
//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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
|
|
//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));
|
|
}
|
|
hardware_buffer_vertices_int=(int32*)hardware_buffer_vertices;
|
|
|
|
//clockwise
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x1; hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_y1;
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x2; hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_y1;
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x1; hardware_buffer_vertices_int[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_int[hardware_buffer_vertices_count++]=dst_x1; hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_y2;
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x2; hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_y1;
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x2; hardware_buffer_vertices_int[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;
|
|
}
|
|
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=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
|
|
);
|
|
|
|
}
|
|
|
|
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__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;
|
|
}
|
|
|
|
//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_int=(int32*)hardware_buffer_vertices;
|
|
|
|
|
|
|
|
//clockwise
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x1; hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_y1;
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x2; hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_y2;
|
|
hardware_buffer_vertices_int[hardware_buffer_vertices_count++]=dst_x3; hardware_buffer_vertices_int[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){
|
|
hardware_buffer_flush();
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}else{ //dest is 0
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
//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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
//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
|
|
}
|
|
if (i!=last_i){
|
|
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
|
|
#ifndef DEPENDENCY_GL //we aren't using SUB _GL
|
|
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();
|
|
|
|
|
|
|
|
goto auto_resized;
|
|
}
|
|
}//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
|
|
if (full_screen_set!=-1){//full screen mode change requested
|
|
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
|
|
if (full_screen_set!=-1){//full screen mode change requested
|
|
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)){
|
|
//full screen using desktop dimensions
|
|
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;
|
|
return;
|
|
}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){
|
|
|
|
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){
|
|
software_screen_hardware_frame=new_hardware_img(display_frame[i].w, display_frame[i].h,display_frame[i].bgra,NULL);
|
|
}
|
|
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;
|
|
use_alpha=0; if (level>1) use_alpha=1;
|
|
|
|
//put the software screen
|
|
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,
|
|
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 (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
|
|
|
|
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 glut_button,int x,int y){
|
|
#ifdef QB64_GLUT
|
|
|
|
int32 i;
|
|
int32 button;
|
|
button=1;//default
|
|
if (glut_button==GLUT_LEFT_BUTTON) button=1;
|
|
if (glut_button==GLUT_RIGHT_BUTTON) button=3;
|
|
if (glut_button==GLUT_MIDDLE_BUTTON) button=2;
|
|
if (glut_button==3) button=4;
|
|
if (glut_button==4) button=5;
|
|
i=(last_mouse_message+1)&65535;
|
|
if (i==current_mouse_message) current_mouse_message=(current_mouse_message+1)&65535;//if buffer full, skip oldest message
|
|
mouse_messages[i].movementx=0;
|
|
mouse_messages[i].movementy=0;
|
|
mouse_messages[i].x=x;
|
|
mouse_messages[i].y=y;
|
|
mouse_messages[i].buttons=mouse_messages[last_mouse_message].buttons;
|
|
if (mouse_messages[i].buttons&(1<<(button-1))) mouse_messages[i].buttons^=(1<<(button-1));
|
|
last_mouse_message=i;
|
|
if (device_last){//core devices required?
|
|
if ((button>=1)&&(button<=3)){
|
|
button--;
|
|
static device_struct *d;
|
|
d=&devices[2];//mouse
|
|
static uint8 *cp,*cp2;
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
*(d->events+(d->queued_events*d->event_size)+button)=0;
|
|
d->queued_events++;
|
|
}//valid range
|
|
}//core devices required
|
|
|
|
#endif
|
|
}
|
|
|
|
void GLUT_MouseButton_Down(int glut_button,int x,int y){
|
|
#ifdef QB64_GLUT
|
|
|
|
int32 i;
|
|
int32 button;
|
|
button=1;//default
|
|
if (glut_button==GLUT_LEFT_BUTTON) button=1;
|
|
if (glut_button==GLUT_RIGHT_BUTTON) button=3;
|
|
if (glut_button==GLUT_MIDDLE_BUTTON) button=2;
|
|
if (glut_button==3) button=4;
|
|
if (glut_button==4) button=5;
|
|
i=(last_mouse_message+1)&65535;
|
|
if (i==current_mouse_message) current_mouse_message=(current_mouse_message+1)&65535;//if buffer full, skip oldest message
|
|
mouse_messages[i].movementx=0;
|
|
mouse_messages[i].movementy=0;
|
|
mouse_messages[i].x=x;
|
|
mouse_messages[i].y=y;
|
|
mouse_messages[i].buttons=mouse_messages[last_mouse_message].buttons;
|
|
mouse_messages[i].buttons|=(1<<(button-1));
|
|
last_mouse_message=i;
|
|
if (device_last){//core devices required?
|
|
if ((button>=1)&&(button<=3)){
|
|
button--;
|
|
static device_struct *d;
|
|
d=&devices[2];//mouse
|
|
static uint8 *cp,*cp2;
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
*(d->events+(d->queued_events*d->event_size)+button)=1;
|
|
d->queued_events++;
|
|
//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
|
|
static uint8 *cp,*cp2;
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+(3-1)*4)=f;
|
|
d->queued_events++;
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+(3-1)*4)=0;
|
|
d->queued_events++;
|
|
}//4-5
|
|
}//not 1-3
|
|
}//core devices required
|
|
#endif
|
|
}
|
|
|
|
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,x,y);
|
|
if (state==GLUT_UP) GLUT_MouseButton_Up(glut_button,x,y);
|
|
#endif
|
|
}
|
|
|
|
void GLUT_MOTION_FUNC(int x, int y){
|
|
|
|
static int32 i,last_i;
|
|
static int32 xrel=0,yrel=0;
|
|
//message #1
|
|
last_i=last_mouse_message;
|
|
i=(last_mouse_message+1)&65535;
|
|
if (i==current_mouse_message) current_mouse_message=(current_mouse_message+1)&65535;//if buffer full, skip oldest message
|
|
mouse_messages[i].x=x;
|
|
mouse_messages[i].y=y;
|
|
if (mouseinput_ignoremovement){
|
|
mouseinput_ignoremovement--;
|
|
mouse_messages[i].movementx=0;
|
|
mouse_messages[i].movementy=0;
|
|
}else{
|
|
mouse_messages[i].movementx=xrel;
|
|
mouse_messages[i].movementy=yrel;
|
|
}
|
|
mouse_messages[i].buttons=mouse_messages[last_i].buttons;
|
|
last_mouse_message=i;
|
|
//message #2 (clears movement values to avoid confusion)
|
|
last_i=last_mouse_message;
|
|
i=(last_mouse_message+1)&65535;
|
|
if (i==current_mouse_message) current_mouse_message=(current_mouse_message+1)&65535;//if buffer full, skip oldest message
|
|
mouse_messages[i].x=x;
|
|
mouse_messages[i].y=y;
|
|
mouse_messages[i].movementx=0;
|
|
mouse_messages[i].movementy=0;
|
|
mouse_messages[i].buttons=mouse_messages[last_i].buttons;
|
|
last_mouse_message=i;
|
|
if (device_last){//core devices required?
|
|
if (!device_mouse_relative){
|
|
static device_struct *d;
|
|
d=&devices[2];//mouse
|
|
static uint8 *cp,*cp2;
|
|
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
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
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton)=fx;
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+4)=fy;
|
|
d->queued_events++;
|
|
}else{
|
|
static device_struct *d;
|
|
d=&devices[2];//mouse
|
|
static uint8 *cp,*cp2;
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
static float fx,fy;
|
|
static int32 z;
|
|
fx=xrel;
|
|
fy=yrel;
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4)=fx;
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+4)=fy;
|
|
d->queued_events++;
|
|
if (d->queued_events==d->max_events){//expand/shift event buffer
|
|
if (d->max_events>=QUEUED_EVENTS_LIMIT){
|
|
//discard base message
|
|
memmove(d->events,d->events+d->event_size,(d->queued_events-1)*d->event_size);
|
|
d->queued_events--;
|
|
}else{
|
|
cp=(uint8*)calloc(d->max_events*2,d->event_size);
|
|
memcpy(cp,d->events,d->queued_events*d->event_size);//copy existing events
|
|
cp2=d->events;
|
|
d->events=cp;
|
|
free(cp2);
|
|
d->max_events*=2;
|
|
}
|
|
}
|
|
memmove(d->events+d->queued_events*d->event_size,d->events+(d->queued_events-1)*d->event_size,d->event_size);//duplicate last event
|
|
*(int64*)(d->events+(d->queued_events*d->event_size)+(d->event_size-8))=device_event_index++;//store global event index
|
|
//make required changes
|
|
fx=0;
|
|
fy=0;
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4)=fx;
|
|
*(float*)(d->events+(d->queued_events*d->event_size)+d->lastbutton+d->lastaxis*4+4)=fy;
|
|
d->queued_events++;
|
|
}
|
|
}//core devices required
|
|
}
|
|
|
|
void GLUT_PASSIVEMOTION_FUNC(int x, int y){
|
|
GLUT_MOTION_FUNC(x,y);
|
|
}
|
|
|
|
|
|
#endif
|