mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 08:34:40 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
413
Engine/source/gfx/gl/ggl/x11/glx.cpp
Normal file
413
Engine/source/gfx/gl/ggl/x11/glx.cpp
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue