Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
311 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,2 @@ | ||
# Compiled Object files | ||
*.slo | ||
*.lo | ||
*.o | ||
*.obj | ||
|
||
# Compiled Dynamic libraries | ||
*.so | ||
*.dylib | ||
*.dll | ||
|
||
# Compiled Static libraries | ||
*.lai | ||
*.la | ||
*.a | ||
*.lib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
build | ||
.syntastic |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
PROJECT(cairo-gl-sdl2) | ||
|
||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) | ||
|
||
SET(CMAKE_CXX_FLAGS "-W -Wall -Wno-unused-parameter -Werror -O3 -std=c++11") | ||
|
||
INCLUDE(FindPkgConfig) | ||
|
||
PKG_CHECK_MODULES(CAIRO REQUIRED cairo) | ||
PKG_CHECK_MODULES(SDL2 REQUIRED sdl2) | ||
|
||
INCLUDE_DIRECTORIES( | ||
${CAIRO_INCLUDE_DIRS} | ||
${SDL2_INCLUDE_DIRS} | ||
) | ||
|
||
LINK_DIRECTORIES( | ||
${CAIRO_LIBRARY_DIRS} | ||
${SDL2_LIBRARY_DIRS} | ||
) | ||
|
||
ADD_EXECUTABLE(cairo-gl-sdl2 "src/main.cpp") | ||
|
||
TARGET_LINK_LIBRARIES(cairo-gl-sdl2 | ||
${CAIRO_LIBRARIES} | ||
${SDL2_LIBRARIES} | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,9 @@ | ||
cairo-gl-sdl2 | ||
============= | ||
|
||
Cairo, SDL2, and GL/GLES2 tests. | ||
This project is a test bed for using Cairo, SDL2, and GL/GLES2 together. | ||
It differs from existing projects in that it uses the new (ACTUAL) OpenGL | ||
Cairo backend, which has recently received a lot of development attention. | ||
|
||
I have found it to be almost twice as fast as the image backend, though | ||
it can be up to triple the speed in some cases. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
#ifndef SDL2_HPP | ||
#define SDL2_HPP | ||
|
||
#include <SDL2/SDL.h> | ||
#include <SDL2/SDL_syswm.h> | ||
#include <tuple> | ||
#include <iostream> | ||
|
||
class SDL2Window { | ||
public: | ||
typedef std::tuple<int, int> size_type; | ||
|
||
SDL2Window(): | ||
_window(nullptr), | ||
_context(nullptr) { | ||
} | ||
|
||
bool init(int width, int height, unsigned int flags=0) { | ||
if(SDL_Init(SDL_INIT_VIDEO)) { | ||
std::cerr << "SDL_Init failed!" << std::endl; | ||
|
||
return false; | ||
} | ||
|
||
_window = SDL_CreateWindow( | ||
"Cairo+OpenGL+SDL2", | ||
SDL_WINDOWPOS_UNDEFINED, | ||
SDL_WINDOWPOS_UNDEFINED, | ||
width, | ||
height, | ||
SDL_WINDOW_OPENGL | flags | ||
); | ||
|
||
if(!_window) { | ||
std::cerr << "SDL_CreateWindow failed!" << std::endl; | ||
|
||
return false; | ||
} | ||
|
||
_context = SDL_GL_CreateContext(_window); | ||
|
||
if(!_context) { | ||
std::cerr << "SDL_GL_CreateContext failed." << std::endl; | ||
|
||
return false; | ||
} | ||
|
||
SDL_VERSION(&_info.version); | ||
|
||
if(!SDL_GetWindowWMInfo(_window, &_info)) { | ||
std::cout << SDL_FALSE << std::endl; | ||
std::cerr << "SDL_GetWindowWMInfofailed." << std::endl; | ||
std::cerr << SDL_GetError() << std::endl; | ||
|
||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
double main() { | ||
double frames = 0.0; | ||
bool running = true; | ||
Uint32 start = SDL_GetTicks(); | ||
|
||
SDL_Event event; | ||
|
||
while(running) { | ||
while(SDL_PollEvent(&event)) { | ||
if(_mainQuit(event)) running = false; | ||
} | ||
|
||
// DO STUFF | ||
|
||
SDL_GL_SwapWindow(_window); | ||
|
||
frames += 1.0; | ||
} | ||
|
||
SDL_GL_DeleteContext(_context); | ||
SDL_DestroyWindow(_window); | ||
SDL_Quit(); | ||
|
||
return frames / static_cast<double>(SDL_GetTicks() - start); | ||
} | ||
|
||
size_type getSize() const { | ||
int w = 0; | ||
int h = 0; | ||
|
||
SDL_GetWindowSize(_window, &w, &h); | ||
|
||
return std::make_tuple(w, h); | ||
} | ||
|
||
int getWidth() const { | ||
int w = 0; | ||
|
||
std::tie(w, std::ignore) = getSize(); | ||
|
||
return w; | ||
} | ||
|
||
int getHeight() const { | ||
int h = 0; | ||
|
||
std::tie(std::ignore, h) = getSize(); | ||
|
||
return h; | ||
} | ||
|
||
bool isFullscreen() const { | ||
return SDL_GetWindowFlags(_window) & SDL_WINDOW_FULLSCREEN; | ||
} | ||
|
||
void setFullscreen(bool go_fullscreen) const { | ||
SDL_SetWindowFullscreen(_window, go_fullscreen ? 1 : 0); | ||
} | ||
|
||
const char* getTitle() const { | ||
return SDL_GetWindowTitle(_window); | ||
} | ||
|
||
void setTitle(const std::string& title) { | ||
SDL_SetWindowTitle(_window, title.c_str()); | ||
} | ||
|
||
Display* getDisplay() { | ||
return _info.info.x11.display; | ||
}; | ||
|
||
SDL_GLContext getContext() { | ||
// if(!SDL_GL_MakeCurrent(_window, _context)) return nullptr; | ||
|
||
return _context; | ||
} | ||
|
||
protected: | ||
inline bool _mainQuit(const SDL_Event& event) const { | ||
if(event.type == SDL_QUIT || ( | ||
event.type == SDL_KEYUP && | ||
event.key.keysym.sym == SDLK_ESCAPE | ||
)) return true; | ||
|
||
return false; | ||
} | ||
|
||
SDL_Window* _window; | ||
SDL_GLContext _context; | ||
SDL_SysWMinfo _info; | ||
}; | ||
|
||
#endif | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#include "SDL2.hpp" | ||
|
||
#include <chrono> | ||
#include <string> | ||
#include <cstdlib> | ||
#include <iomanip> | ||
#include <cairo.h> | ||
#include <cairo-gl.h> | ||
|
||
// Size of the surface. | ||
const unsigned int WIDTH = 512; | ||
const unsigned int HEIGHT = 512; | ||
|
||
inline void draw(cairo_t* cr) { | ||
cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 1.0); | ||
cairo_paint(cr); | ||
cairo_arc(cr, 256.0, 256.0, 200.0, 0.0, 2.0 * 3.14159); | ||
cairo_set_source_rgba(cr, 1.0, 0.0, 0.5, 0.5); | ||
cairo_fill(cr); | ||
} | ||
|
||
int main(int argc, char** argv) { | ||
if(argc != 3) { | ||
std::cerr | ||
<< "Usage: " << argv[0] | ||
<< " num_draws [image | gl | gl_texture]" << std::endl | ||
; | ||
|
||
return 1; | ||
} | ||
|
||
SDL2Window window; | ||
|
||
if(!window.init(WIDTH, HEIGHT, SDL_WINDOW_HIDDEN)) { | ||
std::cerr << "Couldn't initialize SDL2 window; fatal." << std::endl; | ||
|
||
return 2; | ||
} | ||
|
||
cairo_device_t* device = cairo_glx_device_create( | ||
window.getDisplay(), | ||
reinterpret_cast<GLXContext>(window.getContext()) | ||
); | ||
|
||
if(!device) { | ||
std::cerr << "Couldn't create device; fatal." << std::endl; | ||
|
||
return 3; | ||
} | ||
|
||
// Variable initialization. In the future, I'll need to setup | ||
// the OpenGL texture to use here as well. | ||
auto num_draws = std::atoi(argv[1]); | ||
auto method = std::string(argv[2]); | ||
cairo_surface_t* surface = nullptr; | ||
|
||
if(method == "image" ) surface = cairo_image_surface_create( | ||
CAIRO_FORMAT_ARGB32, | ||
WIDTH, | ||
HEIGHT | ||
); | ||
|
||
else if(method == "gl") surface = cairo_gl_surface_create( | ||
device, | ||
CAIRO_CONTENT_COLOR_ALPHA, | ||
WIDTH, | ||
HEIGHT | ||
); | ||
|
||
// TODO: Implemente cairo_gl_surface_create_for_texture test. | ||
// else if(method == "gl_texture") | ||
|
||
else { | ||
std::cerr << "Unknown surface type '" << method << "'; fatal." << std::endl; | ||
|
||
return 4; | ||
} | ||
|
||
if(!surface) { | ||
std::cerr << "Couldn't create surface; fatal." << std::endl; | ||
|
||
return 5; | ||
} | ||
|
||
std::cout << "Performing " << num_draws << " iterations: " << std::flush; | ||
|
||
auto start = std::chrono::system_clock::now(); | ||
auto last_tick = 0; | ||
|
||
for(auto i = 0; i < num_draws; i++) { | ||
cairo_t* cr = cairo_create(surface); | ||
|
||
draw(cr); | ||
|
||
cairo_destroy(cr); | ||
|
||
// This is a completely wretched way of doing a progress meter, | ||
// but it's the best I'm willing to do for now. | ||
double pct = (static_cast<double>(i) / static_cast<double>(num_draws)) * 100.0; | ||
|
||
if(pct >= last_tick + 10.0) { | ||
std::cout << "+" << std::flush; | ||
|
||
last_tick = pct; | ||
} | ||
} | ||
|
||
auto end = std::chrono::system_clock::now(); | ||
|
||
std::cout | ||
<< " done! (" | ||
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() | ||
<< "ms)" << std::endl | ||
; | ||
|
||
cairo_surface_destroy(surface); | ||
cairo_device_destroy(device); | ||
|
||
return 0; | ||
} | ||
|