void _al_iphone_update_visuals(void) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *ref; ALLEGRO_SYSTEM_IPHONE *system = (void *)al_get_system_driver(); ref = _al_get_new_display_settings(); /* If we aren't called the first time, only updated scores. */ if (system->visuals) { for (int i = 0; i < system->visuals_count; i++) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = system->visuals[i]; eds->score = _al_score_display_settings(eds, ref); } return; } system->visuals = al_calloc(VISUALS_COUNT, sizeof(*system->visuals)); system->visuals_count = VISUALS_COUNT; for (int i = 0; i < VISUALS_COUNT; i++) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = al_calloc(1, sizeof *eds); eds->settings[ALLEGRO_RENDER_METHOD] = 1; eds->settings[ALLEGRO_COMPATIBLE_DISPLAY] = 1; eds->settings[ALLEGRO_SWAP_METHOD] = 2; eds->settings[ALLEGRO_VSYNC] = 1; switch (i) { case 0: set_rgba8888(eds); break; case 1: set_rgb565(eds); break; case 2: set_rgba8888(eds); eds->settings[ALLEGRO_DEPTH_SIZE] = 16; break; case 3: set_rgb565(eds); eds->settings[ALLEGRO_DEPTH_SIZE] = 16; break; case 4: set_rgba8888(eds); eds->settings[ALLEGRO_DEPTH_SIZE] = 24; eds->settings[ALLEGRO_STENCIL_SIZE] = 8; break; case 5: set_rgb565(eds); eds->settings[ALLEGRO_DEPTH_SIZE] = 24; eds->settings[ALLEGRO_STENCIL_SIZE] = 8; break; } eds->score = _al_score_display_settings(eds, ref); eds->index = i; system->visuals[i] = eds; } }
/* Function: al_get_new_display_option */ int al_get_new_display_option(int option, int *importance) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *extras; extras = _al_get_new_display_settings(); if (extras->required & ((int64_t)1 << option)) { if (importance) *importance = ALLEGRO_REQUIRE; return extras->settings[option]; } if (extras->suggested & ((int64_t)1 << option)) { if (importance) *importance = ALLEGRO_SUGGEST; return extras->settings[option]; } if (importance) *importance = ALLEGRO_DONTCARE; return 0; }
static int win_get_num_display_modes(void) { int format = _al_deduce_color_format(_al_get_new_display_settings()); int refresh_rate = al_get_new_display_refresh_rate(); int flags = al_get_new_display_flags(); #if defined ALLEGRO_CFG_OPENGL if (flags & ALLEGRO_OPENGL) { return _al_wgl_get_num_display_modes(format, refresh_rate, flags); } #endif #if defined ALLEGRO_CFG_D3D return _al_d3d_get_num_display_modes(format, refresh_rate, flags); #endif return 0; }
static ALLEGRO_DISPLAY_MODE *win_get_display_mode(int index, ALLEGRO_DISPLAY_MODE *mode) { int format = _al_deduce_color_format(_al_get_new_display_settings()); int refresh_rate = al_get_new_display_refresh_rate(); int flags = al_get_new_display_flags(); #if defined ALLEGRO_CFG_OPENGL if (flags & ALLEGRO_OPENGL) { return _al_wgl_get_display_mode(index, format, refresh_rate, flags, mode); } #endif #if defined ALLEGRO_CFG_D3D return _al_d3d_get_display_mode(index, format, refresh_rate, flags, mode); #endif return NULL; }
/* Function: al_set_new_display_option */ void al_set_new_display_option(int option, int value, int importance) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *extras; extras = _al_get_new_display_settings(); switch (importance) { case ALLEGRO_REQUIRE: extras->required |= (int64_t)1 << option; extras->suggested &= ~((int64_t)1 << option); break; case ALLEGRO_SUGGEST: extras->suggested |= (int64_t)1 << option; extras->required &= ~((int64_t)1 << option); break; case ALLEGRO_DONTCARE: extras->required &= ~((int64_t)1 << option); extras->suggested &= ~((int64_t)1 << option); break; } extras->settings[option] = value; }
static bool create_display_internals(ALLEGRO_DISPLAY_WGL *wgl_disp) { ALLEGRO_DISPLAY *disp = (void*)wgl_disp; ALLEGRO_DISPLAY_WIN *win_disp = (void*)wgl_disp; WGL_DISPLAY_PARAMETERS ndp; int window_x, window_y; /* The window is created in a separate thread so we need to pass this * TLS on */ al_get_new_window_position(&window_x, &window_y); ndp.window_x = window_x; ndp.window_y = window_y; /* _beginthread closes the handle automatically. */ ndp.display = wgl_disp; ndp.init_failed = true; ndp.AckEvent = CreateEvent(NULL, false, false, NULL); _beginthread(display_thread_proc, 0, &ndp); /* Wait some _finite_ time (10 secs or so) for display thread to init, and * give up if something horrible happened to it, unless we're in debug mode * and we may have intentionally stopped the execution to analyze the code. */ #ifdef DEBUGMODE WaitForSingleObject(ndp.AckEvent, INFINITE); #else WaitForSingleObject(ndp.AckEvent, 10*1000); #endif CloseHandle(ndp.AckEvent); if (ndp.init_failed) { ALLEGRO_ERROR("Failed to create display.\n"); return false; } /* WGL display lists cannot be shared with the API currently in use. */ disp->ogl_extras->is_shared = false; if (!select_pixel_format(wgl_disp, wgl_disp->dc)) { destroy_display_internals(wgl_disp); return false; } if (disp->flags & ALLEGRO_OPENGL_3_0) { bool fc = (disp->flags & ALLEGRO_OPENGL_FORWARD_COMPATIBLE) != 0; wgl_disp->glrc = init_ogl_context_ex(wgl_disp->dc, fc, 3, 0); } else { wgl_disp->glrc = wglCreateContext(wgl_disp->dc); } if (!wgl_disp->glrc) { ALLEGRO_ERROR("Unable to create a render context! %s\n", get_error_desc(GetLastError())); destroy_display_internals(wgl_disp); return false; } /* make the context the current one */ if (!wglMakeCurrent(wgl_disp->dc, wgl_disp->glrc)) { ALLEGRO_ERROR("Unable to make the context current! %s\n", get_error_desc(GetLastError())); destroy_display_internals(wgl_disp); return false; } _al_ogl_manage_extensions(disp); _al_ogl_set_extensions(disp->ogl_extras->extension_api); if (disp->ogl_extras->ogl_info.version < _ALLEGRO_OPENGL_VERSION_1_2) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = _al_get_new_display_settings(); if (eds->required & (1<<ALLEGRO_COMPATIBLE_DISPLAY)) { ALLEGRO_WARN("Allegro requires at least OpenGL version 1.2 to work.\n"); destroy_display_internals(wgl_disp); return false; } disp->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY] = 0; } disp->ogl_extras->backbuffer = _al_ogl_create_backbuffer(disp); if (!disp->ogl_extras->backbuffer) { ALLEGRO_ERROR("Failed to create a backbuffer.\n"); destroy_display_internals(wgl_disp); return false; } /* Try to enable or disable vsync as requested */ /* NOTE: my drivers claim I don't have WGL_EXT_swap_control * (according to al_have_opengl_extension), but wglSwapIntervalEXT * does get loaded, so just check for that. */ if (wglSwapIntervalEXT) { if (disp->extra_settings.settings[ALLEGRO_VSYNC] == 1) { wglSwapIntervalEXT(1); } else if (disp->extra_settings.settings[ALLEGRO_VSYNC] == 2) { wglSwapIntervalEXT(0); } } win_disp->mouse_selected_hcursor = 0; win_disp->mouse_cursor_shown = false; win_disp->can_acknowledge = false; _al_win_grab_input(win_disp); if (disp->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY]) setup_gl(disp); return true; }
/* Function: al_create_display */ ALLEGRO_DISPLAY *al_create_display(int w, int h) { ALLEGRO_SYSTEM *system; ALLEGRO_DISPLAY_INTERFACE *driver; ALLEGRO_DISPLAY *display; ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds; eds = _al_get_new_display_settings(); /* We cannot depend on al_reset_new_display_options() having been called * anywhere because al_create_display() may be called from new threads. */ if (!eds) al_reset_new_display_options(); else _al_fill_display_settings(eds); system = al_get_system_driver(); driver = system->vt->get_display_driver(); display = driver->create_display(w, h); if (!display) { ALLEGRO_DEBUG("Failed to create display (NULL)\n"); return NULL; } display->vertex_cache = 0; display->num_cache_vertices = 0; display->cache_enabled = false; display->vertex_cache_size = 0; display->cache_texture = 0; al_identity_transform(&display->cur_transform); _al_initialize_blender(&display->cur_blender); _al_vector_init(&display->bitmaps, sizeof(ALLEGRO_BITMAP*)); al_set_current_display(display); /* Clear the screen */ #ifndef ALLEGRO_GP2XWIZ if (display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY]) al_clear_to_color(al_map_rgb(0, 0, 0)); #else al_clear_to_color(al_map_rgb(0, 0, 0)); #endif /* on iphone, don't kill the initial splashscreen */ #ifndef ALLEGRO_IPHONE al_flip_display(); #endif /* Clear the backbuffer */ #ifndef ALLEGRO_GP2XWIZ if (display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY]) al_clear_to_color(al_map_rgb(0, 0, 0)); #else al_clear_to_color(al_map_rgb(0, 0, 0)); #endif #ifndef ALLEGRO_IPHONE al_flip_display(); #endif al_set_window_title(al_get_appname()); return display; }
static bool pi_create_display(ALLEGRO_DISPLAY *display) { ALLEGRO_DISPLAY_RASPBERRYPI *d = (void *)display; ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = _al_get_new_display_settings(); egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (egl_display == EGL_NO_DISPLAY) { return false; } int major, minor; if (!eglInitialize(egl_display, &major, &minor)) { return false; } static EGLint attrib_list[] = { EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; attrib_list[1] = eds->settings[ALLEGRO_DEPTH_SIZE]; attrib_list[3] = eds->settings[ALLEGRO_STENCIL_SIZE]; if (eds->settings[ALLEGRO_RED_SIZE] || eds->settings[ALLEGRO_GREEN_SIZE] || eds->settings[ALLEGRO_BLUE_SIZE] || eds->settings[ALLEGRO_ALPHA_SIZE]) { attrib_list[5] = eds->settings[ALLEGRO_RED_SIZE]; attrib_list[7] = eds->settings[ALLEGRO_GREEN_SIZE]; attrib_list[9] = eds->settings[ALLEGRO_BLUE_SIZE]; attrib_list[11] = eds->settings[ALLEGRO_ALPHA_SIZE]; } else if (eds->settings[ALLEGRO_COLOR_SIZE] == 16) { attrib_list[5] = 5; attrib_list[7] = 6; attrib_list[9] = 5; attrib_list[11] = 0; } EGLConfig config; int num_configs; if (!eglChooseConfig(egl_display, attrib_list, &config, 1, &num_configs)) { return false; } eglBindAPI(EGL_OPENGL_ES_API); int es_ver = (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) ? 2 : 1; static EGLint ctxattr[3] = { EGL_CONTEXT_CLIENT_VERSION, 0xDEADBEEF, EGL_NONE }; ctxattr[1] = es_ver; egl_context = eglCreateContext(egl_display, config, EGL_NO_CONTEXT, ctxattr); if (egl_context == EGL_NO_CONTEXT) { return false; } static EGL_DISPMANX_WINDOW_T nativewindow; DISPMANX_ELEMENT_HANDLE_T dispman_element; int dx, dy, screen_width, screen_height; _al_raspberrypi_get_screen_info(&dx, &dy, &screen_width, &screen_height); d->cursor_offset_x = dx; d->cursor_offset_y = dy; dst_rect.x = dx; dst_rect.y = dy; dst_rect.width = screen_width; dst_rect.height = screen_height; d->screen_width = screen_width; d->screen_height = screen_height; src_rect.x = 0; src_rect.y = 0; src_rect.width = display->w << 16; src_rect.height = display->h << 16; dispman_display = vc_dispmanx_display_open(0 /* LCD */); dispman_update = vc_dispmanx_update_start(0); dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, 0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, DISPMANX_NO_ROTATE/*transform*/ ); nativewindow.element = dispman_element; nativewindow.width = display->w; nativewindow.height = display->h; vc_dispmanx_update_submit_sync(dispman_update); egl_window = eglCreateWindowSurface( egl_display, config, &nativewindow, NULL); if (egl_window == EGL_NO_SURFACE) { return false; } if (!eglMakeCurrent(egl_display, egl_window, egl_window, egl_context)) { return false; } return true; }
void _al_set_color_components(int format, ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds, int importance) { ALLEGRO_EXTRA_DISPLAY_SETTINGS old_eds; memcpy(&old_eds, _al_get_new_display_settings(), sizeof(old_eds)); _al_set_new_display_settings(eds); al_set_new_display_option(ALLEGRO_RED_SIZE, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_GREEN_SIZE, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_BLUE_SIZE, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, ALLEGRO_DONTCARE); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 0, ALLEGRO_DONTCARE); switch (format) { case ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); break; case ALLEGRO_PIXEL_FORMAT_ANY_WITH_ALPHA: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 8, importance); break; case ALLEGRO_PIXEL_FORMAT_ANY_16_NO_ALPHA: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_ANY_16_WITH_ALPHA: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 1, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_ANY_24_NO_ALPHA: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 24, importance); break; case ALLEGRO_PIXEL_FORMAT_ANY_32_NO_ALPHA: /* With OpenGL drivers, we never "know" the actual pixel * format. We use glReadPixels when we lock the screen, so * we can always lock the screen in any format we want. There * is no "display format". * * Therefore it makes no sense to fail display creation * if either an RGB or RGBX format was requested but the * other seems available only in WGL/GLX (those really report * the number of bits used for red/green/blue/alpha to us only. * They never report any "X bits".). */ al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 32, ALLEGRO_SUGGEST); break; case ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 8, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 32, importance); break; } switch (format) { case ALLEGRO_PIXEL_FORMAT_RGBA_8888: case ALLEGRO_PIXEL_FORMAT_ABGR_8888: case ALLEGRO_PIXEL_FORMAT_ARGB_8888: case ALLEGRO_PIXEL_FORMAT_RGB_888: case ALLEGRO_PIXEL_FORMAT_BGR_888: case ALLEGRO_PIXEL_FORMAT_RGBX_8888: case ALLEGRO_PIXEL_FORMAT_XRGB_8888: case ALLEGRO_PIXEL_FORMAT_XBGR_8888: al_set_new_display_option(ALLEGRO_RED_SIZE, 8, importance); al_set_new_display_option(ALLEGRO_GREEN_SIZE, 8, importance); al_set_new_display_option(ALLEGRO_BLUE_SIZE, 8, importance); break; case ALLEGRO_PIXEL_FORMAT_BGR_565: case ALLEGRO_PIXEL_FORMAT_RGB_565: al_set_new_display_option(ALLEGRO_RED_SIZE, 5, importance); al_set_new_display_option(ALLEGRO_GREEN_SIZE, 6, importance); al_set_new_display_option(ALLEGRO_BLUE_SIZE, 5, importance); break; case ALLEGRO_PIXEL_FORMAT_RGBA_5551: case ALLEGRO_PIXEL_FORMAT_ARGB_1555: al_set_new_display_option(ALLEGRO_RED_SIZE, 5, importance); al_set_new_display_option(ALLEGRO_GREEN_SIZE, 5, importance); al_set_new_display_option(ALLEGRO_BLUE_SIZE, 5, importance); break; case ALLEGRO_PIXEL_FORMAT_ARGB_4444: case ALLEGRO_PIXEL_FORMAT_RGBA_4444: al_set_new_display_option(ALLEGRO_RED_SIZE, 4, importance); al_set_new_display_option(ALLEGRO_GREEN_SIZE, 4, importance); al_set_new_display_option(ALLEGRO_BLUE_SIZE, 4, importance); break; } switch (format) { case ALLEGRO_PIXEL_FORMAT_RGBA_8888: case ALLEGRO_PIXEL_FORMAT_ABGR_8888: case ALLEGRO_PIXEL_FORMAT_ARGB_8888: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 8, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 32, importance); break; case ALLEGRO_PIXEL_FORMAT_RGB_888: case ALLEGRO_PIXEL_FORMAT_BGR_888: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 24, importance); break; case ALLEGRO_PIXEL_FORMAT_RGBX_8888: case ALLEGRO_PIXEL_FORMAT_XRGB_8888: case ALLEGRO_PIXEL_FORMAT_XBGR_8888: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 32, importance); break; case ALLEGRO_PIXEL_FORMAT_BGR_565: case ALLEGRO_PIXEL_FORMAT_RGB_565: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 0, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_RGBA_5551: case ALLEGRO_PIXEL_FORMAT_ARGB_1555: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 1, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_ARGB_4444: case ALLEGRO_PIXEL_FORMAT_RGBA_4444: al_set_new_display_option(ALLEGRO_ALPHA_SIZE, 4, importance); al_set_new_display_option(ALLEGRO_COLOR_SIZE, 16, importance); break; } switch (format) { case ALLEGRO_PIXEL_FORMAT_RGBA_8888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 16, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 24, importance); break; case ALLEGRO_PIXEL_FORMAT_ABGR_8888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 24, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 16, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, importance); break; case ALLEGRO_PIXEL_FORMAT_ARGB_8888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 24, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_RGB_888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_BGR_888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 16, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, importance); break; case ALLEGRO_PIXEL_FORMAT_XRGB_8888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 16, importance); break; case ALLEGRO_PIXEL_FORMAT_RGBX_8888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 16, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 24, importance); break; case ALLEGRO_PIXEL_FORMAT_XBGR_8888: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 16, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, importance); break; case ALLEGRO_PIXEL_FORMAT_BGR_565: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 11, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 5, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, importance); break; case ALLEGRO_PIXEL_FORMAT_RGB_565: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 5, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 11, importance); break; case ALLEGRO_PIXEL_FORMAT_RGBA_5551: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 1, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 6, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 11, importance); break; case ALLEGRO_PIXEL_FORMAT_ARGB_1555: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 15, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 0, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 5, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 10, importance); break; case ALLEGRO_PIXEL_FORMAT_ARGB_4444: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 12, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 4, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, importance); case ALLEGRO_PIXEL_FORMAT_RGBA_4444: al_set_new_display_option(ALLEGRO_ALPHA_SHIFT, 12, importance); al_set_new_display_option(ALLEGRO_BLUE_SHIFT, 8, importance); al_set_new_display_option(ALLEGRO_GREEN_SHIFT, 4, importance); al_set_new_display_option(ALLEGRO_RED_SHIFT, 0, importance); break; } memcpy(eds, _al_get_new_display_settings(), sizeof(*eds)); _al_set_new_display_settings(&old_eds); }
/* Function: al_reset_new_display_options */ void al_reset_new_display_options(void) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *extras; extras = _al_get_new_display_settings(); _al_fill_display_settings(extras); }
/* Create a new X11 display, which maps directly to a GLX window. */ static ALLEGRO_DISPLAY *xdpy_create_display(int w, int h) { ALLEGRO_SYSTEM_XGLX *system = (void *)al_get_system_driver(); int adapter = al_get_new_display_adapter(); if (system->x11display == NULL) { ALLEGRO_WARN("Not connected to X server.\n"); return NULL; } if (w <= 0 || h <= 0) { ALLEGRO_ERROR("Invalid window size %dx%d\n", w, h); return NULL; } _al_mutex_lock(&system->lock); ALLEGRO_DISPLAY_XGLX *d = al_calloc(1, sizeof *d); ALLEGRO_DISPLAY *display = (void*)d; ALLEGRO_OGL_EXTRAS *ogl = al_calloc(1, sizeof *ogl); display->ogl_extras = ogl; int major, minor; glXQueryVersion(system->x11display, &major, &minor); d->glx_version = major * 100 + minor * 10; ALLEGRO_INFO("GLX %.1f.\n", d->glx_version / 100.f); display->w = w; display->h = h; display->vt = _al_display_xglx_driver(); display->refresh_rate = al_get_new_display_refresh_rate(); display->flags = al_get_new_display_flags(); // FIXME: default? Is this the right place to set this? display->flags |= ALLEGRO_OPENGL; // store our initial virtual adapter, used by fullscreen and positioning code d->adapter = adapter; ALLEGRO_DEBUG("selected adapter %i\n", adapter); if (d->adapter < 0) { d->adapter = _al_xglx_get_default_adapter(system); } _al_xglx_use_adapter(system, d->adapter); /* if we're in multi-head X mode, bail if we try to use more than one display * as there are bugs in X/glX that cause us to hang in X if we try to use more than one. */ /* if we're in real xinerama mode, also bail, x makes mouse use evil */ bool true_xinerama_active = false; #ifdef ALLEGRO_XWINDOWS_WITH_XINERAMA bool xrandr_active = false; #ifdef ALLEGRO_XWINDOWS_WITH_XRANDR xrandr_active = system->xrandr_available; #endif true_xinerama_active = !xrandr_active && system->xinerama_available; #endif if ((true_xinerama_active || ScreenCount(system->x11display) > 1) && system->adapter_use_count) { uint32_t i, adapter_use_count = 0; for (i = 0; i < 32; i++) { if (system->adapter_map[i]) adapter_use_count++; } if (adapter_use_count > 1) { ALLEGRO_ERROR("Use of more than one adapter at once in multi-head X or X with true Xinerama active is not possible.\n"); al_free(d); al_free(ogl); _al_mutex_unlock(&system->lock); return NULL; } } ALLEGRO_DEBUG("xdpy: selected adapter %i\n", d->adapter); // store or initial X Screen, used by window creation, fullscreen, and glx visual code d->xscreen = _al_xglx_get_xscreen(system, d->adapter); ALLEGRO_DEBUG("xdpy: selected xscreen %i\n", d->xscreen); d->is_mapped = false; _al_cond_init(&d->mapped); d->resize_count = 0; d->programmatic_resize = false; _al_xglx_config_select_visual(d); if (!d->xvinfo) { ALLEGRO_ERROR("FIXME: Need better visual selection.\n"); ALLEGRO_ERROR("No matching visual found.\n"); al_free(d); al_free(ogl); _al_mutex_unlock(&system->lock); return NULL; } ALLEGRO_INFO("Selected X11 visual %lu.\n", d->xvinfo->visualid); /* Add ourself to the list of displays. */ ALLEGRO_DISPLAY_XGLX **add; add = _al_vector_alloc_back(&system->system.displays); *add = d; /* Each display is an event source. */ _al_event_source_init(&display->es); /* Create a colormap. */ Colormap cmap = XCreateColormap(system->x11display, RootWindow(system->x11display, d->xvinfo->screen), d->xvinfo->visual, AllocNone); /* Create an X11 window */ XSetWindowAttributes swa; int mask = CWBorderPixel | CWColormap | CWEventMask; swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | ExposureMask | PropertyChangeMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; /* For a non-compositing window manager, a black background can look * less broken if the application doesn't react to expose events fast * enough. However in some cases like resizing, the black background * causes horrible flicker. */ if (!(display->flags & ALLEGRO_RESIZABLE)) { mask |= CWBackPixel; swa.background_pixel = BlackPixel(system->x11display, d->xvinfo->screen); } int x_off = INT_MAX, y_off = INT_MAX; if (display->flags & ALLEGRO_FULLSCREEN) { _al_xglx_get_display_offset(system, d->adapter, &x_off, &y_off); } else { /* we want new_display_adapter's offset to add to the new_window_position */ int xscr_x = 0, xscr_y = 0; al_get_new_window_position(&x_off, &y_off); if (adapter >= 0) { /* non default adapter. I'm assuming this means the user wants the window to be placed on the adapter offset by new display pos */ _al_xglx_get_display_offset(system, d->adapter, &xscr_x, &xscr_y); if (x_off != INT_MAX) x_off += xscr_x; if (y_off != INT_MAX) y_off += xscr_y; } } d->window = XCreateWindow(system->x11display, RootWindow(system->x11display, d->xvinfo->screen), x_off != INT_MAX ? x_off : 0, y_off != INT_MAX ? y_off : 0, w, h, 0, d->xvinfo->depth, InputOutput, d->xvinfo->visual, mask, &swa); // Try to set full screen mode if requested, fail if we can't if (display->flags & ALLEGRO_FULLSCREEN) { /* According to the spec, the window manager is supposed to disable * window decorations when _NET_WM_STATE_FULLSCREEN is in effect. * However, some WMs may not be fully compliant, e.g. Fluxbox. */ xdpy_set_frame(display, false); _al_xglx_set_above(display, 1); if (!_al_xglx_fullscreen_set_mode(system, d, w, h, 0, display->refresh_rate)) { ALLEGRO_DEBUG("xdpy: failed to set fullscreen mode.\n"); xdpy_destroy_display(display); _al_mutex_unlock(&system->lock); return NULL; } //XSync(system->x11display, False); } if (display->flags & ALLEGRO_FRAMELESS) { xdpy_set_frame(display, false); } ALLEGRO_DEBUG("X11 window created.\n"); _al_xwin_set_size_hints(display, x_off, y_off); XLockDisplay(system->x11display); d->wm_delete_window_atom = XInternAtom(system->x11display, "WM_DELETE_WINDOW", False); XSetWMProtocols(system->x11display, d->window, &d->wm_delete_window_atom, 1); XMapWindow(system->x11display, d->window); ALLEGRO_DEBUG("X11 window mapped.\n"); XUnlockDisplay(system->x11display); /* Send the pending request to the X server. */ XSync(system->x11display, False); /* To avoid race conditions where some X11 functions fail before the window * is mapped, we wait here until it is mapped. Note that the thread is * locked, so the event could not possibly have been processed yet in the * events thread. So as long as no other map events occur, the condition * should only be signalled when our window gets mapped. */ while (!d->is_mapped) { _al_cond_wait(&d->mapped, &system->lock); } /* We can do this at any time, but if we already have a mapped * window when switching to fullscreen it will use the same * monitor (with the MetaCity version I'm using here right now). */ if ((display->flags & ALLEGRO_FULLSCREEN_WINDOW)) { ALLEGRO_INFO("Toggling fullscreen flag for %d x %d window.\n", display->w, display->h); _al_xwin_reset_size_hints(display); _al_xwin_set_fullscreen_window(display, 2); _al_xwin_set_size_hints(display, INT_MAX, INT_MAX); XWindowAttributes xwa; XGetWindowAttributes(system->x11display, d->window, &xwa); display->w = xwa.width; display->h = xwa.height; ALLEGRO_INFO("Using ALLEGRO_FULLSCREEN_WINDOW of %d x %d\n", display->w, display->h); } if (display->flags & ALLEGRO_FULLSCREEN) { /* kwin wants these here */ /* metacity wants these here too */ /* XXX compiz is quiky, can't seem to find a combination of hints that * make sure we are layerd over panels, and are positioned properly */ //_al_xwin_set_fullscreen_window(display, 1); _al_xglx_set_above(display, 1); _al_xglx_fullscreen_to_display(system, d); /* Grab mouse if we only have one display, ungrab it if we have more than * one. */ if (_al_vector_size(&system->system.displays) == 1) { al_grab_mouse(display); } else if (_al_vector_size(&system->system.displays) > 1) { al_ungrab_mouse(); } } if (!_al_xglx_config_create_context(d)) { xdpy_destroy_display(display); _al_mutex_unlock(&system->lock); return NULL; } /* Make our GLX context current for reading and writing in the current * thread. */ if (d->fbc) { if (!glXMakeContextCurrent(system->gfxdisplay, d->glxwindow, d->glxwindow, d->context)) { ALLEGRO_ERROR("glXMakeContextCurrent failed\n"); } } else { if (!glXMakeCurrent(system->gfxdisplay, d->glxwindow, d->context)) { ALLEGRO_ERROR("glXMakeCurrent failed\n"); } } _al_ogl_manage_extensions(display); _al_ogl_set_extensions(ogl->extension_api); /* Print out OpenGL version info */ ALLEGRO_INFO("OpenGL Version: %s\n", (const char*)glGetString(GL_VERSION)); ALLEGRO_INFO("Vendor: %s\n", (const char*)glGetString(GL_VENDOR)); ALLEGRO_INFO("Renderer: %s\n", (const char*)glGetString(GL_RENDERER)); if (display->ogl_extras->ogl_info.version < _ALLEGRO_OPENGL_VERSION_1_2) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = _al_get_new_display_settings(); if (eds->required & (1<<ALLEGRO_COMPATIBLE_DISPLAY)) { ALLEGRO_ERROR("Allegro requires at least OpenGL version 1.2 to work.\n"); xdpy_destroy_display(display); _al_mutex_unlock(&system->lock); return NULL; } display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY] = 0; } #if 0 // Apparently, you can get a OpenGL 3.0 context without specifically creating // it with glXCreateContextAttribsARB, and not every OpenGL 3.0 is evil, but we // can't tell the difference at this stage. else if (display->ogl_extras->ogl_info.version > _ALLEGRO_OPENGL_VERSION_2_1) { /* We don't have OpenGL3 a driver. */ display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY] = 0; } #endif if (display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY]) _al_ogl_setup_gl(display); /* vsync */ /* Fill in the user setting. */ display->extra_settings.settings[ALLEGRO_VSYNC] = _al_get_new_display_settings()->settings[ALLEGRO_VSYNC]; /* We set the swap interval to 0 if vsync is forced off, and to 1 * if it is forced on. * http://www.opengl.org/registry/specs/SGI/swap_control.txt * If the option is set to 0, we simply use the system default. The * above extension specifies vsync on as default though, so in the * end with GLX we can't force vsync on, just off. */ ALLEGRO_DEBUG("requested vsync=%d.\n", display->extra_settings.settings[ALLEGRO_VSYNC]); if (display->extra_settings.settings[ALLEGRO_VSYNC]) { if (display->ogl_extras->extension_list->ALLEGRO_GLX_SGI_swap_control) { int x = 1; if (display->extra_settings.settings[ALLEGRO_VSYNC] == 2) x = 0; if (glXSwapIntervalSGI(x)) { ALLEGRO_WARN("glXSwapIntervalSGI(%d) failed.\n", x); } } else { ALLEGRO_WARN("no vsync, GLX_SGI_swap_control missing.\n"); /* According to the specification that means it's on, but * the driver might have disabled it. So we do not know. */ display->extra_settings.settings[ALLEGRO_VSYNC] = 0; } } d->invisible_cursor = None; /* Will be created on demand. */ d->current_cursor = None; /* Initially, we use the root cursor. */ d->cursor_hidden = false; d->icon = None; d->icon_mask = None; _al_mutex_unlock(&system->lock); return display; }
static ALLEGRO_DISPLAY_XGLX *xdpy_create_display_locked( ALLEGRO_SYSTEM_XGLX *system, int flags, int w, int h, int adapter) { ALLEGRO_DISPLAY_XGLX *d = al_calloc(1, sizeof *d); ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)d; ALLEGRO_OGL_EXTRAS *ogl = al_calloc(1, sizeof *ogl); display->ogl_extras = ogl; d->glx_version = query_glx_version(system); display->w = w; display->h = h; display->vt = _al_display_xglx_driver(); display->refresh_rate = al_get_new_display_refresh_rate(); display->flags = flags; // FIXME: default? Is this the right place to set this? display->flags |= ALLEGRO_OPENGL; /* Store our initial virtual adapter, used by fullscreen and positioning * code. */ ALLEGRO_DEBUG("selected adapter %i\n", adapter); if (adapter < 0) d->adapter = _al_xglx_get_default_adapter(system); else d->adapter = adapter; ALLEGRO_DEBUG("xdpy: selected adapter %i\n", d->adapter); _al_xglx_use_adapter(system, d->adapter); if (!check_adapter_use_count(system)) { goto EarlyError; } /* Store our initial X Screen, used by window creation, fullscreen, and glx * visual code. */ d->xscreen = _al_xglx_get_xscreen(system, d->adapter); ALLEGRO_DEBUG("xdpy: selected xscreen %i\n", d->xscreen); d->wm_delete_window_atom = None; d->is_mapped = false; _al_cond_init(&d->mapped); d->is_selectioned = false; _al_cond_init(&d->selectioned); d->resize_count = 0; d->programmatic_resize = false; _al_xglx_config_select_visual(d); if (!d->xvinfo) { ALLEGRO_ERROR("FIXME: Need better visual selection.\n"); ALLEGRO_ERROR("No matching visual found.\n"); goto EarlyError; } ALLEGRO_INFO("Selected X11 visual %lu.\n", d->xvinfo->visualid); /* Add ourself to the list of displays. */ ALLEGRO_DISPLAY_XGLX **add; add = _al_vector_alloc_back(&system->system.displays); *add = d; /* Each display is an event source. */ _al_event_source_init(&display->es); if (!xdpy_create_display_window(system, d, w, h, adapter)) { goto LateError; } /* Send any pending requests to the X server. * This is necessary to make the window ID immediately valid * for a GtkSocket. */ XSync(system->x11display, False); if (display->flags & ALLEGRO_GTK_TOPLEVEL_INTERNAL) { ASSERT(gtk_override_vt); if (!gtk_override_vt->create_display_hook(display, w, h)) { goto LateError; } } else { default_overridable_vt.set_window_title(display, al_get_new_window_title()); if (!default_overridable_vt.create_display_hook(display, w, h)) { goto LateError; } } /* overridable_vt should be set by the create_display_hook. */ ASSERT(d->overridable_vt); /* Send any pending requests to the X server. */ XSync(system->x11display, False); /* To avoid race conditions where some X11 functions fail before the window * is mapped, we wait here until it is mapped. Note that the thread is * locked, so the event could not possibly have been processed yet in the * events thread. So as long as no other map events occur, the condition * should only be signalled when our window gets mapped. */ while (!d->is_mapped) { _al_cond_wait(&d->mapped, &system->lock); } /* In tiling WMs, we might get resize events pretty much immediately after * Window creation. This location seems to catch them reliably, tested with * dwm, awesome, xmonad and i3. */ if ((display->flags & ALLEGRO_RESIZABLE) && d->resize_count > 0) { xdpy_acknowledge_resize(display); } /* We can do this at any time, but if we already have a mapped * window when switching to fullscreen it will use the same * monitor (with the MetaCity version I'm using here right now). */ if ((display->flags & ALLEGRO_FULLSCREEN_WINDOW)) { ALLEGRO_INFO("Toggling fullscreen flag for %d x %d window.\n", display->w, display->h); _al_xwin_reset_size_hints(display); _al_xwin_set_fullscreen_window(display, 2); _al_xwin_set_size_hints(display, INT_MAX, INT_MAX); XWindowAttributes xwa; XGetWindowAttributes(system->x11display, d->window, &xwa); display->w = xwa.width; display->h = xwa.height; ALLEGRO_INFO("Using ALLEGRO_FULLSCREEN_WINDOW of %d x %d\n", display->w, display->h); } if (display->flags & ALLEGRO_FULLSCREEN) { /* kwin wants these here */ /* metacity wants these here too */ /* XXX compiz is quiky, can't seem to find a combination of hints that * make sure we are layerd over panels, and are positioned properly */ //_al_xwin_set_fullscreen_window(display, 1); _al_xwin_set_above(display, 1); _al_xglx_fullscreen_to_display(system, d); /* Grab mouse if we only have one display, ungrab it if we have more than * one. */ if (_al_vector_size(&system->system.displays) == 1) { al_grab_mouse(display); } else if (_al_vector_size(&system->system.displays) > 1) { al_ungrab_mouse(); } } if (flags & ALLEGRO_MAXIMIZED) { _al_xwin_maximize(display, true); } if (!_al_xglx_config_create_context(d)) { goto LateError; } /* Make our GLX context current for reading and writing in the current * thread. */ if (d->fbc) { if (!glXMakeContextCurrent(system->gfxdisplay, d->glxwindow, d->glxwindow, d->context)) { ALLEGRO_ERROR("glXMakeContextCurrent failed\n"); } } else { if (!glXMakeCurrent(system->gfxdisplay, d->glxwindow, d->context)) { ALLEGRO_ERROR("glXMakeCurrent failed\n"); } } _al_ogl_manage_extensions(display); _al_ogl_set_extensions(ogl->extension_api); /* Print out OpenGL version info */ ALLEGRO_INFO("OpenGL Version: %s\n", (const char*)glGetString(GL_VERSION)); ALLEGRO_INFO("Vendor: %s\n", (const char*)glGetString(GL_VENDOR)); ALLEGRO_INFO("Renderer: %s\n", (const char*)glGetString(GL_RENDERER)); if (display->ogl_extras->ogl_info.version < _ALLEGRO_OPENGL_VERSION_1_2) { ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = _al_get_new_display_settings(); if (eds->required & (1<<ALLEGRO_COMPATIBLE_DISPLAY)) { ALLEGRO_ERROR("Allegro requires at least OpenGL version 1.2 to work.\n"); goto LateError; } display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY] = 0; } if (display->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY]) _al_ogl_setup_gl(display); /* vsync */ int vsync_setting = _al_get_new_display_settings()->settings[ALLEGRO_VSYNC]; vsync_setting = xdpy_swap_control(display, vsync_setting); display->extra_settings.settings[ALLEGRO_VSYNC] = vsync_setting; d->invisible_cursor = None; /* Will be created on demand. */ d->current_cursor = None; /* Initially, we use the root cursor. */ d->cursor_hidden = false; d->icon = None; d->icon_mask = None; return d; EarlyError: al_free(d); al_free(ogl); return NULL; LateError: xdpy_destroy_display(display); return NULL; }