SFML/examples/X11/X11.cpp

237 lines
6.9 KiB
C++

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/OpenGL.hpp>
#include <X11/Xlib-xcb.h>
#include <iostream>
#include <cmath>
////////////////////////////////////////////////////////////
/// Initialize OpenGL states into the specified view
///
/// \param Window Target window to initialize
///
////////////////////////////////////////////////////////////
void initialize(sf::Window& window)
{
// Activate the window
window.setActive();
// Setup OpenGL states
// Set color and depth clear value
glClearDepth(1.f);
glClearColor(0.f, 0.5f, 0.5f, 0.f);
// Enable Z-buffer read and write
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
// Setup a perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
static const double pi = 3.141592654;
GLdouble extent = std::tan(90.0 * pi / 360.0);
glFrustum(-extent, extent, -extent, extent, 1.0, 500.0);
// Enable position and texture coordinates vertex components
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
}
////////////////////////////////////////////////////////////
/// Draw the OpenGL scene (a rotating cube) into
/// the specified view
///
/// \param window Target window for rendering
/// \param elapsedTime Time elapsed since the last draw
///
////////////////////////////////////////////////////////////
void draw(sf::Window& window, float elapsedTime)
{
// Activate the window
window.setActive();
// Clear color and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Apply some transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.f, 0.f, -200.f);
glRotatef(elapsedTime * 10.f, 1.f, 0.f, 0.f);
glRotatef(elapsedTime * 6.f, 0.f, 1.f, 0.f);
glRotatef(elapsedTime * 18.f, 0.f, 0.f, 1.f);
// Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices)
static const GLfloat cube[] =
{
// positions // colors
-50, -50, -50, 1, 1, 0,
-50, 50, -50, 1, 1, 0,
-50, -50, 50, 1, 1, 0,
-50, -50, 50, 1, 1, 0,
-50, 50, -50, 1, 1, 0,
-50, 50, 50, 1, 1, 0,
50, -50, -50, 1, 1, 0,
50, 50, -50, 1, 1, 0,
50, -50, 50, 1, 1, 0,
50, -50, 50, 1, 1, 0,
50, 50, -50, 1, 1, 0,
50, 50, 50, 1, 1, 0,
-50, -50, -50, 1, 0, 1,
50, -50, -50, 1, 0, 1,
-50, -50, 50, 1, 0, 1,
-50, -50, 50, 1, 0, 1,
50, -50, -50, 1, 0, 1,
50, -50, 50, 1, 0, 1,
-50, 50, -50, 1, 0, 1,
50, 50, -50, 1, 0, 1,
-50, 50, 50, 1, 0, 1,
-50, 50, 50, 1, 0, 1,
50, 50, -50, 1, 0, 1,
50, 50, 50, 1, 0, 1,
-50, -50, -50, 0, 1, 1,
50, -50, -50, 0, 1, 1,
-50, 50, -50, 0, 1, 1,
-50, 50, -50, 0, 1, 1,
50, -50, -50, 0, 1, 1,
50, 50, -50, 0, 1, 1,
-50, -50, 50, 0, 1, 1,
50, -50, 50, 0, 1, 1,
-50, 50, 50, 0, 1, 1,
-50, 50, 50, 0, 1, 1,
50, -50, 50, 0, 1, 1,
50, 50, 50, 0, 1, 1
};
// Draw the cube
glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), cube);
glColorPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), cube + 3);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Error code
///
////////////////////////////////////////////////////////////
int main()
{
// Open a connection with the X server
Display* display = XOpenDisplay(NULL);
if (!display)
return EXIT_FAILURE;
// Get the XCB connection for the opened display.
xcb_connection_t* xcbConnection = XGetXCBConnection(display);
if (!xcbConnection)
{
sf::err() << "Failed to get the XCB connection for opened display." << std::endl;
return EXIT_FAILURE;
}
// Get XCB screen.
const xcb_setup_t* xcbSetup = xcb_get_setup(xcbConnection);
xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(xcbSetup);
xcb_screen_t* screen = xcbScreenIter.data;
if (!screen)
{
sf::err() << "Failed to get the XCB screen." << std::endl;
return EXIT_FAILURE;
}
// Generate the XCB window IDs.
xcb_window_t rootWindowId = xcb_generate_id(xcbConnection);
xcb_window_t view1WindowId = xcb_generate_id(xcbConnection);
xcb_window_t view2WindowId = xcb_generate_id(xcbConnection);
// Create the root window with a black background.
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t attributes[2] = {screen->black_pixel, XCB_EVENT_MASK_KEY_PRESS};
xcb_create_window(xcbConnection,
XCB_COPY_FROM_PARENT,
rootWindowId,
screen->root,
0, 0, 650, 330,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, attributes);
// Create windows for the SFML views.
xcb_create_window(xcbConnection,
XCB_COPY_FROM_PARENT,
view1WindowId,
rootWindowId,
10, 10, 310, 310,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, attributes);
xcb_create_window(xcbConnection,
XCB_COPY_FROM_PARENT,
view2WindowId,
rootWindowId,
330, 10, 310, 310,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, attributes);
// Map windows to screen.
xcb_map_window(xcbConnection, rootWindowId);
xcb_map_window(xcbConnection, view1WindowId);
xcb_map_window(xcbConnection, view2WindowId);
// Flush commands.
xcb_flush(xcbConnection);
// Create our SFML views
sf::Window sfmlView1(view1WindowId);
sf::Window sfmlView2(view2WindowId);
// Create a clock for measuring elapsed time
sf::Clock clock;
// Initialize our views
initialize(sfmlView1);
initialize(sfmlView2);
// Start the event loop
bool running = true;
xcb_generic_event_t* event = NULL;
while (running)
{
while ((event = xcb_poll_for_event(xcbConnection)))
{
running = false;
}
// Draw something into our views
draw(sfmlView1, clock.getElapsedTime().asSeconds());
draw(sfmlView2, clock.getElapsedTime().asSeconds() * 0.3f);
// Display the views on screen
sfmlView1.display();
sfmlView2.display();
}
return EXIT_SUCCESS;
}