Loading modern OpenGL context for Linux (GLX);

Canoi 1587f3d4 fd09c00f

Changed files
+175 -1
+175 -1
bite.c
··· 33 33 #else 34 34 Display* display; 35 35 Window handle; 36 + Colormap map; 37 + 38 + GLXFBConfig fbconf; 36 39 #endif 37 40 }; 38 41 ··· 91 94 #define WGL_FULL_ACCELERATION_ARB 0x2027 92 95 #define WGL_TYPE_RGBA_ARB 0x202B 93 96 #else 97 + typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); 98 + #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 99 + #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 94 100 #endif 95 101 96 102 #define DEFINE_GL(ret, name, ...)\ ··· 579 585 ReleaseDC(dummy_window, dummy_dc); 580 586 DestroyWindow(dummy_window); 581 587 } 588 + #else 589 + static BITE_BOOL is_extension_supported(const char *extList, const char *extension) { 590 + const char *start; 591 + const char *where, *terminator; 592 + 593 + /* Extension names should not have spaces. */ 594 + where = strchr(extension, ' '); 595 + if (where || *extension == '\0') 596 + return BITE_FALSE; 597 + 598 + /* It takes a bit of care to be fool-proof about parsing the 599 + OpenGL extensions string. Don't be fooled by sub-strings, 600 + etc. */ 601 + for (start=extList;;) { 602 + where = strstr(start, extension); 603 + 604 + if (!where) 605 + break; 606 + 607 + terminator = where + strlen(extension); 608 + 609 + if ( where == start || *(where - 1) == ' ' ) 610 + if ( *terminator == ' ' || *terminator == '\0' ) 611 + return BITE_TRUE; 612 + 613 + start = terminator; 614 + } 615 + } 582 616 #endif 583 617 584 618 BITE_RESULT _init_context(be_Context* ctx, const be_Config* conf) { ··· 638 672 639 673 ShowWindow(handle, SW_SHOWDEFAULT); 640 674 UpdateWindow(handle); 675 + #elif (__EMSCRIPTEN__) 676 + #else 677 + Display* dpy; 678 + Window handle; 679 + dpy = XOpenDisplay(NULL); 680 + if (dpy == NULL) { 681 + fprintf(stderr, "Could not open X11 display\n"); 682 + return BITE_ERROR; 683 + } 684 + int scrId = DefaultScreen(dpy); 685 + 686 + static int visual_attribs[] = 687 + { 688 + GLX_X_RENDERABLE , True, 689 + GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, 690 + GLX_RENDER_TYPE , GLX_RGBA_BIT, 691 + GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, 692 + GLX_RED_SIZE , 8, 693 + GLX_GREEN_SIZE , 8, 694 + GLX_BLUE_SIZE , 8, 695 + GLX_ALPHA_SIZE , 8, 696 + GLX_DEPTH_SIZE , 24, 697 + GLX_STENCIL_SIZE , 8, 698 + GLX_DOUBLEBUFFER , True, 699 + //GLX_SAMPLE_BUFFERS , 1, 700 + //GLX_SAMPLES , 4, 701 + None 702 + }; 703 + 704 + GLint major, minor; 705 + glXQueryVersion(dpy, &major, &minor); 706 + if ((major == 1 && minor < 3) || (major < 1)) { 707 + fprintf(stderr, "Invalid GLX version\n"); 708 + XCloseDisplay(dpy); 709 + return BITE_ERROR; 710 + } 711 + 712 + int fbcount; 713 + GLXFBConfig* fbc = glXChooseFBConfig(dpy, scrId, visual_attribs, &fbcount); 714 + if (!fbc) { 715 + fprintf(stderr, "Failed to retrieve a framebuffer config\n"); 716 + return BITE_ERROR; 717 + } 718 + 719 + int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; 720 + 721 + int i; 722 + for (i=0; i<fbcount; ++i) { 723 + XVisualInfo *vi = glXGetVisualFromFBConfig(dpy, fbc[i]); 724 + if ( vi ) 725 + { 726 + int samp_buf, samples; 727 + glXGetFBConfigAttrib(dpy, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); 728 + glXGetFBConfigAttrib(dpy, fbc[i], GLX_SAMPLES, &samples); 729 + 730 + // printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," 731 + // " SAMPLES = %d\n", 732 + // i, vi -> visualid, samp_buf, samples ); 733 + 734 + if ( best_fbc < 0 || samp_buf && samples > best_num_samp ) 735 + best_fbc = i, best_num_samp = samples; 736 + if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp ) 737 + worst_fbc = i, worst_num_samp = samples; 738 + } 739 + XFree( vi ); 740 + } 741 + GLXFBConfig bestFbc = fbc[best_fbc]; 742 + XFree(fbc); 743 + 744 + XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, bestFbc); 745 + XSetWindowAttributes swa; 746 + Colormap map; 747 + swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); 748 + swa.background_pixmap = None; 749 + swa.border_pixel = 0; 750 + swa.event_mask = ExposureMask | StructureNotifyMask; 751 + 752 + handle = XCreateWindow( 753 + dpy, RootWindow(dpy, vi->screen), 754 + 0, 0, conf->window.width, conf->window.height, 755 + 0, vi->depth, InputOutput, 756 + vi->visual, 757 + CWBorderPixel | CWColormap | CWEventMask, &swa 758 + ); 759 + 760 + if (!handle) { 761 + fprintf(stderr, "Failed to create X11 window\n"); 762 + return BITE_ERROR; 763 + } 764 + 765 + XFree(vi); 766 + XStoreName(dpy, handle, conf->window.title); 767 + XMapWindow(dpy, handle); 768 + 769 + window->handle = handle; 770 + window->display = dpy; 771 + window->map = swa.colormap; 772 + window->fbconf = bestFbc; 641 773 #endif 642 774 window->width = conf->window.width; 643 775 window->height = conf->window.height; ··· 721 853 _close_gl(); 722 854 #elif defined(__EMSCRIPTEN__) 723 855 #else 856 + Display* dpy = window->display; 857 + int scrId = DefaultScreen(dpy); 858 + const char* glxExts = glXQueryExtensionsString(dpy, scrId); 859 + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; 860 + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB"); 861 + 862 + GLXContext ctx = 0; 863 + 864 + if (!glXCreateContextAttribsARB) { 865 + fprintf(stderr, "Failed to load glXCreateContextAttribsARB(), loading legacy OpenGL context\n"); 866 + ctx = glXCreateNewContext(dpy, window->fbconf, GLX_RGBA_TYPE, 0, True); 867 + } else { 868 + int context_attribs[] = { 869 + GLX_CONTEXT_MAJOR_VERSION_ARB, 2, 870 + GLX_CONTEXT_MINOR_VERSION_ARB, 1, 871 + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 872 + None 873 + }; 874 + 875 + ctx = glXCreateContextAttribsARB(dpy, window->fbconf, 0, True, context_attribs); 876 + XSync(dpy, False); 877 + if (!ctx) { 878 + fprintf(stderr, "Failed to create 3.0 OpenGL context\n"); 879 + XDestroyWindow(dpy, window->handle); 880 + XFreeColormap(dpy, window->map); 881 + XCloseDisplay(dpy); 882 + return BITE_ERROR; 883 + } 884 + glXMakeCurrent(dpy, window->handle, ctx); 885 + render->gl_context = ctx; 886 + if (_load_gl() != BITE_OK) { 887 + fprintf(stderr, "Failed to init OpenGL loader\n"); 888 + XDestroyWindow(dpy, window->handle); 889 + XFreeColormap(dpy, window->map); 890 + XCloseDisplay(dpy); 891 + return BITE_ERROR; 892 + } 893 + _setup_gl(); 894 + _close_gl(); 895 + } 724 896 #endif 725 897 return BITE_OK; 726 898 } ··· 1027 1199 #if defined(__APPLE__) || defined(__HAIKU__) 1028 1200 return BITE_OK; 1029 1201 #else 1030 - _proc_address = (void*(*)(const i8*))dlsym(_gl_sym, "glXGetProcAddress"); 1202 + _proc_address = (void*(*)(const char*))dlsym(_gl_sym, "glXGetProcAddress"); 1031 1203 return _proc_address != NULL ? BITE_OK : BITE_ERROR; 1032 1204 #endif 1033 1205 break; ··· 1098 1270 GET_GL_PROC(glLinkProgram); 1099 1271 GET_GL_PROC(glGetProgramiv); 1100 1272 GET_GL_PROC(glGetProgramInfoLog); 1273 + 1274 + fprintf(stdout, "glCreateProgram: %p\n", glCreateProgram); 1101 1275 } 1102 1276 1103 1277 BITE_BOOL _load_procs(void) {