📄 display_window_opengl.cpp
字号:
/* $Id: display_window_opengl.cpp,v 1.62 2004/01/08 20:41:45 harry Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <iostream>
#include <cstdio>
#include "display_window_opengl.h"
#include "input_device_linuxjoystick.h"
#include "input_device_linuxusbmouse.h"
#include "Display/display_precomp.h"
#include "Display/display_window_generic.h"
#include "API/Core/System/keep_alive.h"
#include "graphic_context_opengl.h"
#include "GL/pixel_buffer_opengl_frame.h"
#include "API/Core/System/error.h"
#include "API/Core/System/log.h"
#include "GL/gl_state_checker.h"
#include "Display/X11/input_device_x11keyboard.h"
#include "Display/X11/input_device_x11mouse.h"
#include "API/Core/System/clanstring.h"
#include "API/GL/opengl_window_description.h"
#include "API/GL/opengl_state.h"
#include "API/GL/opengl_wrap.h"
#include "../opengl_window_description_generic.h"
#include <unistd.h>
GLXContext CL_DisplayWindow_OpenGL::share_context = 0;
Display *CL_DisplayWindow_OpenGL::disp = 0;
int CL_DisplayWindow_OpenGL::disp_ref_count = 0;
/////////////////////////////////////////////////////////////////////////////
// Construction:
CL_DisplayWindow_OpenGL::CL_DisplayWindow_OpenGL() :
left_ctrl_down(false), left_alt_down(false), left_shift_down(false),
right_ctrl_down(false), right_alt_down(false), right_shift_down(false),
fullscreen(false), fullscreen_width(0), fullscreen_height(0),
saved_position(0, 0, 0, 0),
context(0),
window(0)
{
gc = CL_GraphicContext(new CL_GraphicContext_OpenGL(this));
}
CL_DisplayWindow_OpenGL::~CL_DisplayWindow_OpenGL()
{
if(fullscreen)
set_windowed();
destroy_window();
}
/////////////////////////////////////////////////////////////////////////////
// Attributes:
int CL_DisplayWindow_OpenGL::get_width() const
{
XWindowAttributes attr;
XGetWindowAttributes(disp, window, &attr);
return attr.width;
}
int CL_DisplayWindow_OpenGL::get_height() const
{
XWindowAttributes attr;
XGetWindowAttributes(disp, window, &attr);
return attr.height;
}
bool CL_DisplayWindow_OpenGL::is_fullscreen() const
{
return fullscreen;
}
bool CL_DisplayWindow_OpenGL::has_focus() const
{
return focus;
}
CL_PixelBuffer &CL_DisplayWindow_OpenGL::get_buffer(int i)
{
if (i == 0) return buffer_front;
else return buffer_back;
}
const CL_PixelBuffer &CL_DisplayWindow_OpenGL::get_buffer(int i) const
{
if (i == 0) return buffer_front;
else return buffer_back;
}
int CL_DisplayWindow_OpenGL::get_buffer_count() const
{
return 2;
}
CL_GraphicContext *CL_DisplayWindow_OpenGL::get_gc()
{
return &gc;
}
Display *CL_DisplayWindow_OpenGL::get_hwnd()
{
return disp;
}
CL_Size CL_DisplayWindow_OpenGL::get_max_surface_size() const
{
CLint max_texture_size;
clGetIntegerv(CL_MAX_TEXTURE_SIZE, &max_texture_size);
return CL_Size(max_texture_size, max_texture_size);
}
/////////////////////////////////////////////////////////////////////////////
// Operations:
void CL_DisplayWindow_OpenGL::create_window(const CL_DisplayWindowDescription &desc)
{
CL_OpenGLWindowDescription_Generic *gl_desc = 0;
gl_desc = dynamic_cast<CL_OpenGLWindowDescription_Generic*>(desc.impl);
fullscreen_width = desc.get_size().width;
fullscreen_height = desc.get_size().height;
XVisualInfo *vi;
Colormap cmap;
if (disp == 0)
{
disp = XOpenDisplay(0);
if (disp == 0) throw CL_Error("Could not open X11 display!");
}
disp_ref_count++;
int gl_attribs_single[] =
{
GLX_RGBA,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 16,
None
};
int gl_attribs[32];
int i = 0;
if( gl_desc )
{
if( gl_desc->rgba ) gl_attribs[i++] = GLX_RGBA;
if( gl_desc->doublebuffer ) gl_attribs[i++] = GLX_DOUBLEBUFFER;
if( gl_desc->stereo ) gl_attribs[i++] = GLX_STEREO;
gl_attribs[i++] = GLX_BUFFER_SIZE;
gl_attribs[i++] = gl_desc->buffer_size;
gl_attribs[i++] = GLX_LEVEL;
gl_attribs[i++] = gl_desc->level;
gl_attribs[i++] = GLX_AUX_BUFFERS;
gl_attribs[i++] = gl_desc->aux_buffers;
gl_attribs[i++] = GLX_RED_SIZE;
gl_attribs[i++] = gl_desc->red_size;
gl_attribs[i++] = GLX_GREEN_SIZE;
gl_attribs[i++] = gl_desc->green_size;
gl_attribs[i++] = GLX_BLUE_SIZE;
gl_attribs[i++] = gl_desc->blue_size;
gl_attribs[i++] = GLX_DEPTH_SIZE;
gl_attribs[i++] = gl_desc->depth_size;
gl_attribs[i++] = GLX_STENCIL_SIZE;
gl_attribs[i++] = gl_desc->stencil_size;
gl_attribs[i++] = GLX_ACCUM_RED_SIZE;
gl_attribs[i++] = gl_desc->accum_red_size;
gl_attribs[i++] = GLX_ACCUM_GREEN_SIZE;
gl_attribs[i++] = gl_desc->accum_green_size;
gl_attribs[i++] = GLX_ACCUM_BLUE_SIZE;
gl_attribs[i++] = gl_desc->accum_blue_size;
gl_attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
gl_attribs[i++] = gl_desc->accum_alpha_size;
gl_attribs[i++] = GLX_ACCUM_RED_SIZE;
gl_attribs[i++] = gl_desc->accum_red_size;
gl_attribs[i++] = None;
}
else
{
gl_attribs[i++] = GLX_RGBA;
gl_attribs[i++] = GLX_DOUBLEBUFFER;
gl_attribs[i++] = GLX_RED_SIZE;
gl_attribs[i++] = 4;
gl_attribs[i++] = GLX_GREEN_SIZE;
gl_attribs[i++] = 4;
gl_attribs[i++] = GLX_BLUE_SIZE;
gl_attribs[i++] = 4;
gl_attribs[i++] = GLX_DEPTH_SIZE;
gl_attribs[i++] = 16;
gl_attribs[i++] = None;
}
// get an appropriate visual
vi = glXChooseVisual(disp, DefaultScreen(disp), gl_attribs);
if (vi == NULL)
{
vi = glXChooseVisual(disp, window, gl_attribs_single);
printf("Requested visual not supported by your OpenGL implementation. Falling back on singlebuffered Visual!\n");
}
// create a GLX context
context = glXCreateContext(disp, vi, share_context, GL_TRUE);
if( share_context == NULL )
share_context = context;
glXGetConfig(disp, vi, GLX_BUFFER_SIZE, &glx_bpp);
// create a color map
cmap = XCreateColormap( disp, RootWindow(disp, vi->screen), vi->visual, AllocNone);
attributes.colormap = cmap;
attributes.border_pixel = 0;
attributes.override_redirect = False;
// create a window in window mode
attributes.event_mask =
ExposureMask |
KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
StructureNotifyMask |
PointerMotionMask |
EnterWindowMask |
LeaveWindowMask |
FocusChangeMask;
window = XCreateWindow(disp, RootWindow(disp, vi->screen),
0, 0, desc.get_size().width, desc.get_size().height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWOverrideRedirect | CWEventMask, &attributes);
XSelectInput(disp, window,
FocusChangeMask | KeyPressMask | KeyReleaseMask
| PropertyChangeMask | StructureNotifyMask |
KeymapStateMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
// set title of window:
set_title(desc.get_title());
// setup size hints:
XSizeHints size_hints;
memset(&size_hints, 0, sizeof(XSizeHints));
size_hints.width = desc.get_size().width;
size_hints.height = desc.get_size().height;
size_hints.base_width = desc.get_size().width;
size_hints.base_height = desc.get_size().height;
size_hints.min_width = size_hints.width;
size_hints.min_height = size_hints.height;
size_hints.max_width = size_hints.width;
size_hints.max_height = size_hints.height;
size_hints.flags = PSize|PBaseSize;
if (!desc.get_allow_resize()) size_hints.flags |= PMinSize | PMaxSize;
XSetWMNormalHints(disp, window, &size_hints);
// handle wm_delete_events if in windowed mode:
Atom wm_delete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
XSetWMProtocols(disp, window, &wm_delete, 1);
// make window visible:
XMapRaised(disp, window);
if (!glXIsDirect(disp, context))
printf("No hardware acceleration available. I hope you got a really fast machine..\n");
// Create input devices for window:
keyboard = CL_InputDevice(new CL_InputDevice_X11Keyboard(this));
mouse = CL_InputDevice(new CL_InputDevice_X11Mouse(this));
get_ic()->clear();
get_ic()->add_keyboard(keyboard);
get_ic()->add_mouse(mouse);
setup_joysticks();
setup_usb_mice();
buffer_front = CL_PixelBuffer(new CL_PixelBuffer_OpenGL_Frame(CL_FRONT, gc));
buffer_back = CL_PixelBuffer(new CL_PixelBuffer_OpenGL_Frame(CL_BACK, gc));
XSync(disp, True);
focus = true;
system_cursor = XCreateFontCursor(disp, XC_left_ptr);
char *data = (char*)malloc(64); // 8x8
memset(data, 0, 64);
XColor black_color;
memset(&black_color, 0, sizeof(black_color));
cursor_bitmap = XCreateBitmapFromData(disp, window, data, 8, 8);
hidden_cursor = XCreatePixmapCursor(disp, cursor_bitmap, cursor_bitmap, &black_color, &black_color, 0,0 );
if (desc.is_fullscreen())
set_fullscreen(desc.get_size().width, desc.get_size().height, desc.get_bpp(), desc.get_refresh_rate());
}
void CL_DisplayWindow_OpenGL::setup_usb_mice()
{
char pathname[256];
bool done = false;
for(int i = 0; !done; ++i)
{
snprintf(pathname, sizeof(pathname), "/dev/input/mouse%d", i);
if (access(pathname, R_OK) == 0)
{
try
{
get_ic()->add_mouse(CL_InputDevice(new CL_InputDevice_LinuxUSBMouse(this, pathname)));
}
catch (CL_Error& err)
{
CL_Log::log("debug", "Mouse Error: %1", err.message);
done = true;
}
}
else
{
CL_Log::log("debug", "Mouse Error: %1: %2", pathname, strerror(errno));
done = true;
}
}
}
void CL_DisplayWindow_OpenGL::setup_joysticks()
{
// This could need some improvments, it doesn't look for
// /dev/input/jsX for example
char pathname[256];
bool done = false;
CL_Log::log("debug", "Setting up joystick");
for(int i = 0; !done; ++i)
{
snprintf(pathname, sizeof(pathname), "/dev/js%d", i);
if (access(pathname, R_OK) == 0)
{
try
{
get_ic()->add_joystick(CL_InputDevice(new CL_InputDevice_LinuxJoystick(pathname)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -