Programação com OpenGL/Classe GLXWindow: diferenças entre revisões

[edição verificada][edição verificada]
Conteúdo apagado Conteúdo adicionado
Linha 57:
 
A parte mais importante e complicado de uma classe de janela é código que cria a janela OpenGL, A primeira coisa que pegaremos uma manipulador(handle) de tela usando <code>XopenDisplay</code>, que passaremos o valor zero(ou NULL) isto vai pegar qualquer display, que é configurado no ambiente de variável de DISPLAY( que normalmente é que você esta usando para ver sua Area de trabalho!)
 
<source lang="cpp">
m_display = XOpenDisplay(0); //Open default display
if (m_display == NULL)
{
std::cerr << "Could not open the display" << std::endl;
return false;
}
</source>
 
Assim, tornamos ela o padrão da tela, e se haver algum erro não registrado é retornado falso para indicar um erro na criação da janela. Depois, nós pegaremos um manipulador que identificara o padrão de exibição na tela.
 
<source lang="cpp">
m_screenID = DefaultScreen(m_display); //Get the default screen id
</source>
 
Agora vamos pegar uma lista de modos de tela disponíveis, e veremos se algum é o que queremos. se não teremos que recorrer a um erro:
<source lang="cpp">
XF86VidModeModeInfo **modes;
if (!XF86VidModeGetAllModeLines(m_display, m_screenID, &modeNum, &modes))
{
std::cerr << "Could not query the video modes" << std::endl;
return false;
}
int bestMode = -1;
for (int i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == width) &&
(modes[i]->vdisplay == height))
{
bestMode = i;
}
}
if (bestMode == -1)
{
std::cerr << "Could not find a suitable graphics mode" << std::endl;
return false;
}
</source>
 
Depois, nós guardaremos o modo de tela que melhor combina, nós pediremos um double buffer de janela com 16 bit depthbuffer:
<source lang="cpp">
int doubleBufferedAttribList [] = {
GLX_RGBA, GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DEPTH_SIZE, 16,
None
};
XVisualInfo* vi = NULL;
//Attempt to create a double buffered window
vi = glXChooseVisual(m_display, m_screenID, doubleBufferedAttribList);
if (vi == NULL)
{
std::cerr << "Could not create a double buffered window" << std::endl;
return false;
}
</source>
 
O próximo passo é a criação de um contexto OpenGL 2.1, assim possamos em vez de solicitar uma GL3. Estes são alguns passos que temos que dar em janelas:
<source lang="cpp">
//Create a GL 2.1 context
GLXContext gl2Context = glXCreateContext(m_display, vi, 0, GL_TRUE);
if (gl2Context == NULL)
{
std::cerr << "Could not create a GL 2.1 context, please check your graphics drivers" << std::endl;
return false;
}
//Get a pointer to the GL 3.0 context creation
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)"glXCreateContextAttribsARB");
if (glXCreateContextAttribs == NULL)
{
std::cerr << "OpenGL 3.0 is not supported, falling back to 2.1" << std::endl;
m_glContext = gl2Context;
m_GL3Supported = false;
}
else
{
//Create a GL 3.0 context
int attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,//we want a 3.0 context
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
0 //zero indicates the end of the array
};
m_glContext = glXCreateContextAttribs(m_display, framebufferConfig, 0, true, &attribs[0]);
glXDestroyContext(m_display, gl2Context); //We can destroy the GL 2.0 context once the 3.0 one has bene created
m_GL3Supported = true;
}
</source>
 
Se o OpenGL 3.0 não for suportados, nós vamos setar uma flag assim podemos usar um substituto com shader 2.1
 
Agora nós temos informaçãoes suficentes para criar uma janela, lembre que nós guardaremos o melhor modo de tela que podemos encontrar? Usamos essa abaixo depois de configurar algumas definições de configuração da janela:
<source lang="cpp">
Colormap cmap = XCreateColormap(m_display, RootWindow(m_display, vi->screen),vi->visual, AllocNone);
m_XSetAttr.colormap = cmap;
m_XSetAttr.border_pixel = 0;
m_XSetAttr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
StructureNotifyMask;
m_XSetAttr.override_redirect = False;
unsigned long windowAttributes = CWBorderPixel | CWColormap | CWEventMask;
if (fullscreen)
{
windowAttributes = CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
XF86VidModeSwitchToMode(m_display, m_screenID, modes[bestMode]);
XF86VidModeSetViewPort(m_display, m_screenID, 0, 0);
m_XSetAttr.override_redirect = True;
}
m_XWindow = XCreateWindow(m_display, RootWindow(m_display, vi->screen),
0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &m_XSetAttr);
</source>
 
Finalmente, vamos colocar um titulo na janela, e se estiver em tela cheia colocaremos um cursor:
<source lang="cpp">
if (fullscreen)
{
XWarpPointer(m_display, None, m_XWindow, 0, 0, 0, 0, 0, 0);
XMapRaised(m_display, m_XWindow);
XGrabKeyboard(m_display, m_XWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(m_display, m_XWindow, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, m_XWindow, None, CurrentTime);
m_isFullscreen = true;
}
else
{
Atom wmDelete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(m_display, m_XWindow, &wmDelete, 1);
XSetStandardProperties(m_display, m_XWindow, title.c_str(), None, NULL, NULL, 0, NULL);
XMapRaised(m_display, m_XWindow);
}
XFree(modes);
</source>
 
Na ultima linha acima libera a memoria para os modos de tela que nós encontramos por ultimo.
 
== Destruindo a Janela ==
 
É muito simples aqui está o código:
<source lang="cpp">
void SimpleGLXWindow::destroy()
{
m_mouse->showCursor(true);
if (m_glContext)
{
glXMakeCurrent(m_display, None, NULL);
glXDestroyContext(m_display, m_glContext);
m_glContext = NULL;
}
if (m_isFullscreen)
{
XF86VidModeSwitchToMode(m_display, m_screenID, &m_XF86DeskMode);
XF86VidModeSetViewPort(m_display, m_screenID, 0, 0);
}
XCloseDisplay(m_display);
}
</source>
 
Basicamente nós garantimos que o cursos está visível,depois nós destruimos o contexto OpenGL e finalmente voltamos a modo de tela que esta antes. Nós liberamos nosso manipulador na tela e destruímos complemente a janela.