| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "os/osDlibrary.h"
- #include "os/osLog.h"
- #include "util/utilArray.h"
- #include "glx.h"
- namespace GL
- {
- using namespace Torque;
- using namespace GL;
- extern bool gglBindCoreFunctions(DLibrary* dll,GLXExtensionPtrs*);
- void gglBindGLX(::Display* display,int screen,GLXExtensionFlags* glx);
- bool gglBindExtensions(GLExtensionFlags* gl);
- struct GGLContext;
- //-----------------------------------------------------------------------------
- // The OpenGL DLL is shared by all the devices.
- static DLibraryRef _hGL;
- // Unlike WGL, GLX does not require a set of function pointers per
- // context pixel format. All functions in the DLL are bound in a single
- // table and shared by all contexts.
- static GLXExtensionPtrs _LibraryFunctions;
- //-----------------------------------------------------------------------------
- struct GGLDisplay: public _GLDisplay
- {
- ::Display* display;
- int screen;
- GLXExtensionFlags glx; // GLX extension flags
- Array<GGLContext*> contextList;
- };
- #define _hasGLXExtension(display,name) (display->glx.has_##name)
- GLDisplay gglCreateDisplay(::Display* display,int screen)
- {
- // Load and bind DLL functions
- if (!_hGL) {
- static LogCategory log("/Gfx/Device/GL");
- _hGL = LoadLibrary("libGL.so");
- if (!_hGL) {
- log.print("GLDevice: OpenGL dll failed to load");
- return false;
- }
- if (!gglBindCoreFunctions(_hGL.ptr(),&_LibraryFunctions)) {
- log.print("GLDevice: Failed to bind all core functions");
- return false;
- }
- _GGLptr = &_LibraryFunctions;
- log.print("OpenGL library loaded");
- }
- //
- GGLDisplay* dp = new GGLDisplay;
- dp->display = display;
- dp->screen = screen;
- gglBindGLX(display,screen,&dp->glx);
- return dp;
- }
- void gglDeleteDisplay(GLDisplay dp)
- {
- GGLDisplay* display = (GGLDisplay*)dp;
- Assert(!display->contextList.size(),"gglDeleteDisplay: Not all context destroyed");
- delete display;
- }
- //-----------------------------------------------------------------------------
- struct GGLFormat: public _GLFormat {
- GLFormatInfo mode;
- U32 pformat;
- };
- static bool _getFBConfig(GGLDisplay* display,U32 pformat,GLXFBConfig& config)
- {
- // Get config info from format ID
- int attributes[] = { GLX_FBCONFIG_ID, pformat, None };
- int count = 0;
- GLXFBConfig* configList = glXChooseFBConfig(display->display,
- display->screen,attributes,&count);
- if (!count)
- return false;
- config = *configList;
- XFree(configList);
- return true;
- }
- GLFormat gglSelectFormat(GLDisplay dp,GLFormatInfo& mode)
- {
- GGLDisplay* display = (GGLDisplay*)dp;
- U32 pformat;
- if (!_hasGLXExtension(display,GLX_VERSION_1_3)) {
- // Find GL compatible X visual using 1.2 interface.
- // 1.2 or earlier does not include pbuffer support.
- if (mode.target != GLFormatInfo::Window)
- return 0;
- int attributes[] = {
- GLX_RGBA,
- GLX_RED_SIZE, mode.red,
- GLX_BLUE_SIZE, mode.blue,
- GLX_GREEN_SIZE, mode.green,
- GLX_DEPTH_SIZE, mode.z,
- GLX_ALPHA_SIZE, mode.alpha,
- GLX_STENCIL_SIZE, mode.stencil,
- GLX_DOUBLEBUFFER, true,
- GLX_DOUBLEBUFFER,
- None
- };
- XVisualInfo* visual = glXChooseVisual(display->display, display->screen, attributes);
- if (!visual) {
- static LogCategory log("/Gfx/Device/GL");
- log.print("GGLContext: Could not get an accelerated visual");
- return 0;
- }
- pformat = visual->visualid;
- XFree(visual);
- }
- else {
- // Find GL compatible X visual using 1.3 interface.
- int attributes[] = {
- GLX_DRAWABLE_TYPE, (mode.target == GLFormatInfo::Buffer)?
- GLX_PBUFFER_BIT: GLX_WINDOW_BIT,
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_RED_SIZE, mode.red,
- GLX_BLUE_SIZE, mode.blue,
- GLX_GREEN_SIZE, mode.green,
- GLX_DEPTH_SIZE, mode.z,
- GLX_ALPHA_SIZE, mode.alpha,
- GLX_STENCIL_SIZE, mode.stencil,
- GLX_DOUBLEBUFFER, true,
- None
- };
- int count = 0;
- GLXFBConfig* configList = glXChooseFBConfig(display->display,
- display->screen,attributes,&count);
- if (!count)
- return 0;
- // Return the config ID
- int xid;
- glXGetFBConfigAttrib(display->display,configList[0],GLX_FBCONFIG_ID,&xid);
- XFree(configList);
- pformat = xid;
- }
- if (pformat) {
- GGLFormat* format = new GGLFormat;
- format->pformat = pformat;
- format->mode = mode;
- return format;
- }
- return 0;
- }
- bool gglFormatInfo(GLDisplay display,GLFormat pformat,GLFormatInfo& mode)
- {
- return 0;
- }
- bool gglAreCompatible(GLFormat,GLFormat)
- {
- return false;
- }
- void gglDeleteFormat(GLFormat fp)
- {
- GGLFormat* format = (GGLFormat*)fp;
- delete format;
- }
- XVisualInfo* gglGetFormatVisual(GLDisplay dp,GLFormat fp)
- {
- GGLDisplay* display = (GGLDisplay*)dp;
- GGLFormat* format = (GGLFormat*)fp;
- if (!_hasGLXExtension(display,GLX_VERSION_1_3)) {
- // Format is a visual id
- int count;
- XVisualInfo match;
- match.visualid = format->pformat;
- return XGetVisualInfo(display->display,VisualIDMask,&match,&count);
- }
- else {
- // Format is an FBConfig id
- GLXFBConfig config;
- if (!_getFBConfig(display,format->pformat,config))
- return 0;
- return glXGetVisualFromFBConfig(display->display,config);
- }
- }
- //-----------------------------------------------------------------------------
- struct GGLSurface: public _GLSurface {
- enum Type {
- Window, PBuffer,
- } type;
- GGLDisplay* display;
- GLXDrawable drawable; // Used with GLX 1.3 interface
- ::Window window; // Used with GLX 1.2 interface
- };
- GLSurface gglCreateSurface(GLDisplay dp,::Window hwin,GLFormat fp)
- {
- GGLDisplay* display = (GGLDisplay*)dp;
- GGLFormat* format = (GGLFormat*)fp;
- GGLSurface* surface = 0;
- if (!_hasGLXExtension(display,GLX_VERSION_1_3)) {
- // Return our own GGL surface rep.
- surface = new GGLSurface;
- surface->type = GGLSurface::Window;
- surface->display = display;
- surface->drawable = 0;
- surface->window = hwin;
- }
- else {
- // Get config info from format ID
- GLXFBConfig config;
- if (!_getFBConfig(display,format->pformat,config))
- return 0;
- // Create GLX window
- GLXWindow window = glXCreateWindow(display->display,config,hwin,0);
- if (!window) {
- GLenum error = glGetError();
- static LogCategory log("/Gfx/Device/GL");
- log.print(format("Create window error: %d",error));
- return 0;
- }
- // Return our own GGL surface rep.
- surface = new GGLSurface;
- surface->type = GGLSurface::Window;
- surface->display = display;
- surface->drawable = window;
- surface->window = 0;
- }
- return surface;
- }
- bool gglGetSurfaceSize(GLSurface sp,Vector2I& size)
- {
- GGLSurface* surface = (GGLSurface*)sp;
- if (surface->type != GGLSurface::Window)
- return false;
- if (!_hasGLXExtension(surface->display,GLX_VERSION_1_3)) {
- size.x = 300; size.y = 300;
- }
- else {
- glXQueryDrawable(surface->display->display,surface->drawable,
- GLX_WIDTH,(U32*)&size.x);
- glXQueryDrawable(surface->display->display,surface->drawable,
- GLX_HEIGHT,(U32*)&size.y);
- }
- return true;
- }
- void gglDeleteSurface(GLSurface sp)
- {
- GGLSurface* surface = (GGLSurface*)sp;
- if (surface->type = GGLSurface::Window) {
- glXDestroyWindow(surface->display->display,surface->drawable);
- delete surface;
- }
- }
- //-----------------------------------------------------------------------------
- struct GGLContext: public _GLContext
- {
- GGLDisplay* display;
- GLXContext context;
- GLExtensionFlags glf; // GL has extension flags
- };
- GLContext gglCreateContext(GLDisplay dp,GLFormat fp)
- {
- GGLDisplay* display = (GGLDisplay*)dp;
- GGLFormat* format = (GGLFormat*)fp;
- GGLContext* context = 0;
- GLXContext ctx,share = display->contextList.size()?
- display->contextList[0]->context: 0;
- if (!_hasGLXExtension(display,GLX_VERSION_1_3)) {
- // Get visual from format id.
- int count;
- XVisualInfo match;
- match.visualid = format->pformat;
- XVisualInfo* visual = XGetVisualInfo(display->display,VisualIDMask,&match,&count);
- ctx = glXCreateContext(display->display,visual,share,true);
- XFree(visual);
- }
- else {
- // Get FBConfig from format id
- GLXFBConfig config;
- if (!_getFBConfig(display,format->pformat,config))
- return 0;
- // Need to share contexts...
- ctx = glXCreateNewContext(display->display,config,
- GLX_RGBA_TYPE,share,true);
- }
- if (ctx) {
- context = new GGLContext;
- context->context = ctx;
- context->display = display;
- display->contextList.pushBack(context);
- return context;
- }
- return 0;
- }
- void gglDeleteContext(GLContext ctx)
- {
- GGLContext* context = (GGLContext*)ctx;
- glXDestroyContext(context->display->display,context->context);
- erase(context->display->contextList,context);
- delete context;
- }
- bool gglMakeCurrent(GLSurface sp,GLContext ctx)
- {
- GGLSurface* surface = (GGLSurface*)sp;
- GGLContext* context = (GGLContext*)ctx;
- if (!_hasGLXExtension(surface->display,GLX_VERSION_1_3)) {
- if (!glXMakeCurrent(surface->display->display,
- surface->window,context->context))
- return false;
- }
- else
- if (!glXMakeContextCurrent(surface->display->display,
- surface->drawable,surface->drawable,context->context))
- return false;
- // The first time a context is made current we need to
- // check which extensions are valid.
- if (!context->glf.bound)
- gglBindExtensions(&context->glf);
- _GGLflag = &context->glf;
- return true;
- }
- void gglSwapBuffers(GLSurface sp)
- {
- GGLSurface* surface = (GGLSurface*)sp;
- if (!_hasGLXExtension(surface->display,GLX_VERSION_1_3))
- glXSwapBuffers(surface->display->display,surface->window);
- else
- glXSwapBuffers(surface->display->display,surface->drawable);
- }
- //-----------------------------------------------------------------------------
- GLSurface gglCreatePBufferSurface(GLDisplay display,U32 width,U32 height,bool cubeMap,GLFormat pformat)
- {
- return 0;
- }
- bool gglBindPBufferSurface(GLSurface sp,U32 target)
- {
- return 0;
- }
- bool gglReleasePBufferSurface(GLSurface sp,U32 target)
- {
- return 0;
- }
- bool gglSetPbufferTarget(GLSurface sp,U32 mip,U32 face)
- {
- return 0;
- }
- } // Namespace
|