1
1
Fork 0
mirror of https://github.com/QB64Official/qb64.git synced 2024-07-03 10:01:21 +00:00
qb64/internal/c/libqb/gui.h
2019-04-14 15:33:19 -03:00

290 lines
12 KiB
C

//Common
int32 requestedKeyboardOverlayImage=0;
#ifndef QB64_GUI //begin stubs
//STUB: simulate generating a hardware surface
int32 new_hardware_img(int32 x, int32 y, uint32 *pixels, int32 flags){
//create hardware img
int32 handle;
hardware_img_struct* hardware_img;
handle=list_add(hardware_img_handles);
hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,handle);
hardware_img->w=x;
hardware_img->h=y;
hardware_img->dest_context_handle=0;
hardware_img->depthbuffer_handle=0;
hardware_img->pending_commands=0;
hardware_img->remove=0;
hardware_img->alpha_disabled=0;
hardware_img->depthbuffer_mode=DEPTHBUFFER_MODE__ON;
hardware_img->valid=1;
hardware_img->source_state.PO2_fix=PO2_FIX__OFF;
hardware_img->source_state.texture_wrap=TEXTURE_WRAP_MODE__UNKNOWN;
hardware_img->source_state.smooth_stretched=SMOOTH_MODE__UNKNOWN;
hardware_img->source_state.smooth_shrunk=SMOOTH_MODE__UNKNOWN;
if (flags&NEW_HARDWARE_IMG__BUFFER_CONTENT){
hardware_img->texture_handle=0;
if (flags&NEW_HARDWARE_IMG__DUPLICATE_PROVIDED_BUFFER){
hardware_img->software_pixel_buffer=NULL;
}else{
free(pixels);//the buffer was meant to be consumed, so we just free it immediately
hardware_img->software_pixel_buffer=NULL;
}
}
return handle;
}
#else //end stubs
int32 force_NPO2_fix=0;//This should only be set to 1 for debugging QB64
uint32 *NPO2_buffer=(uint32*)malloc(4);
int32 NPO2_buffer_size_in_pixels=1;
uint32 *NPO2_texture_generate(int32 *px, int32 *py, uint32 *pixels){
int32 ox=*px;
int32 oy=*py;
int32 nx=1;
int32 ny=1;
//assume not negative & not 0
while ((ox&1)==0){
ox>>=1;
nx<<=1;
}
if (ox!=1){//x is not a power of 2
while (ox!=0){
ox>>=1;
nx<<=1;
}
nx<<1;
}
while ((oy&1)==0){
oy>>=1;
ny<<=1;
}
if (oy!=1){//y is not a power of 2
while (oy!=0){
oy>>=1;
ny<<=1;
}
ny<<1;
}
//reset original values
ox=*px;
oy=*py;
if (nx==ox&&ny==oy){ //no action required
return pixels;
}
int32 size_in_pixels=nx*ny;
if (size_in_pixels>NPO2_buffer_size_in_pixels){
NPO2_buffer=(uint32*)realloc(NPO2_buffer,size_in_pixels*4);
NPO2_buffer_size_in_pixels=size_in_pixels;
}
//copy source NPO2 rectangle into destination PO2 rectangle
if (nx==ox){ //can copy as a single block
memcpy(NPO2_buffer,pixels,ox*oy*4);
}else{
uint32 *dst_pixel_offset=NPO2_buffer;
uint32 *src_pixel_offset=pixels;
while (oy--){
memcpy(dst_pixel_offset,src_pixel_offset,ox*4);
dst_pixel_offset+=nx;
src_pixel_offset+=ox;
}
oy=*py;
}
//tidy edges - extend the right-most column and bottom-most row to avoid pixel/color bleeding
//rhs column
if (ox!=nx){
for (int y=0;y<oy;y++){
NPO2_buffer[ox+nx*y]=NPO2_buffer[ox+nx*y-1];
}
}
//bottom row + 1 pixel for corner
if (oy!=ny){
for (int x=0;x<(ox+1);x++){
NPO2_buffer[nx*oy+x]=NPO2_buffer[nx*oy+x-nx];
}
}
//int maxtexsize;
//glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize);
//alert(maxtexsize);
//alert(nx);
//alert(ny);
*px=nx;
*py=ny;
return NPO2_buffer;
}
int32 new_texture_handle(){
GLuint texture=0;
glGenTextures(1,&texture);
return (int32)texture;
}
int32 new_hardware_img(int32 x, int32 y, uint32 *pixels, int32 flags){
//note: non power-of-2 dimensioned textures are supported on modern 3D cards and
// even on some older cards, as long as mip-mapping is not being used
// therefore, no attempt is made to convert the non-power-of-2 SCREEN sizes via software
// to avoid the performance hit this would incur
//create hardware img
int32 handle;
hardware_img_struct* hardware_img;
handle=list_add(hardware_img_handles);
hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,handle);
hardware_img->w=x;
hardware_img->h=y;
hardware_img->dest_context_handle=0;
hardware_img->depthbuffer_handle=0;
hardware_img->pending_commands=0;
hardware_img->remove=0;
hardware_img->alpha_disabled=0;
hardware_img->depthbuffer_mode=DEPTHBUFFER_MODE__ON;
hardware_img->valid=1;
hardware_img->source_state.PO2_fix=PO2_FIX__OFF;
hardware_img->source_state.texture_wrap=TEXTURE_WRAP_MODE__UNKNOWN;
hardware_img->source_state.smooth_stretched=SMOOTH_MODE__UNKNOWN;
hardware_img->source_state.smooth_shrunk=SMOOTH_MODE__UNKNOWN;
if (flags&NEW_HARDWARE_IMG__BUFFER_CONTENT){
hardware_img->texture_handle=0;
if (flags&NEW_HARDWARE_IMG__DUPLICATE_PROVIDED_BUFFER){
hardware_img->software_pixel_buffer=(uint32*)malloc(x*y*4);
memcpy(hardware_img->software_pixel_buffer,pixels,x*y*4);
}else{
hardware_img->software_pixel_buffer=pixels;
}
}else{
hardware_img->software_pixel_buffer=NULL;
hardware_img->texture_handle=new_texture_handle();
glBindTexture (GL_TEXTURE_2D, hardware_img->texture_handle);
//non-power of 2 dimensions fallback support
static int glerrorcode;
glerrorcode=glGetError();//clear any previous errors
if (force_NPO2_fix==0) glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
glerrorcode=glGetError();
if (glerrorcode!=0||force_NPO2_fix==1){
int32 nx=x,ny=y;
uint32 *npixels=NPO2_texture_generate(&nx,&ny,pixels);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_BGRA, GL_UNSIGNED_BYTE,npixels);
hardware_img->source_state.PO2_fix=PO2_FIX__EXPANDED;
hardware_img->PO2_w=nx;
hardware_img->PO2_h=ny;
glerrorcode=glGetError();
if (glerrorcode){
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, x, y, GL_BGRA, GL_UNSIGNED_BYTE, pixels );
glerrorcode=glGetError();
if (glerrorcode){
alert("gluBuild2DMipmaps failed");
alert(glerrorcode);
}
hardware_img->source_state.PO2_fix=PO2_FIX__MIPMAPPED;
hardware_img->PO2_w=x;
hardware_img->PO2_h=y;
}
}
set_render_source(INVALID_HARDWARE_HANDLE);
}
return handle;
}
void hardware_img_buffer_to_texture(int32 handle){
static hardware_img_struct* hardware_img;
hardware_img=(hardware_img_struct*)list_get(hardware_img_handles,handle);
if (hardware_img->texture_handle==0){
hardware_img->texture_handle=new_texture_handle();
glBindTexture (GL_TEXTURE_2D, hardware_img->texture_handle);
//non-power of 2 dimensions fallback support
static int glerrorcode;
glerrorcode=glGetError();//clear any previous errors
if (force_NPO2_fix==0) glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, hardware_img->w, hardware_img->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, hardware_img->software_pixel_buffer);
glerrorcode=glGetError();
if (glerrorcode!=0||force_NPO2_fix==1){
hardware_img->source_state.PO2_fix=PO2_FIX__EXPANDED;
int32 x=hardware_img->w;
int32 y=hardware_img->h;
uint32 *pixels=NPO2_texture_generate(&x,&y,hardware_img->software_pixel_buffer);
hardware_img->PO2_w=x;
hardware_img->PO2_h=y;
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_BGRA, GL_UNSIGNED_BYTE,pixels);
glerrorcode=glGetError();
if (glerrorcode){
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, hardware_img->w, hardware_img->h, GL_BGRA, GL_UNSIGNED_BYTE, hardware_img->software_pixel_buffer);
glerrorcode=glGetError();
if (glerrorcode){
alert("gluBuild2DMipmaps failed");
alert(glerrorcode);
}
hardware_img->source_state.PO2_fix=PO2_FIX__MIPMAPPED;
hardware_img->PO2_w=hardware_img->w;
hardware_img->PO2_h=hardware_img->h;
}
}
free(hardware_img->software_pixel_buffer);
hardware_img->software_pixel_buffer=NULL;//2015 critical bug fix
set_render_source(INVALID_HARDWARE_HANDLE);
}
}
void hardware_img_requires_depthbuffer(hardware_img_struct* hardware_img){
if (hardware_img->depthbuffer_handle==0){
//inspiration... http://www.opengl.org/wiki/Framebuffer_Object_Examples#Color_texture.2C_Depth_texture
static GLuint depth_tex;
#ifndef QB64_GLES
glGenTextures(1, &depth_tex);
glBindTexture(GL_TEXTURE_2D, depth_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, hardware_img->w, hardware_img->h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_tex, 0/*mipmap level*/);
#else
glGenRenderbuffers(1, &depth_tex);
glBindRenderbuffer(GL_RENDERBUFFER, depth_tex);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, hardware_img->w, hardware_img->h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_tex);
#endif
//NULL means reserve texture memory, but texels are undefined
glClear(GL_DEPTH_BUFFER_BIT);
hardware_img->depthbuffer_handle=depth_tex;
set_render_source(INVALID_HARDWARE_HANDLE);
}
}
#endif