2020-12-21 14:03:34 +00:00
|
|
|
#ifdef QB64_MACOSX
|
2022-05-06 04:02:21 +00:00
|
|
|
# include <sys/sysctl.h>
|
2020-12-21 14:03:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-01-08 12:06:28 +00:00
|
|
|
// trigger recompilation = 3
|
2015-10-30 12:18:44 +00:00
|
|
|
|
2022-05-06 04:00:36 +00:00
|
|
|
int32 displayorder_screen = 1;
|
|
|
|
int32 displayorder_hardware = 2;
|
|
|
|
int32 displayorder_glrender = 3;
|
|
|
|
int32 displayorder_hardware1 = 4;
|
2015-02-20 13:15:27 +00:00
|
|
|
|
2022-05-06 04:00:36 +00:00
|
|
|
// sub__displayorder( 1 , 2 , 4 , 3 );
|
|
|
|
// id.specialformat =
|
|
|
|
// "[{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}[,{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}[,{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}[,{_SCREEN|_HARDWARE|_HARDWARE1|_GLRENDER}]]]]"
|
2022-05-06 04:02:21 +00:00
|
|
|
void sub__displayorder(int32 method1, int32 method2, int32 method3, int32 method4) {
|
2015-02-20 13:15:27 +00:00
|
|
|
|
2022-05-06 04:00:36 +00:00
|
|
|
// check no value has been used twice
|
|
|
|
if (method1 != 0)
|
|
|
|
if (method1 == method2 || method1 == method3 || method1 == method4) {
|
|
|
|
error(5);
|
|
|
|
return;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
if (method2 != 0)
|
|
|
|
if (method2 == method1 || method2 == method3 || method2 == method4) {
|
|
|
|
error(5);
|
|
|
|
return;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
if (method3 != 0)
|
|
|
|
if (method3 == method1 || method3 == method2 || method3 == method4) {
|
|
|
|
error(5);
|
|
|
|
return;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
if (method4 != 0)
|
|
|
|
if (method4 == method1 || method4 == method2 || method4 == method3) {
|
|
|
|
error(5);
|
|
|
|
return;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2015-02-20 13:15:27 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef DEPENDENCY_GL
|
2022-05-06 04:00:36 +00:00
|
|
|
extern void SUB__GL();
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +00:00
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
# define GL_BGR 0x80E0
|
|
|
|
# define GL_BGRA 0x80E1
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
/* 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
|
2015-02-20 13:15:27 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
list *hardware_img_handles=NULL;
|
|
|
|
*/
|
|
|
|
|
|
|
|
void free_hardware_img(int32 handle, int32 caller_id) {
|
|
|
|
|
|
|
|
hardware_img_struct *hardware_img;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
if (hardware_img == NULL) {
|
|
|
|
alert("free_hardware_img: image does not exist");
|
2015-02-20 13:15:27 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if (environment_2d__screen_width == environment__window_width && environment_2d__screen_height == environment__window_height) {
|
2022-05-06 04:00:36 +00:00
|
|
|
// 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;
|
2022-05-06 04:02:21 +00:00
|
|
|
window_ratio = (float)environment__window_width / (float)environment__window_height;
|
|
|
|
screen_ratio = (float)environment_2d__screen_width / (float)environment_2d__screen_height;
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
static int32 x1, y1, x2, y2, z, x_limit, y_limit, x_offset, y_offset;
|
2022-05-06 04:00:36 +00:00
|
|
|
// 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
|
2022-05-06 04:02:21 +00:00
|
|
|
z = (float)environment__window_height * screen_ratio; // new width
|
2022-05-06 04:00:36 +00:00
|
|
|
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
|
2022-05-06 04:02:21 +00:00
|
|
|
z = (float)environment__window_width / screen_ratio; // new height
|
2022-05-06 04:00:36 +00:00
|
|
|
y1 = environment__window_height / 2 - z / 2;
|
|
|
|
y2 = y1 + z - 1;
|
2022-05-06 04:02:21 +00:00
|
|
|
environment_2d__letterbox = 2; // horizontal black stripes required
|
2022-05-06 04:00:36 +00:00
|
|
|
// y_offset=-y1;
|
|
|
|
// y_scale=(float)environment_2d__screen_height/(float)z;
|
|
|
|
// y_limit=z-1;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
environment_2d__screen_x1 = x1;
|
|
|
|
environment_2d__screen_y1 = y1;
|
|
|
|
environment_2d__screen_x2 = x2;
|
|
|
|
environment_2d__screen_y2 = y2;
|
|
|
|
}
|
|
|
|
cant_scale:
|
2022-05-06 04:02:21 +00:00
|
|
|
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;
|
2015-02-20 13:15:27 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
} // prepare_environment_2d
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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; }
|
2022-05-06 04:00:36 +00:00
|
|
|
int32 environment_2d__get_window_x2_coord(int32 x) {
|
2022-05-06 04:02:21 +00:00
|
|
|
return qbr_float_to_long(((float)x + 1.0f) * environment_2d__screen_x_scale - 1.0f) + environment_2d__screen_x1;
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int32 environment_2d__get_window_y2_coord(int32 y) {
|
2022-05-06 04:02:21 +00:00
|
|
|
return qbr_float_to_long(((float)y + 1.0f) * environment_2d__screen_y_scale - 1.0f) + environment_2d__screen_y1;
|
2022-05-06 04:00:36 +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;
|
2022-05-06 04:02:21 +00:00
|
|
|
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;
|
2022-05-06 04:00:36 +00:00
|
|
|
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_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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
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
|
2022-05-06 04:00:36 +00:00
|
|
|
glDrawArrays(GL_TRIANGLES, 0,
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_vertices_count / 2); // start index, number of indexes
|
2022-05-06 04:00:36 +00:00
|
|
|
} else {
|
2022-05-06 04:02:21 +00:00
|
|
|
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
|
2022-05-06 04:00:36 +00:00
|
|
|
glDrawArrays(GL_TRIANGLES, 0,
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_vertices_count / 3); // start index, number of indexes
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
if (new_mode_shrunk == current_mode_shrunk && new_mode_stretched == current_mode_stretched)
|
2022-05-06 04:00:36 +00:00
|
|
|
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
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifndef QB64_GLES
|
2022-05-06 04:00:36 +00:00
|
|
|
// glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
|
|
|
// GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
2022-05-06 04:02:21 +00:00
|
|
|
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
|
2022-05-06 04:00:36 +00:00
|
|
|
} else {
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2015-02-20 13:15:27 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
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.0f, 1.0f, 1.0f, 1.0f);
|
2018-06-30 15:16:59 +00:00
|
|
|
glDisable(GL_COLOR_MATERIAL);
|
|
|
|
glDisable(GL_LIGHTING);
|
2022-05-06 04:00:36 +00:00
|
|
|
set_alpha(ALPHA_MODE__BLEND);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
2018-06-30 15:16:59 +00:00
|
|
|
glCullFace(GL_BACK);
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
if (render_state.dest_handle == 0) {
|
|
|
|
static int32 dst_w, dst_h;
|
|
|
|
static int32 scale_factor = 0;
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_MACOSX
|
2022-05-06 04:00:36 +00:00
|
|
|
if (scale_factor == 0) {
|
|
|
|
// 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;
|
2022-05-06 04:02:21 +00:00
|
|
|
FILE *consoleStream = popen("system_profiler SPDisplaysDataType", "r");
|
2022-05-06 04:00:36 +00:00
|
|
|
if (consoleStream) {
|
|
|
|
char buffer[128];
|
|
|
|
while (!feof(consoleStream)) {
|
|
|
|
if (fgets(buffer, 128, consoleStream) != NULL) {
|
|
|
|
string szBuffer(buffer);
|
|
|
|
|
|
|
|
if (!b_isRetina)
|
2022-05-06 04:02:21 +00:00
|
|
|
b_isRetina = (szBuffer.rfind("Retina") != ULONG_MAX);
|
2022-05-06 04:00:36 +00:00
|
|
|
if (!b_is5k)
|
|
|
|
b_is5k = (szBuffer.rfind("5K") != ULONG_MAX);
|
2020-12-21 14:03:34 +00:00
|
|
|
}
|
2020-03-12 02:10:19 +00:00
|
|
|
}
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
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);
|
2022-05-06 04:02:21 +00:00
|
|
|
int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
string sz_osrelease(str);
|
|
|
|
if (sz_osrelease.rfind("19.") == 0)
|
|
|
|
scale_factor = 2;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:02:21 +00:00
|
|
|
# else
|
2022-05-06 04:00:36 +00:00
|
|
|
scale_factor = 1;
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +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
|
|
|
|
glViewport(0, 0, dst_w * scale_factor, dst_h * scale_factor);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
static hardware_img_struct *hardware_img;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, render_state.dest_handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
set_alpha(ALPHA_MODE__BLEND);
|
2022-05-06 04:00:36 +00:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glCullFace(GL_BACK);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
if (environment_2d__screen_scaled_width > environment_2d__screen_scaled_height) {
|
|
|
|
fov = 90.0f * ((float)environment__window_width / (float)environment_2d__screen_scaled_width);
|
2022-05-06 04:00:36 +00:00
|
|
|
// convert fov from horizontal to vertical
|
|
|
|
fov = fov * ((float)dst_h / (float)dst_w);
|
|
|
|
} else {
|
2022-05-06 04:02:21 +00:00
|
|
|
fov = 90.0f * ((float)environment__window_height / (float)environment_2d__screen_scaled_height);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +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
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
} else {
|
|
|
|
|
|
|
|
static hardware_img_struct *hardware_img;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, render_state.dest_handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +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
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
// alert("3D rendering onto FBO not supported yet");
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, new_handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
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) {
|
2015-10-30 12:18:44 +00:00
|
|
|
hardware_buffer_flush();
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, new_handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
// 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;
|
2022-05-06 04:02:21 +00:00
|
|
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hardware_img->texture_handle, 0);
|
2022-05-06 04:00:36 +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 {
|
2022-05-06 04:02:21 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER, hardware_img->dest_context_handle);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
render_state.dest = &hardware_img->dest_state;
|
|
|
|
}
|
|
|
|
render_state.dest_handle = new_handle;
|
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +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) {
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
rect = environment_2d__screen_to_window_rect(dst_x1, dst_y1, dst_x2, dst_y2);
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
src_hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, src_img);
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_vertices = (float *)realloc(hardware_buffer_vertices, hardware_buffer_vertices_max * sizeof(float));
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
2022-05-06 04:02:21 +00:00
|
|
|
if ((hardware_buffer_texcoords_count + 12) > hardware_buffer_texcoords_max) {
|
2022-05-06 04:00:36 +00:00
|
|
|
hardware_buffer_texcoords_max = hardware_buffer_texcoords_max * 2 + 12;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_texcoords = (float *)realloc(hardware_buffer_texcoords, hardware_buffer_texcoords_max * sizeof(float));
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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) {
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
dst_hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, dst_img);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2022-05-06 04:00:36 +00:00
|
|
|
static int32 basey;
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
set_render_source(src_img);
|
|
|
|
|
|
|
|
static hardware_img_struct *src_hardware_img;
|
|
|
|
static int32 src_h, src_w;
|
2022-05-06 04:02:21 +00:00
|
|
|
src_hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, src_img);
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_vertices = (float *)realloc(hardware_buffer_vertices, hardware_buffer_vertices_max * sizeof(float));
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
if ((hardware_buffer_texcoords_count + 6) > hardware_buffer_texcoords_max) {
|
|
|
|
hardware_buffer_texcoords_max = hardware_buffer_texcoords_max * 2 + 6;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_texcoords = (float *)realloc(hardware_buffer_texcoords, hardware_buffer_texcoords_max * sizeof(float));
|
2015-10-30 12:18:44 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
// 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) {
|
|
|
|
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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_img_requires_depthbuffer((hardware_img_struct *)list_get(hardware_img_handles, dst_img));
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +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,
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
dst_hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, dst_img);
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
src_hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, src_img);
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_vertices = (float *)realloc(hardware_buffer_vertices, hardware_buffer_vertices_max * sizeof(float));
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
if ((hardware_buffer_texcoords_count + 6) > hardware_buffer_texcoords_max) {
|
|
|
|
hardware_buffer_texcoords_max = hardware_buffer_texcoords_max * 2 + 6;
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_buffer_texcoords = (float *)realloc(hardware_buffer_texcoords, hardware_buffer_texcoords_max * sizeof(float));
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_MACOSX
|
2022-05-06 04:00:36 +00:00
|
|
|
if (temp_window_title_set == 1) {
|
|
|
|
glutSetWindowTitle((char *)window_title);
|
|
|
|
temp_window_title_set = 0;
|
|
|
|
}
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +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;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
i = -1;
|
|
|
|
static int64 highest_order;
|
|
|
|
highest_order = 0;
|
|
|
|
if (last_i != -1)
|
2022-05-06 04:02:21 +00:00
|
|
|
highest_order = display_frame[last_i].order; // avoid any frames below the current one
|
2022-05-06 04:00:36 +00:00
|
|
|
for (i2 = 0; i2 <= 2; i2++) {
|
2022-05-06 04:02:21 +00:00
|
|
|
if (display_frame[i2].state == DISPLAY_FRAME_STATE__READY && display_frame[i2].order > highest_order) {
|
2022-05-06 04:00:36 +00:00
|
|
|
highest_order = display_frame[i2].order;
|
|
|
|
i = i2;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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 &&
|
2022-05-06 04:02:21 +00:00
|
|
|
(display_frame[i2].state == DISPLAY_FRAME_STATE__DISPLAYING || display_frame[i2].state == DISPLAY_FRAME_STATE__READY))
|
2022-05-06 04:00:36 +00:00
|
|
|
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
|
2022-05-06 04:02:21 +00:00
|
|
|
if (last_rendered_hardware_display_frame_order == last_hardware_display_frame_order) {
|
2022-05-06 04:00:36 +00:00
|
|
|
if (i == last_i) {
|
|
|
|
if (full_screen_set == -1) { // no pending full-screen changes
|
|
|
|
if (os_resize_event == 0) { // no resize events
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifndef DEPENDENCY_GL // we aren't using SUB _GL
|
2022-05-06 04:00:36 +00:00
|
|
|
in_GLUT_DISPLAY_REQUEST = 0;
|
|
|
|
return;
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +00:00
|
|
|
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)
|
2022-05-06 04:02:21 +00:00
|
|
|
last_hardware_command_rendered = first_command_prev_order;
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if ((full_screen == 0) && (full_screen_set == -1)) { // not in (or attempting to enter) full screen
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
display_required_x = display_frame[i].w;
|
|
|
|
display_required_y = display_frame[i].h;
|
|
|
|
static int32 framesize_changed;
|
|
|
|
framesize_changed = 0;
|
2022-05-06 04:02:21 +00:00
|
|
|
if ((display_required_x != resize_snapback_x) || (display_required_y != resize_snapback_y))
|
2022-05-06 04:00:36 +00:00
|
|
|
framesize_changed = 1;
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
resize_auto_ideal_aspect = (float)display_frame[i].w / (float)display_frame[i].h;
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2022-05-06 04:02:21 +00:00
|
|
|
if ((ar != resize_auto_accept_aspect) && (ar != resize_auto_ideal_aspect)) {
|
2022-05-06 04:00:36 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2022-05-06 04:02:21 +00:00
|
|
|
if ((display_y_prev != display_y) && (display_x_prev != display_x)) {
|
|
|
|
if (abs(display_y_prev - display_y) < abs(display_x_prev - display_x)) {
|
2022-05-06 04:00:36 +00:00
|
|
|
x = display_x;
|
|
|
|
y = (float)x / resize_auto_ideal_aspect;
|
|
|
|
} else {
|
|
|
|
y = display_y;
|
|
|
|
x = (float)y * resize_auto_ideal_aspect;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
resize_auto_accept_aspect = (float)x / (float)y;
|
|
|
|
resize_pending = 1;
|
|
|
|
glutReshapeWindow(x, y);
|
|
|
|
glutPostRedisplay();
|
|
|
|
|
|
|
|
goto auto_resized;
|
|
|
|
}
|
|
|
|
} // resize_auto
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if ((display_required_x != display_x) || (display_required_y != display_y)) {
|
2022-05-06 04:00:36 +00:00
|
|
|
if (resize_snapback || framesize_changed) {
|
|
|
|
glutReshapeWindow(display_required_x, display_required_y);
|
|
|
|
glutPostRedisplay();
|
|
|
|
resize_pending = 1;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
auto_resized:;
|
|
|
|
|
|
|
|
} // not in (or attempting to enter) full screen
|
|
|
|
|
|
|
|
// Pseudo-Fullscreen
|
2022-05-06 04:02:21 +00:00
|
|
|
if (!resize_pending) { // avoid switching to fullscreen before resize
|
|
|
|
// operations take effect
|
2022-05-06 04:00:36 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
glutPostRedisplay();
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
full_screen = 0;
|
|
|
|
full_screen_set = -1;
|
|
|
|
} else {
|
|
|
|
if (full_screen == 0) {
|
|
|
|
glutFullScreen();
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
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
|
2018-06-30 15:16:59 +00:00
|
|
|
}//size pending check
|
2022-05-06 04:00:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
// 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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef DEPENDENCY_GL
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
set_view(VIEW_MODE__RESET);
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if (close_program || dont_call_sub_gl || suspend_program || stop_program)
|
2022-05-06 04:00:36 +00:00
|
|
|
goto abort_gl;
|
|
|
|
display_lock_request++;
|
|
|
|
while (display_lock_confirmed < display_lock_request) {
|
2022-05-06 04:02:21 +00:00
|
|
|
if (close_program || dont_call_sub_gl || suspend_program || stop_program)
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif // DEPENDENCY_GL
|
2022-05-06 04:00:36 +00:00
|
|
|
} // 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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
software_screen_hardware_frame = new_hardware_img(display_frame[i].w, display_frame[i].h, display_frame[i].bgra, NULL);
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static hardware_img_struct *f1;
|
2022-05-06 04:02:21 +00:00
|
|
|
f1 = (hardware_img_struct *)list_get(hardware_img_handles, software_screen_hardware_frame);
|
2022-05-06 04:00:36 +00:00
|
|
|
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
|
2022-05-06 04:02:21 +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);
|
2022-05-06 04:00:36 +00:00
|
|
|
hardware_buffer_flush();
|
|
|
|
|
|
|
|
} // level==displayorder_screen
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if (level == displayorder_hardware || level == displayorder_hardware1) {
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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 =
|
2022-05-06 04:02:21 +00:00
|
|
|
(hardware_graphics_command_struct *)list_get(hardware_graphics_command_handles, last_hardware_command_rendered);
|
2022-05-06 04:00:36 +00:00
|
|
|
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;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
// process/skip pending hardware puts before this
|
|
|
|
// frame's order value
|
|
|
|
while (command) {
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_graphics_command_struct *hgc = (hardware_graphics_command_struct *)list_get(hardware_graphics_command_handles, command);
|
2022-05-06 04:00:36 +00:00
|
|
|
if (hgc->order < order) {
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if (hgc->command == HARDWARE_GRAPHICS_COMMAND__FREEIMAGE) {
|
|
|
|
free_hardware_img(hgc->src_img, 847002 + caller_flag);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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
|
2022-05-06 04:00:36 +00:00
|
|
|
clear_depthbuffer(hgc->dst_img);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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;
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
hardware_graphics_command_struct *hgc = (hardware_graphics_command_struct *)list_get(hardware_graphics_command_handles, command);
|
2022-05-06 04:00:36 +00:00
|
|
|
if (hgc == NULL) {
|
|
|
|
|
|
|
|
hardware_graphics_command_struct *hgcx =
|
2022-05-06 04:02:21 +00:00
|
|
|
(hardware_graphics_command_struct *)list_get(hardware_graphics_command_handles, next_hardware_command_to_remove);
|
2022-05-06 04:00:36 +00:00
|
|
|
alert(order);
|
|
|
|
alert(hgcx->order);
|
|
|
|
alert(command);
|
|
|
|
alert("Renderer: Command does not exist.");
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
if (hgc->order == order) {
|
|
|
|
if (first_command_prev_order == 0)
|
|
|
|
first_command_prev_order = command;
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
if (hgc->command == HARDWARE_GRAPHICS_COMMAND__FREEIMAGE && rerender_prev_hardware_frame == 0 && first_hardware_layer_rendered == 0) {
|
2022-05-06 04:00:36 +00:00
|
|
|
free_hardware_img(hgc->src_img, 847003);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
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) {
|
2022-05-06 04:00:36 +00:00
|
|
|
clear_depthbuffer(hgc->dst_img);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
last_hardware_command_rendered = command;
|
|
|
|
if (next_hardware_command_to_remove == 0)
|
2022-05-06 04:02:21 +00:00
|
|
|
next_hardware_command_to_remove = command; //!!!! should be prev to this command
|
2022-05-06 04:00:36 +00:00
|
|
|
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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
black_texture = new_hardware_img(1, 1, &black_pixel, NULL);
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (environment_2d__letterbox == 1) {
|
|
|
|
// vertical stripes
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2022-05-06 04:00:36 +00:00
|
|
|
} else {
|
|
|
|
// horizontal stripes
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2018-06-30 15:16:59 +00:00
|
|
|
}
|
|
|
|
hardware_buffer_flush();
|
2022-05-06 04:00:36 +00:00
|
|
|
} // letterbox
|
|
|
|
|
|
|
|
} // level==5
|
|
|
|
|
|
|
|
} // level!=0
|
|
|
|
} // level loop
|
|
|
|
|
|
|
|
if (requestedKeyboardOverlayImage) {
|
|
|
|
int32 src = requestedKeyboardOverlayImage - HARDWARE_IMG_HANDLE_OFFSET;
|
|
|
|
hardware_img_struct *src_hardware_img;
|
2022-05-06 04:02:21 +00:00
|
|
|
src_hardware_img = (hardware_img_struct *)list_get(hardware_img_handles, src);
|
2022-05-06 04:00:36 +00:00
|
|
|
/*
|
|
|
|
hardware_img_put(0,0,src_hardware_img->w-1,src_hardware_img->h-1,
|
2018-06-30 15:16:59 +00:00
|
|
|
src, 0,
|
|
|
|
0,0,src_hardware_img->w-1,src_hardware_img->h-1,
|
|
|
|
1,0);
|
2022-05-06 04:00:36 +00:00
|
|
|
*/
|
2022-05-06 04:02:21 +00:00
|
|
|
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);
|
2022-05-06 04:00:36 +00:00
|
|
|
hardware_buffer_flush();
|
|
|
|
}
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
last_rendered_hardware_display_frame_order = last_hardware_display_frame_order;
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_GLUT
|
2022-05-06 04:00:36 +00:00
|
|
|
int32 i;
|
|
|
|
int32 handle;
|
|
|
|
handle = mouse_message_queue_first;
|
2022-05-06 04:02:21 +00:00
|
|
|
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GLUT_MouseButton_Down(int button, int x, int y) {
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_GLUT
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
int32 i;
|
|
|
|
int32 handle;
|
|
|
|
handle = mouse_message_queue_first;
|
2022-05-06 04:02:21 +00:00
|
|
|
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
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;
|
2018-06-30 15:16:59 +00:00
|
|
|
static device_struct *d;
|
2022-05-06 04:00:36 +00:00
|
|
|
d = &devices[2]; // mouse
|
|
|
|
|
|
|
|
int32 eventIndex = createDeviceEvent(d);
|
|
|
|
setDeviceEventWheelValue(d, eventIndex, 2, f);
|
2018-06-30 15:16:59 +00:00
|
|
|
commitDeviceEvent(d);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
eventIndex = createDeviceEvent(d);
|
|
|
|
setDeviceEventWheelValue(d, eventIndex, 2, 0);
|
2018-06-30 15:16:59 +00:00
|
|
|
commitDeviceEvent(d);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
} // 4-5
|
|
|
|
} // not 1-3
|
|
|
|
} // core devices required
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GLUT_MOUSE_FUNC(int glut_button, int state, int x, int y) {
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_GLUT
|
2022-05-06 04:00:36 +00:00
|
|
|
if (state == GLUT_DOWN)
|
|
|
|
GLUT_MouseButton_Down(glut_button + 1, x, y);
|
|
|
|
if (state == GLUT_UP)
|
|
|
|
GLUT_MouseButton_Up(glut_button + 1, x, y);
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GLUT_MOTION_FUNC(int x, int y) {
|
|
|
|
|
|
|
|
int32 i, last_i;
|
|
|
|
int32 handle;
|
|
|
|
int32 xrel, yrel;
|
|
|
|
handle = mouse_message_queue_first;
|
2022-05-06 04:02:21 +00:00
|
|
|
mouse_message_queue_struct *queue = (mouse_message_queue_struct *)list_get(mouse_message_queue_handles, handle);
|
2022-05-06 04:00:36 +00:00
|
|
|
|
|
|
|
// message #1
|
|
|
|
last_i = queue->last;
|
|
|
|
i = queue->last + 1;
|
|
|
|
if (i > queue->lastIndex)
|
|
|
|
i = 0; // wrap around
|
|
|
|
if (i == queue->current) {
|
|
|
|
int32 nextIndex = queue->last + 1;
|
|
|
|
if (nextIndex > queue->lastIndex)
|
|
|
|
nextIndex = 0;
|
|
|
|
queue->current = nextIndex;
|
|
|
|
}
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_WINDOWS
|
2022-05-06 04:00:36 +00:00
|
|
|
// Windows calculates relative movement by intercepting WM_INPUT events
|
|
|
|
// instead
|
|
|
|
xrel = 0;
|
|
|
|
yrel = 0;
|
2022-05-06 04:02:21 +00:00
|
|
|
# else
|
2022-05-06 04:00:36 +00:00
|
|
|
xrel = x - queue->queue[queue->last].x;
|
|
|
|
yrel = y - queue->queue[queue->last].y;
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +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);
|
|
|
|
setDeviceEventAxisValue(d, eventIndex, 1, fy);
|
|
|
|
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);
|
|
|
|
setDeviceEventWheelValue(d, eventIndex, 1, fy);
|
|
|
|
commitDeviceEvent(d);
|
|
|
|
|
|
|
|
eventIndex = createDeviceEvent(d);
|
|
|
|
fx = 0;
|
|
|
|
fy = 0;
|
|
|
|
setDeviceEventWheelValue(d, eventIndex, 0, fx);
|
|
|
|
setDeviceEventWheelValue(d, eventIndex, 1, fy);
|
|
|
|
commitDeviceEvent(d);
|
|
|
|
}
|
|
|
|
} // core devices required
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2022-05-06 04:02:21 +00:00
|
|
|
# ifdef QB64_GLUT
|
2022-05-06 04:00:36 +00:00
|
|
|
// 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);
|
|
|
|
}
|
2022-05-06 04:02:21 +00:00
|
|
|
# endif
|
2022-05-06 04:00:36 +00:00
|
|
|
}
|
|
|
|
|
2015-02-20 13:15:27 +00:00
|
|
|
#endif
|