static bool make_egl_current_and_test(EGLDisplay *dpy, EGLContext ctx) { const char *string; GLuint shader; bool pass = true; eglMakeCurrent(dpy, NULL, NULL, ctx); if (!epoxy_is_desktop_gl()) { fputs("Claimed to be desktop\n", stderr); pass = false; } if (epoxy_gl_version() < 20) { fprintf(stderr, "Claimed to be GL version %d\n", epoxy_gl_version()); pass = false; } string = (const char *)glGetString(GL_VERSION); printf("GL version: %s\n", string); shader = glCreateShader(GL_FRAGMENT_SHADER); pass = glIsShader(shader); return pass; }
int main (void) { CGLPixelFormatAttribute attribs[] = {0}; CGLPixelFormatObj pix; CGLContextObj ctx; const char *string; bool pass = true; int npix; GLint shader; CGLChoosePixelFormat(attribs, &pix, &npix); CGLCreateContext(pix, (void *) 0, &ctx); CGLSetCurrentContext(ctx); if (!epoxy_is_desktop_gl()) { fputs("Claimed not to be desktop\n", stderr); pass = false; } if (epoxy_gl_version() < 20) { fprintf(stderr, "Claimed to be GL version %d\n", epoxy_gl_version()); pass = false; } if (epoxy_glsl_version() < 100) { fprintf(stderr, "Claimed to have GLSL version %d\n", epoxy_glsl_version()); pass = false; } string = (const char *)glGetString(GL_VERSION); printf("GL version: %s - Epoxy: %d\n", string, epoxy_gl_version()); string = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); printf("GLSL version: %s - Epoxy: %d\n", string, epoxy_glsl_version()); shader = glCreateShader(GL_FRAGMENT_SHADER); pass = glIsShader(shader); CGLSetCurrentContext(NULL); CGLReleaseContext(ctx); CGLReleasePixelFormat(pix); return pass != true; }
static bool test_gl_version(void) { int version = epoxy_gl_version(); if (version < 12) { fprintf(stderr, "Reported GL version %d, should be at least 12\n", version); return false; } return true; }
bool S9xOpenGLDisplayDriver::create_context() { gdk_window = gtk_widget_get_window (drawing_area); #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_WINDOW (gdk_window)) { context = &wl; } #endif #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_WINDOW (gdk_window)) { context = &glx; } #endif if (!context->attach (drawing_area)) return false; if (!context->create_context ()) return false; output_window_width = context->width; output_window_height = context->height; context->make_current (); legacy = false; version = epoxy_gl_version (); if (version < 20) { printf ("OpenGL version is only %d.%d. Recommended version is 2.0.\n", version / 10, version % 10); legacy = true; } int profile_mask = 0; glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &profile_mask); if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT) core = true; else core = false; return true; }
GlContext::GlContext(SDL_Window *window) { this->capabilities = find_capabilities(); auto const &capabilities = this->capabilities; SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, capabilities.major_version); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, capabilities.minor_version); this->gl_context = SDL_GL_CreateContext(window); if (this->gl_context == nullptr) { throw Error(MSG(err) << "OpenGL context creation failed. SDL error: " << SDL_GetError()); } // We still have to verify that our version of libepoxy supports this version of OpenGL. int epoxy_glv = capabilities.major_version * 10 + capabilities.minor_version; if (!epoxy_is_desktop_gl() || epoxy_gl_version() < epoxy_glv) { throw Error(MSG(err) << "The used version of libepoxy does not support OpenGL version " << capabilities.major_version << "." << capabilities.minor_version); } log::log(MSG(info) << "Created OpenGL context version " << capabilities.major_version << "." << capabilities.minor_version); // To quote the standard doc: 'The value gives a rough estimate of the // largest texture that the GL can handle' // -> wat? anyways, we need at least 1024x1024. log::log(MSG(dbg) << "Maximum supported texture size: " << capabilities.max_texture_size); if (capabilities.max_texture_size < 1024) { throw Error(MSG(err) << "Maximum supported texture size is too small: " << capabilities.max_texture_size); } log::log(MSG(dbg) << "Maximum supported texture units: " << capabilities.max_texture_slots); if (capabilities.max_texture_slots < 2) { throw Error(MSG(err) << "Your GPU doesn't have enough texture units: " << capabilities.max_texture_slots); } }
static int test_function(HDC hdc) { ctx1 = wglCreateContext(hdc); ctx2 = wglCreateContext(hdc); if (!ctx1 || !ctx2) { fputs("Failed to create wgl contexts\n", stderr); return 1; } if (!wglMakeCurrent(hdc, ctx1)) { fputs("Failed to make context current\n", stderr); return 1; } if (epoxy_gl_version() < 20) { /* We could possibly do a 1.3 entrypoint or something instead. */ fputs("Test relies on overriding a GL 2.0 entrypoint\n", stderr); return 77; } /* Force resolving epoxy_wglGetProcAddress. */ wglGetProcAddress("glCreateShader"); test_createshader(hdc, ctx1); test_createshader(hdc, ctx1); test_createshader(hdc, ctx2); test_createshader(hdc, ctx2); test_createshader(hdc, ctx1); test_createshader(hdc, ctx2); wglMakeCurrent(NULL, NULL); wglDeleteContext(ctx1); wglDeleteContext(ctx2); return !pass; }
/** Set up glamor for an already-configured GL context. */ Bool glamor_init(ScreenPtr screen, unsigned int flags) { glamor_screen_private *glamor_priv; int gl_version; int max_viewport_size[2]; #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif if (flags & ~GLAMOR_VALID_FLAGS) { ErrorF("glamor_init: Invalid flags %x\n", flags); return FALSE; } glamor_priv = calloc(1, sizeof(*glamor_priv)); if (glamor_priv == NULL) return FALSE; glamor_priv->flags = flags; if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) { LogMessage(X_WARNING, "glamor%d: Failed to allocate screen private\n", screen->myNum); goto fail; } glamor_set_screen_private(screen, glamor_priv); if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) { LogMessage(X_WARNING, "glamor%d: Failed to allocate pixmap private\n", screen->myNum); goto fail; } if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC, sizeof (glamor_gc_private))) { LogMessage(X_WARNING, "glamor%d: Failed to allocate gc private\n", screen->myNum); goto fail; } if (epoxy_is_desktop_gl()) glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; else glamor_priv->gl_flavor = GLAMOR_GL_ES2; gl_version = epoxy_gl_version(); /* Would be nice to have a cleaner test for GLSL 1.30 support, * but for now this should suffice */ if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && gl_version >= 30) glamor_priv->glsl_version = 130; else glamor_priv->glsl_version = 120; /* We'd like to require GL_ARB_map_buffer_range or * GL_OES_map_buffer_range, since it offers more information to * the driver than plain old glMapBuffer() or glBufferSubData(). * It's been supported on Mesa on the desktop since 2009 and on * GLES2 since October 2012. It's supported on Apple's iOS * drivers for SGX535 and A7, but apparently not on most Android * devices (the OES extension spec wasn't released until June * 2012). * * 82% of 0 A.D. players (desktop GL) submitting hardware reports * have support for it, with most of the ones lacking it being on * Windows with Intel 4-series (G45) graphics or older. */ if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { if (gl_version < 21) { ErrorF("Require OpenGL version 2.1 or later.\n"); goto fail; } } else { if (gl_version < 20) { ErrorF("Require Open GLES2.0 or later.\n"); goto fail; } if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) { ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); goto fail; } } glamor_priv->has_rw_pbo = FALSE; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) glamor_priv->has_rw_pbo = TRUE; glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug"); glamor_priv->has_pack_invert = epoxy_has_gl_extension("GL_MESA_pack_invert"); glamor_priv->has_fbo_blit = epoxy_has_gl_extension("GL_EXT_framebuffer_blit"); glamor_priv->has_map_buffer_range = epoxy_has_gl_extension("GL_ARB_map_buffer_range"); glamor_priv->has_buffer_storage = epoxy_has_gl_extension("GL_ARB_buffer_storage"); glamor_priv->has_nv_texture_barrier = epoxy_has_gl_extension("GL_NV_texture_barrier"); glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size); glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]); glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]); #ifdef MAX_FBO_SIZE glamor_priv->max_fbo_size = MAX_FBO_SIZE; #endif glamor_set_debug_level(&glamor_debug_level); /* If we are using egl screen, call egl screen init to * register correct close screen function. */ if (flags & GLAMOR_USE_EGL_SCREEN) { glamor_egl_screen_init(screen, &glamor_priv->ctx); } else { if (!glamor_glx_screen_init(&glamor_priv->ctx)) goto fail; } glamor_priv->saved_procs.close_screen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; glamor_priv->saved_procs.create_screen_resources = screen->CreateScreenResources; screen->CreateScreenResources = glamor_create_screen_resources; if (!glamor_font_init(screen)) goto fail; if (flags & GLAMOR_USE_SCREEN) { if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler, _glamor_wakeup_handler, glamor_priv)) { goto fail; } glamor_priv->saved_procs.create_gc = screen->CreateGC; screen->CreateGC = glamor_create_gc; glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; screen->CreatePixmap = glamor_create_pixmap; glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; glamor_priv->saved_procs.get_spans = screen->GetSpans; screen->GetSpans = glamor_get_spans; glamor_priv->saved_procs.get_image = screen->GetImage; screen->GetImage = glamor_get_image; glamor_priv->saved_procs.change_window_attributes = screen->ChangeWindowAttributes; screen->ChangeWindowAttributes = glamor_change_window_attributes; glamor_priv->saved_procs.copy_window = screen->CopyWindow; screen->CopyWindow = glamor_copy_window; glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; screen->BitmapToRegion = glamor_bitmap_to_region; } #ifdef RENDER if (flags & GLAMOR_USE_PICTURE_SCREEN) { glamor_priv->saved_procs.composite = ps->Composite; ps->Composite = glamor_composite; glamor_priv->saved_procs.trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; glamor_priv->saved_procs.triangles = ps->Triangles; ps->Triangles = glamor_triangles; glamor_priv->saved_procs.addtraps = ps->AddTraps; ps->AddTraps = glamor_add_traps; } glamor_priv->saved_procs.composite_rects = ps->CompositeRects; ps->CompositeRects = glamor_composite_rectangles; glamor_priv->saved_procs.glyphs = ps->Glyphs; ps->Glyphs = glamor_glyphs; glamor_priv->saved_procs.unrealize_glyph = ps->UnrealizeGlyph; ps->UnrealizeGlyph = glamor_glyph_unrealize; glamor_priv->saved_procs.create_picture = ps->CreatePicture; ps->CreatePicture = glamor_create_picture; glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture; ps->DestroyPicture = glamor_destroy_picture; glamor_init_composite_shaders(screen); #endif glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap; screen->SetWindowPixmap = glamor_set_window_pixmap; glamor_init_vbo(screen); glamor_init_pixmap_fbo(screen); #ifdef GLAMOR_TRAPEZOID_SHADER glamor_init_trapezoid_shader(screen); #endif glamor_init_finish_access_shaders(screen); #ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); #endif glamor_pixmap_init(screen); glamor_glyphs_init(screen); glamor_sync_init(screen); glamor_priv->screen = screen; return TRUE; fail: free(glamor_priv); glamor_set_screen_private(screen, NULL); return FALSE; }
/** Set up glamor for an already-configured GL context. */ Bool glamor_init(ScreenPtr screen, unsigned int flags) { glamor_screen_private *glamor_priv; int gl_version; int glsl_major, glsl_minor; int max_viewport_size[2]; const char *shading_version_string; int shading_version_offset; PictureScreenPtr ps = GetPictureScreenIfSet(screen); if (flags & ~GLAMOR_VALID_FLAGS) { ErrorF("glamor_init: Invalid flags %x\n", flags); return FALSE; } glamor_priv = calloc(1, sizeof(*glamor_priv)); if (glamor_priv == NULL) return FALSE; glamor_priv->flags = flags; if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) { LogMessage(X_WARNING, "glamor%d: Failed to allocate screen private\n", screen->myNum); goto fail; } glamor_set_screen_private(screen, glamor_priv); if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, sizeof(struct glamor_pixmap_private))) { LogMessage(X_WARNING, "glamor%d: Failed to allocate pixmap private\n", screen->myNum); goto fail; } if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC, sizeof (glamor_gc_private))) { LogMessage(X_WARNING, "glamor%d: Failed to allocate gc private\n", screen->myNum); goto fail; } glamor_priv->saved_procs.close_screen = screen->CloseScreen; screen->CloseScreen = glamor_close_screen; /* If we are using egl screen, call egl screen init to * register correct close screen function. */ if (flags & GLAMOR_USE_EGL_SCREEN) { glamor_egl_screen_init(screen, &glamor_priv->ctx); } else { if (!glamor_glx_screen_init(&glamor_priv->ctx)) goto fail; } glamor_make_current(glamor_priv); if (epoxy_is_desktop_gl()) glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP; else glamor_priv->gl_flavor = GLAMOR_GL_ES2; gl_version = epoxy_gl_version(); shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); if (!shading_version_string) { LogMessage(X_WARNING, "glamor%d: Failed to get GLSL version\n", screen->myNum); goto fail; } shading_version_offset = 0; if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0) shading_version_offset = 18; if (sscanf(shading_version_string + shading_version_offset, "%i.%i", &glsl_major, &glsl_minor) != 2) { LogMessage(X_WARNING, "glamor%d: Failed to parse GLSL version string %s\n", screen->myNum, shading_version_string); goto fail; } glamor_priv->glsl_version = glsl_major * 100 + glsl_minor; if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) { /* Force us back to the base version of our programs on an ES * context, anyway. Basically glamor only uses desktop 1.20 * or 1.30 currently. 1.30's new features are also present in * ES 3.0, but our glamor_program.c constructions use a lot of * compatibility features (to reduce the diff between 1.20 and * 1.30 programs). */ glamor_priv->glsl_version = 120; } /* We'd like to require GL_ARB_map_buffer_range or * GL_OES_map_buffer_range, since it offers more information to * the driver than plain old glMapBuffer() or glBufferSubData(). * It's been supported on Mesa on the desktop since 2009 and on * GLES2 since October 2012. It's supported on Apple's iOS * drivers for SGX535 and A7, but apparently not on most Android * devices (the OES extension spec wasn't released until June * 2012). * * 82% of 0 A.D. players (desktop GL) submitting hardware reports * have support for it, with most of the ones lacking it being on * Windows with Intel 4-series (G45) graphics or older. */ if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { if (gl_version < 21) { ErrorF("Require OpenGL version 2.1 or later.\n"); goto fail; } if (!glamor_check_instruction_count(gl_version)) goto fail; } else { if (gl_version < 20) { ErrorF("Require Open GLES2.0 or later.\n"); goto fail; } if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) { ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); goto fail; } } glamor_priv->has_rw_pbo = FALSE; if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) glamor_priv->has_rw_pbo = TRUE; glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug"); glamor_priv->has_pack_invert = epoxy_has_gl_extension("GL_MESA_pack_invert"); glamor_priv->has_fbo_blit = epoxy_has_gl_extension("GL_EXT_framebuffer_blit"); glamor_priv->has_map_buffer_range = epoxy_has_gl_extension("GL_ARB_map_buffer_range") || epoxy_has_gl_extension("GL_EXT_map_buffer_range"); glamor_priv->has_buffer_storage = epoxy_has_gl_extension("GL_ARB_buffer_storage"); glamor_priv->has_nv_texture_barrier = epoxy_has_gl_extension("GL_NV_texture_barrier"); glamor_priv->has_unpack_subimage = glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP || epoxy_gl_version() >= 30 || epoxy_has_gl_extension("GL_EXT_unpack_subimage"); glamor_priv->has_pack_subimage = glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP || epoxy_gl_version() >= 30 || epoxy_has_gl_extension("GL_NV_pack_subimage"); glamor_priv->has_vertex_array_object = epoxy_has_gl_extension("GL_ARB_vertex_array_object"); glamor_priv->has_dual_blend = epoxy_has_gl_extension("GL_ARB_blend_func_extended"); /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */ glamor_priv->is_core_profile = gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility"); glamor_setup_debug_output(screen); glamor_priv->use_quads = (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) && !glamor_priv->is_core_profile; /* Driver-specific hack: Avoid using GL_QUADS on VC4, where * they'll be emulated more expensively than we can with our * cached IB. */ if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") && strstr((char *)glGetString(GL_RENDERER), "VC4")) glamor_priv->use_quads = FALSE; glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size); glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]); glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]); #ifdef MAX_FBO_SIZE glamor_priv->max_fbo_size = MAX_FBO_SIZE; #endif glamor_priv->one_channel_format = GL_ALPHA; if (epoxy_has_gl_extension("GL_ARB_texture_rg") && epoxy_has_gl_extension("GL_ARB_texture_swizzle")) glamor_priv->one_channel_format = GL_RED; glamor_set_debug_level(&glamor_debug_level); glamor_priv->saved_procs.create_screen_resources = screen->CreateScreenResources; screen->CreateScreenResources = glamor_create_screen_resources; if (!glamor_font_init(screen)) goto fail; glamor_priv->saved_procs.block_handler = screen->BlockHandler; screen->BlockHandler = _glamor_block_handler; if (!glamor_composite_glyphs_init(screen)) { ErrorF("Failed to initialize composite masks\n"); goto fail; } glamor_priv->saved_procs.create_gc = screen->CreateGC; screen->CreateGC = glamor_create_gc; glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; screen->CreatePixmap = glamor_create_pixmap; glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; screen->DestroyPixmap = glamor_destroy_pixmap; glamor_priv->saved_procs.get_spans = screen->GetSpans; screen->GetSpans = glamor_get_spans; glamor_priv->saved_procs.get_image = screen->GetImage; screen->GetImage = glamor_get_image; glamor_priv->saved_procs.change_window_attributes = screen->ChangeWindowAttributes; screen->ChangeWindowAttributes = glamor_change_window_attributes; glamor_priv->saved_procs.copy_window = screen->CopyWindow; screen->CopyWindow = glamor_copy_window; glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; screen->BitmapToRegion = glamor_bitmap_to_region; glamor_priv->saved_procs.composite = ps->Composite; ps->Composite = glamor_composite; glamor_priv->saved_procs.trapezoids = ps->Trapezoids; ps->Trapezoids = glamor_trapezoids; glamor_priv->saved_procs.triangles = ps->Triangles; ps->Triangles = glamor_triangles; glamor_priv->saved_procs.addtraps = ps->AddTraps; ps->AddTraps = glamor_add_traps; glamor_priv->saved_procs.composite_rects = ps->CompositeRects; ps->CompositeRects = glamor_composite_rectangles; glamor_priv->saved_procs.glyphs = ps->Glyphs; ps->Glyphs = glamor_composite_glyphs; glamor_init_vbo(screen); glamor_init_pixmap_fbo(screen); glamor_init_finish_access_shaders(screen); #ifdef GLAMOR_GRADIENT_SHADER glamor_init_gradient_shader(screen); #endif glamor_pixmap_init(screen); glamor_sync_init(screen); glamor_priv->screen = screen; return TRUE; fail: free(glamor_priv); glamor_set_screen_private(screen, NULL); return FALSE; }
Engine::Engine(util::Dir *data_dir, const char *windowtitle) : running{false}, drawing_debug_overlay{true}, drawing_huds{true}, engine_coord_data{this->get_coord_data()}, current_player{1}, data_dir{data_dir}, audio_manager{} { for (uint32_t size : {12, 20}) { fonts[size] = std::unique_ptr<Font>{new Font{"DejaVu Serif", "Book", size}}; } this->logsink_file = std::make_unique<log::FileSink>("/tmp/openage-log", true); // enqueue the engine's own input handler to the // execution list. this->register_resize_action(this); if (SDL_Init(SDL_INIT_VIDEO) < 0) { throw util::Error(MSG(err) << "SDL video initialization: " << SDL_GetError()); } else { log::log(MSG(info) << "Initialized SDL video subsystems."); } SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); int32_t window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED; this->window = SDL_CreateWindow( windowtitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->engine_coord_data->window_size.x, this->engine_coord_data->window_size.y, window_flags ); if (this->window == nullptr) { throw util::Error(MSG(err) << "Failed to create SDL window: " << SDL_GetError()); } // load support for the PNG image formats, jpg bit: IMG_INIT_JPG int wanted_image_formats = IMG_INIT_PNG; int sdlimg_inited = IMG_Init(wanted_image_formats); if ((sdlimg_inited & wanted_image_formats) != wanted_image_formats) { throw util::Error(MSG(err) << "Failed to init PNG support: " << IMG_GetError()); } this->glcontext = SDL_GL_CreateContext(this->window); if (this->glcontext == nullptr) { throw util::Error(MSG(err) << "Failed creating OpenGL context: " << SDL_GetError()); } // check the OpenGL version, for shaders n stuff if (!epoxy_is_desktop_gl() || epoxy_gl_version() < 21) { throw util::Error(MSG(err) << "OpenGL 2.1 not available"); } // to quote the standard doc: // 'The value gives a rough estimate // of the largest texture that the GL can handle' // -> wat? // anyways, we need at least 1024x1024. int max_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); log::log(MSG(dbg) << "Maximum supported texture size: " << max_texture_size); if (max_texture_size < 1024) { throw util::Error(MSG(err) << "Maximum supported texture size too small: " << max_texture_size); } int max_texture_units; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_units); log::log(MSG(dbg) << "Maximum supported texture units: " << max_texture_units); if (max_texture_units < 2) { throw util::Error(MSG(err) << "Your GPU has too less texture units: " << max_texture_units); } // vsync on SDL_GL_SetSwapInterval(1); // enable alpha blending glEnable(GL_BLEND); // order of drawing relevant for depth // what gets drawn last is displayed on top. glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // initialize job manager with cpucount-2 worker threads int number_of_worker_threads = SDL_GetCPUCount() - 2; if (number_of_worker_threads <= 0) { number_of_worker_threads = 1; } this->job_manager = new job::JobManager{number_of_worker_threads}; // initialize audio auto devices = audio::AudioManager::get_devices(); if (devices.empty()) { throw util::Error{MSG(err) << "No audio devices found"}; } }
Engine::Engine(util::Dir *data_dir, const char *windowtitle) : OptionNode{"Engine"}, running{false}, drawing_debug_overlay{this, "drawing_debug_overlay", true}, drawing_huds{this, "drawing_huds", true}, engine_coord_data{this->get_coord_data()}, current_player{this, "current_player", 1}, data_dir{data_dir}, audio_manager{} { for (uint32_t size : {12, 20}) { fonts[size] = std::unique_ptr<Font>{new Font{"DejaVu Serif", "Book", size}}; } this->logsink_file = std::make_unique<log::FileSink>("/tmp/openage-log", true); // enqueue the engine's own input handler to the // execution list. this->register_resize_action(this); // register the engines input manager this->register_input_action(&this->input_manager); if (SDL_Init(SDL_INIT_VIDEO) < 0) { throw Error(MSG(err) << "SDL video initialization: " << SDL_GetError()); } else { log::log(MSG(info) << "Initialized SDL video subsystems."); } SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); int32_t window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED; this->window = SDL_CreateWindow( windowtitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, this->engine_coord_data->window_size.x, this->engine_coord_data->window_size.y, window_flags ); if (this->window == nullptr) { throw Error(MSG(err) << "Failed to create SDL window: " << SDL_GetError()); } // load support for the PNG image formats, jpg bit: IMG_INIT_JPG int wanted_image_formats = IMG_INIT_PNG; int sdlimg_inited = IMG_Init(wanted_image_formats); if ((sdlimg_inited & wanted_image_formats) != wanted_image_formats) { throw Error(MSG(err) << "Failed to init PNG support: " << IMG_GetError()); } this->glcontext = SDL_GL_CreateContext(this->window); if (this->glcontext == nullptr) { throw Error(MSG(err) << "Failed creating OpenGL context: " << SDL_GetError()); } // check the OpenGL version, for shaders n stuff if (!epoxy_is_desktop_gl() || epoxy_gl_version() < 21) { throw Error(MSG(err) << "OpenGL 2.1 not available"); } // to quote the standard doc: // 'The value gives a rough estimate // of the largest texture that the GL can handle' // -> wat? // anyways, we need at least 1024x1024. int max_texture_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); log::log(MSG(dbg) << "Maximum supported texture size: " << max_texture_size); if (max_texture_size < 1024) { throw Error(MSG(err) << "Maximum supported texture size too small: " << max_texture_size); } int max_texture_units; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_units); log::log(MSG(dbg) << "Maximum supported texture units: " << max_texture_units); if (max_texture_units < 2) { throw Error(MSG(err) << "Your GPU has too less texture units: " << max_texture_units); } // vsync on SDL_GL_SetSwapInterval(1); // enable alpha blending glEnable(GL_BLEND); // order of drawing relevant for depth // what gets drawn last is displayed on top. glDisable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // initialize job manager with cpucount-2 worker threads int number_of_worker_threads = SDL_GetCPUCount() - 2; if (number_of_worker_threads <= 0) { number_of_worker_threads = 1; } this->job_manager = new job::JobManager{number_of_worker_threads}; // initialize audio auto devices = audio::AudioManager::get_devices(); if (devices.empty()) { throw Error{MSG(err) << "No audio devices found"}; } // initialize engine related global keybinds auto &global_input_context = this->get_input_manager().get_global_context(); global_input_context.bind(input::action_t::STOP_GAME, [this](const input::action_arg_t &) { this->stop(); }); global_input_context.bind(input::action_t::TOGGLE_HUD, [this](const input::action_arg_t &) { this->drawing_huds.value = !this->drawing_huds.value; }); global_input_context.bind(input::action_t::SCREENSHOT, [this](const input::action_arg_t &) { this->get_screenshot_manager().save_screenshot(); }); global_input_context.bind(input::action_t::TOGGLE_DEBUG_OVERLAY, [this](const input::action_arg_t &) { this->drawing_debug_overlay.value = !this->drawing_debug_overlay.value; }); global_input_context.bind(input::action_t::TOGGLE_PROFILER, [this](const input::action_arg_t &) { if (this->external_profiler.currently_profiling) { this->external_profiler.stop(); this->external_profiler.show_results(); } else { this->external_profiler.start(); } }); global_input_context.bind(input::event_class::MOUSE, [this](const input::action_arg_t &arg) { if (arg.e.cc.has_class(input::event_class::MOUSE_MOTION) && this->get_input_manager().is_down(input::event_class::MOUSE_BUTTON, 2)) { this->move_phys_camera(arg.motion.x, arg.motion.y); return true; } return false; }); // Switching between players with the 1-8 keys auto bind_player_switch = [this, &global_input_context](input::action_t action, int player) { global_input_context.bind(action, [this, player](const input::action_arg_t &) { this->current_player.value = player; }); }; bind_player_switch(input::action_t::SWITCH_TO_PLAYER_1, 1); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_2, 2); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_3, 3); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_4, 4); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_5, 5); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_6, 6); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_7, 7); bind_player_switch(input::action_t::SWITCH_TO_PLAYER_8, 8); }