diff options
author | Hans de Goede <jwrdegoede@fedoraproject.org> | 2018-10-31 15:04:55 +0000 |
---|---|---|
committer | Hans de Goede <jwrdegoede@fedoraproject.org> | 2018-10-31 15:04:55 +0000 |
commit | 025ce598252c6a08738e0efbc3512500b668a94b (patch) | |
tree | 92c713c267ba85225e923f2a02dfcf402fcef04c | |
parent | b4f751b5f1f400c3135a7f8f693ae7409e9fd530 (diff) | |
parent | da2c99707235ec3d2206d120d8852f8c4259b04f (diff) |
Merge branch 'drm-preferred-mode' into 'master'0.9.4
drm: use preferred mode for outputs
Closes #68 and #59
See merge request plymouth/plymouth!4
-rw-r--r-- | src/client/plymouth.c | 34 | ||||
-rw-r--r-- | src/libply/ply-utils.c | 94 | ||||
-rw-r--r-- | src/libply/ply-utils.h | 4 | ||||
-rw-r--r-- | src/main.c | 137 | ||||
-rw-r--r-- | src/plugins/renderers/drm/plugin.c | 137 |
5 files changed, 234 insertions, 172 deletions
diff --git a/src/client/plymouth.c b/src/client/plymouth.c index 46a64f54..8e613def 100644 --- a/src/client/plymouth.c +++ b/src/client/plymouth.c @@ -49,7 +49,6 @@ typedef struct ply_event_loop_t *loop; ply_boot_client_t *client; ply_command_parser_t *command_parser; - char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; } state_t; typedef struct @@ -704,31 +703,6 @@ on_quit_request (state_t *state, on_failure, state); } -static bool -get_kernel_command_line (state_t *state) -{ - int fd; - - ply_trace ("opening /proc/cmdline"); - fd = open ("/proc/cmdline", O_RDONLY); - - if (fd < 0) { - ply_trace ("couldn't open it: %m"); - return false; - } - - ply_trace ("reading kernel command line"); - if (read (fd, state->kernel_command_line, sizeof(state->kernel_command_line) - 1) < 0) { - ply_trace ("couldn't read it: %m"); - close (fd); - return false; - } - - ply_trace ("Kernel command line is: '%s'", state->kernel_command_line); - close (fd); - return true; -} - static void on_update_root_fs_request (state_t *state, const char *command) @@ -1099,12 +1073,8 @@ main (int argc, return 0; } - if (get_kernel_command_line (&state)) { - if ((strstr (state.kernel_command_line, "plymouth.debug") != NULL || - strstr (state.kernel_command_line, "plymouth:debug") != NULL) - && !ply_is_tracing ()) - ply_toggle_tracing (); - } + if (ply_kernel_command_line_has_argument ("plymouth.debug") && !ply_is_tracing ()) + ply_toggle_tracing (); if (should_be_verbose && !ply_is_tracing ()) ply_toggle_tracing (); diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 89e37e93..c17e0c85 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -24,6 +24,7 @@ #include "ply-utils.h" #include <assert.h> +#include <ctype.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> @@ -80,6 +81,9 @@ static int errno_stack_position = 0; static int overridden_device_scale = 0; +static char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; +static bool kernel_command_line_is_set; + bool ply_open_unidirectional_pipe (int *sender_fd, int *receiver_fd) @@ -1015,4 +1019,94 @@ ply_get_device_scale (uint32_t width, return device_scale; } +static const char * +ply_get_kernel_command_line (void) +{ + const char *remaining_command_line; + char *key; + int fd; + + if (kernel_command_line_is_set) + return kernel_command_line; + + ply_trace ("opening /proc/cmdline"); + fd = open ("/proc/cmdline", O_RDONLY); + + if (fd < 0) { + ply_trace ("couldn't open it: %m"); + return NULL; + } + + ply_trace ("reading kernel command line"); + if (read (fd, kernel_command_line, sizeof(kernel_command_line) - 1) < 0) { + ply_trace ("couldn't read it: %m"); + close (fd); + return NULL; + } + + /* we now use plymouth.argument for kernel commandline arguments. + * It used to be plymouth:argument. This bit just rewrites all : to be . + */ + remaining_command_line = kernel_command_line; + while ((key = strstr (remaining_command_line, "plymouth:")) != NULL) { + char *colon; + + colon = key + strlen ("plymouth"); + *colon = '.'; + + remaining_command_line = colon + 1; + } + ply_trace ("Kernel command line is: '%s'", kernel_command_line); + + close (fd); + + kernel_command_line_is_set = true; + return kernel_command_line; +} + +const char * +ply_kernel_command_line_get_string_after_prefix (const char *prefix) +{ + const char *command_line = ply_get_kernel_command_line(); + char *argument; + + if (!command_line) + return NULL; + + argument = strstr (command_line, prefix); + + if (argument == NULL) + return NULL; + + if (argument == command_line || + argument[-1] == ' ') + return argument + strlen (prefix); + + return NULL; +} + +bool +ply_kernel_command_line_has_argument (const char *argument) +{ + const char *string; + + string = ply_kernel_command_line_get_string_after_prefix (argument); + + if (string == NULL) + return false; + + if (!isspace ((int) string[0]) && string[0] != '\0') + return false; + + return true; +} + +void +ply_kernel_command_line_override (const char *command_line) +{ + strncpy (kernel_command_line, command_line, sizeof(kernel_command_line)); + kernel_command_line[sizeof(kernel_command_line) - 1] = '\0'; + kernel_command_line_is_set = true; +} + /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index c46603ee..ae4776e2 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -128,6 +128,10 @@ int ply_get_device_scale (uint32_t width, uint32_t width_mm, uint32_t height_mm); +const char *ply_kernel_command_line_get_string_after_prefix (const char *prefix); +bool ply_kernel_command_line_has_argument (const char *argument); +void ply_kernel_command_line_override (const char *command_line); + #endif #endif /* PLY_UTILS_H */ @@ -24,7 +24,6 @@ #include <sys/stat.h> #include <sys/types.h> #include <math.h> -#include <ctype.h> #include <limits.h> #include <dirent.h> #include <fcntl.h> @@ -56,10 +55,6 @@ #include "ply-utils.h" #include "ply-progress.h" -#ifndef PLY_MAX_COMMAND_LINE_SIZE -#define PLY_MAX_COMMAND_LINE_SIZE 4097 -#endif - #define BOOT_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/boot-duration" #define SHUTDOWN_DURATION_FILE PLYMOUTH_TIME_DIRECTORY "/shutdown-duration" @@ -109,8 +104,6 @@ typedef struct double splash_delay; double device_timeout; - char kernel_command_line[PLY_MAX_COMMAND_LINE_SIZE]; - uint32_t kernel_command_line_is_set : 1; uint32_t no_boot_log : 1; uint32_t showing_details : 1; uint32_t system_initialized : 1; @@ -386,41 +379,6 @@ show_detailed_splash (state_t *state) update_display (state); } -static const char * -command_line_get_string_after_prefix (const char *command_line, - const char *prefix) -{ - char *argument; - - argument = strstr (command_line, prefix); - - if (argument == NULL) - return NULL; - - if (argument == command_line || - argument[-1] == ' ') - return argument + strlen (prefix); - - return NULL; -} - -static bool -command_line_has_argument (const char *command_line, - const char *argument) -{ - const char *string; - - string = command_line_get_string_after_prefix (command_line, argument); - - if (string == NULL) - return false; - - if (!isspace ((int) string[0]) && string[0] != '\0') - return false; - - return true; -} - static void find_override_splash (state_t *state) { @@ -429,8 +387,7 @@ find_override_splash (state_t *state) if (state->override_splash_path != NULL) return; - splash_string = command_line_get_string_after_prefix (state->kernel_command_line, - "plymouth.splash="); + splash_string = ply_kernel_command_line_get_string_after_prefix ("plymouth.splash="); if (splash_string != NULL) { const char *end; @@ -457,7 +414,7 @@ find_override_splash (state_t *state) if (isnan (state->splash_delay)) { const char *delay_string; - delay_string = command_line_get_string_after_prefix (state->kernel_command_line, "plymouth.splash-delay="); + delay_string = ply_kernel_command_line_get_string_after_prefix ("plymouth.splash-delay="); if (delay_string != NULL) state->splash_delay = atof (delay_string); @@ -469,7 +426,7 @@ find_force_scale (state_t *state) { const char *scale_string; - scale_string = command_line_get_string_after_prefix (state->kernel_command_line, "plymouth.force-scale="); + scale_string = ply_kernel_command_line_get_string_after_prefix ("plymouth.force-scale="); if (scale_string != NULL) ply_set_device_scale (strtoul (scale_string, NULL, 0)); @@ -884,10 +841,10 @@ static bool plymouth_should_ignore_show_splash_calls (state_t *state) { ply_trace ("checking if plymouth should be running"); - if (state->mode != PLY_MODE_BOOT || command_line_has_argument (state->kernel_command_line, "plymouth.force-splash")) + if (state->mode != PLY_MODE_BOOT || ply_kernel_command_line_has_argument ("plymouth.force-splash")) return false; - if (command_line_has_argument (state->kernel_command_line, "plymouth.ignore-show-splash")) + if (ply_kernel_command_line_has_argument ("plymouth.ignore-show-splash")) return true; return false; @@ -899,7 +856,7 @@ sh_is_init (state_t *state) const char *init_string; size_t length; - init_string = command_line_get_string_after_prefix (state->kernel_command_line, "init="); + init_string = ply_kernel_command_line_get_string_after_prefix ("init="); if (init_string) { length = strcspn (init_string, " \n"); @@ -924,28 +881,28 @@ plymouth_should_show_default_splash (state_t *state) return false; for (i = 0; strings[i] != NULL; i++) { - if (command_line_has_argument (state->kernel_command_line, strings[i])) { + if (ply_kernel_command_line_has_argument (strings[i])) { ply_trace ("no default splash because kernel command line has option \"%s\"", strings[i]); return false; } } - if (command_line_has_argument (state->kernel_command_line, "splash=verbose")) { + if (ply_kernel_command_line_has_argument ("splash=verbose")) { ply_trace ("no default splash because kernel command line has option \"splash=verbose\""); return false; } - if (command_line_has_argument (state->kernel_command_line, "rhgb")) { + if (ply_kernel_command_line_has_argument ("rhgb")) { ply_trace ("using default splash because kernel command line has option \"rhgb\""); return true; } - if (command_line_has_argument (state->kernel_command_line, "splash")) { + if (ply_kernel_command_line_has_argument ("splash")) { ply_trace ("using default splash because kernel command line has option \"splash\""); return true; } - if (command_line_has_argument (state->kernel_command_line, "splash=silent")) { + if (ply_kernel_command_line_has_argument ("splash=silent")) { ply_trace ("using default splash because kernel command line has option \"splash=silent\""); return true; } @@ -1284,7 +1241,7 @@ deactivate_console (state_t *state) } /* do not let any tty opened where we could write after deactivate */ - if (command_line_has_argument (state->kernel_command_line, "plymouth.debug")) + if (ply_kernel_command_line_has_argument ("plymouth.debug")) ply_logger_close_file (ply_logger_get_error_default ()); } @@ -1880,52 +1837,6 @@ detach_from_running_session (state_t *state) state->is_attached = false; } -static bool -get_kernel_command_line (state_t *state) -{ - int fd; - const char *remaining_command_line; - char *key; - - if (state->kernel_command_line_is_set) - return true; - - ply_trace ("opening /proc/cmdline"); - fd = open ("/proc/cmdline", O_RDONLY); - - if (fd < 0) { - ply_trace ("couldn't open it: %m"); - return false; - } - - ply_trace ("reading kernel command line"); - if (read (fd, state->kernel_command_line, sizeof(state->kernel_command_line) - 1) < 0) { - ply_trace ("couldn't read it: %m"); - close (fd); - return false; - } - - - /* we now use plymouth.argument for kernel commandline arguments. - * It used to be plymouth:argument. This bit just rewrites all : to be . - */ - remaining_command_line = state->kernel_command_line; - while ((key = strstr (remaining_command_line, "plymouth:")) != NULL) { - char *colon; - - colon = key + strlen ("plymouth"); - *colon = '.'; - - remaining_command_line = colon + 1; - } - ply_trace ("Kernel command line is: '%s'", state->kernel_command_line); - - close (fd); - - state->kernel_command_line_is_set = true; - return true; -} - static void check_verbosity (state_t *state) { @@ -1934,13 +1845,11 @@ check_verbosity (state_t *state) ply_trace ("checking if tracing should be enabled"); - stream = command_line_get_string_after_prefix (state->kernel_command_line, - "plymouth.debug=stream:"); + stream = ply_kernel_command_line_get_string_after_prefix ("plymouth.debug=stream:"); - path = command_line_get_string_after_prefix (state->kernel_command_line, - "plymouth.debug=file:"); + path = ply_kernel_command_line_get_string_after_prefix ("plymouth.debug=file:"); if (stream != NULL || path != NULL || - command_line_has_argument (state->kernel_command_line, "plymouth.debug")) { + ply_kernel_command_line_has_argument ("plymouth.debug")) { int fd; ply_trace ("tracing should be enabled!"); @@ -2018,7 +1927,7 @@ check_logging (state_t *state) ply_trace ("checking if console messages should be redirected and logged"); - kernel_no_log = command_line_has_argument (state->kernel_command_line, "plymouth.nolog"); + kernel_no_log = ply_kernel_command_line_has_argument ("plymouth.nolog"); if (kernel_no_log) state->no_boot_log = true; @@ -2072,9 +1981,6 @@ initialize_environment (state_t *state) { ply_trace ("initializing minimal work environment"); - if (!get_kernel_command_line (state)) - return false; - if (!state->default_tty) if (getenv ("DISPLAY") != NULL && access (PLYMOUTH_PLUGIN_PATH "renderers/x11.so", F_OK) == 0) state->default_tty = "/dev/tty"; @@ -2287,11 +2193,8 @@ main (int argc, if (tty != NULL) state.default_tty = tty; - if (kernel_command_line != NULL) { - strncpy (state.kernel_command_line, kernel_command_line, sizeof(state.kernel_command_line)); - state.kernel_command_line[sizeof(state.kernel_command_line) - 1] = '\0'; - state.kernel_command_line_is_set = true; - } + if (kernel_command_line != NULL) + ply_kernel_command_line_override (kernel_command_line); if (geteuid () != 0) { ply_error ("plymouthd must be run as root user"); @@ -2383,10 +2286,10 @@ main (int argc, find_system_default_splash (&state); find_distribution_default_splash (&state); - if (command_line_has_argument (state.kernel_command_line, "plymouth.ignore-serial-consoles")) + if (ply_kernel_command_line_has_argument ("plymouth.ignore-serial-consoles")) device_manager_flags |= PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES; - if (command_line_has_argument (state.kernel_command_line, "plymouth.ignore-udev") || + if (ply_kernel_command_line_has_argument ("plymouth.ignore-udev") || (getenv ("DISPLAY") != NULL)) device_manager_flags |= PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV; diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index 1080590e..1ff2b295 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -84,6 +84,9 @@ struct _ply_renderer_head uint32_t encoder_id; uint32_t console_buffer_id; uint32_t scan_out_buffer_id; + + int gamma_size; + uint16_t *gamma; }; struct _ply_renderer_input_source @@ -134,6 +137,7 @@ struct _ply_renderer_backend uint32_t is_active : 1; uint32_t requires_explicit_flushing : 1; + uint32_t use_preferred_mode : 1; }; ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void); @@ -146,6 +150,36 @@ static bool reset_scan_out_buffer_if_needed (ply_renderer_backend_t *backend, static void flush_head (ply_renderer_backend_t *backend, ply_renderer_head_t *head); +static bool efi_enabled (void) +{ + return ply_directory_exists ("/sys/firmware/efi/efivars"); +} + +/* A small helper to determine if we should try to keep the current mode + * or pick the best mode ourselves, we keep the current mode if: + * 1. The user specified a specific mode using video= on the commandline + * 2. The code to pick the best mode was added because with flicker-free boot + * we can no longer rely on the kernel's fbcon code setting things up. + * We should be able to do a better job then fbcon regardless, but for + * now lets only use the new code on flicker-free systems until it is + * more mature, this means only using it on UEFI systems. + */ +static bool +should_use_preferred_mode (void) +{ + bool use_preferred_mode = true; + + if (ply_kernel_command_line_get_string_after_prefix ("video=")) + use_preferred_mode = false; + + if (!efi_enabled ()) + use_preferred_mode = false; + + ply_trace ("should_use_preferred_mode: %d", use_preferred_mode); + + return use_preferred_mode; +} + static bool ply_renderer_buffer_map (ply_renderer_backend_t *backend, ply_renderer_buffer_t *buffer) @@ -373,7 +407,7 @@ destroy_output_buffer (ply_renderer_backend_t *backend, ply_renderer_buffer_free (backend, buffer); } -static int +static ply_pixel_buffer_rotation_t connector_orientation_prop_to_rotation (drmModePropertyPtr prop, int orientation) { @@ -395,12 +429,17 @@ connector_orientation_prop_to_rotation (drmModePropertyPtr prop, return PLY_PIXEL_BUFFER_ROTATE_UPRIGHT; } -static int -ply_renderer_connector_get_rotation (ply_renderer_backend_t *backend, - drmModeConnector *connector) +static void +ply_renderer_connector_get_rotation_and_tiled (ply_renderer_backend_t *backend, + drmModeConnector *connector, + ply_pixel_buffer_rotation_t *rotation, + bool *tiled) { drmModePropertyPtr prop; - int i, rotation; + int i; + + *rotation = PLY_PIXEL_BUFFER_ROTATE_UPRIGHT; + *tiled = false; for (i = 0; i < connector->count_props; i++) { prop = drmModeGetProperty (backend->device_fd, connector->props[i]); @@ -408,16 +447,15 @@ ply_renderer_connector_get_rotation (ply_renderer_backend_t *backend, continue; if ((prop->flags & DRM_MODE_PROP_ENUM) && - strcmp (prop->name, "panel orientation") == 0) { - rotation = connector_orientation_prop_to_rotation (prop, connector->prop_values[i]); - drmModeFreeProperty (prop); - return rotation; - } + strcmp (prop->name, "panel orientation") == 0) + *rotation = connector_orientation_prop_to_rotation (prop, connector->prop_values[i]); + + if ((prop->flags & DRM_MODE_PROP_BLOB) && + strcmp (prop->name, "TILE") == 0) + *tiled = true; drmModeFreeProperty (prop); } - - return PLY_PIXEL_BUFFER_ROTATE_UPRIGHT; } static bool @@ -446,16 +484,18 @@ ply_renderer_head_add_connector (ply_renderer_head_t *head, } static ply_renderer_head_t * -ply_renderer_head_new (ply_renderer_backend_t *backend, - drmModeConnector *connector, - int connector_mode_index, - uint32_t encoder_id, - uint32_t controller_id, - uint32_t console_buffer_id) +ply_renderer_head_new (ply_renderer_backend_t *backend, + drmModeConnector *connector, + int connector_mode_index, + uint32_t encoder_id, + uint32_t controller_id, + uint32_t console_buffer_id, + int gamma_size, + ply_pixel_buffer_rotation_t rotation) { ply_renderer_head_t *head; drmModeModeInfo *mode; - int rotation; + int i, step; head = calloc (1, sizeof(ply_renderer_head_t)); @@ -476,10 +516,21 @@ ply_renderer_head_new (ply_renderer_backend_t *backend, head->area.width = mode->hdisplay; head->area.height = mode->vdisplay; + if (gamma_size) { + head->gamma_size = gamma_size; + head->gamma = malloc (gamma_size * 3 * sizeof(uint16_t)); + + step = UINT16_MAX / (gamma_size - 1); + for (i = 0; i < gamma_size; i++) { + head->gamma[0 * gamma_size + i] = i * step; /* red */ + head->gamma[1 * gamma_size + i] = i * step; /* green */ + head->gamma[2 * gamma_size + i] = i * step; /* blue */ + } + } + ply_renderer_head_add_connector (head, connector, connector_mode_index); assert (ply_array_get_size (head->connector_ids) > 0); - rotation = ply_renderer_connector_get_rotation (backend, connector); head->pixel_buffer = ply_pixel_buffer_new_with_device_rotation (head->area.width, head->area.height, rotation); ply_pixel_buffer_set_device_scale (head->pixel_buffer, ply_get_device_scale (head->area.width, @@ -502,6 +553,7 @@ ply_renderer_head_free (ply_renderer_head_t *head) drmModeFreeConnector (head->connector0); ply_array_free (head->connector_ids); + free (head->gamma); free (head); } @@ -601,6 +653,18 @@ ply_renderer_head_set_scan_out_buffer (ply_renderer_backend_t *backend, ply_trace ("Setting scan out buffer of %ldx%ld head to our buffer", head->area.width, head->area.height); + /* Set gamma table, do this only once */ + if (head->gamma) { + drmModeCrtcSetGamma (backend->device_fd, + head->controller_id, + head->gamma_size, + head->gamma + 0 * head->gamma_size, + head->gamma + 1 * head->gamma_size, + head->gamma + 2 * head->gamma_size); + free (head->gamma); + head->gamma = NULL; + } + /* Tell the controller to use the allocated scan out buffer on each connectors */ if (drmModeSetCrtc (backend->device_fd, head->controller_id, buffer_id, @@ -743,6 +807,7 @@ create_backend (const char *device_name, backend->requires_explicit_flushing = true; backend->output_buffers = ply_hashtable_new (ply_hashtable_direct_hash, ply_hashtable_direct_compare); + backend->use_preferred_mode = should_use_preferred_mode (); return backend; } @@ -992,6 +1057,22 @@ find_index_of_mode (ply_renderer_backend_t *backend, } static int +get_index_of_preferred_mode (drmModeConnector *connector) +{ + int i; + + for (i = 0; i < connector->count_modes; i++) + if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) { + ply_trace ("Found preferred mode %dx%d at index %d\n", + connector->modes[i].hdisplay, + connector->modes[i].vdisplay, i); + return i; + } + + return -1; +} + +static int get_index_of_active_mode (ply_renderer_backend_t *backend, drmModeCrtc *controller, drmModeConnector *connector) @@ -1023,7 +1104,10 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend) drmModeCrtc *controller; uint32_t controller_id; uint32_t console_buffer_id; - int connector_mode_index; + int connector_mode_index = -1; + int gamma_size; + ply_pixel_buffer_rotation_t rotation; + bool tiled; connector = drmModeGetConnector (backend->device_fd, backend->resources->connectors[i]); @@ -1059,7 +1143,13 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend) controller_id = controller->crtc_id; - connector_mode_index = get_index_of_active_mode (backend, controller, connector); + ply_renderer_connector_get_rotation_and_tiled (backend, connector, &rotation, &tiled); + + if (!tiled && backend->use_preferred_mode) + connector_mode_index = get_index_of_preferred_mode (connector); + + if (connector_mode_index < 0) + connector_mode_index = get_index_of_active_mode (backend, controller, connector); /* If we couldn't find the current active mode, fall back to the first available. */ @@ -1069,6 +1159,7 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend) } console_buffer_id = controller->buffer_id; + gamma_size = controller->gamma_size; drmModeFreeCrtc (controller); head = ply_hashtable_lookup (heads_by_controller_id, @@ -1077,7 +1168,7 @@ create_heads_for_active_connectors (ply_renderer_backend_t *backend) if (head == NULL) { head = ply_renderer_head_new (backend, connector, connector_mode_index, encoder_id, controller_id, - console_buffer_id); + console_buffer_id, gamma_size, rotation); ply_list_append_data (backend->heads, head); |