static void create_dummy_control_points(entity_state_t *entity_state) { rig_selection_tool_t *tool = entity_state->tool; cg_texture_t *tex = rut_load_texture_from_data_file(tool->shell, "dot.png", NULL); control_point_t *point; point = c_slice_new0(control_point_t); point->entity_state = entity_state; point->x = 0; point->y = 0; point->z = 0; point->transform = rut_transform_new(tool->shell); rut_graphable_add_child(tool->tool_overlay, point->transform); rut_object_unref(point->transform); point->marker = rut_nine_slice_new(tool->shell, tex, 0, 0, 0, 0, 10, 10); rut_graphable_add_child(point->transform, point->marker); rut_object_unref(point->marker); point->input_region = rut_input_region_new_circle(0, 0, 5, control_point_input_cb, point); rut_graphable_add_child(tool->tool_overlay, point->input_region); rut_object_unref(point->input_region); entity_state->control_points = c_llist_prepend(entity_state->control_points, point); point = c_slice_new0(control_point_t); point->entity_state = entity_state; point->x = 100; point->y = 0; point->z = 0; point->transform = rut_transform_new(tool->shell); rut_graphable_add_child(tool->tool_overlay, point->transform); rut_object_unref(point->transform); point->marker = rut_nine_slice_new(tool->shell, tex, 0, 0, 0, 0, 10, 10); rut_graphable_add_child(point->transform, point->marker); rut_object_unref(point->marker); point->input_region = rut_input_region_new_circle(0, 0, 5, control_point_input_cb, point); rut_graphable_add_child(tool->tool_overlay, point->input_region); rut_object_unref(point->input_region); entity_state->control_points = c_llist_prepend(entity_state->control_points, point); cg_object_unref(tex); }
static rut_input_event_status_t control_point_input_cb( rut_input_region_t *region, rut_input_event_t *event, void *user_data) { control_point_t *point = user_data; entity_state_t *entity_state = point->entity_state; rig_selection_tool_t *tool = entity_state->tool; c_return_val_if_fail(tool->selected_entities != NULL, RUT_INPUT_EVENT_STATUS_UNHANDLED); if (rut_input_event_get_type(event) == RUT_INPUT_EVENT_TYPE_MOTION && rut_motion_event_get_action(event) == RUT_MOTION_EVENT_ACTION_DOWN && rut_motion_event_get_button_state(event) == RUT_BUTTON_STATE_1) { // float x = rut_motion_event_get_x (event); // float y = rut_motion_event_get_y (event); grab_state_t *state = c_slice_new0(grab_state_t); state->tool = tool; state->entity_state = entity_state; state->point = point; rut_shell_grab_input(tool->shell, rut_input_event_get_camera(event), control_point_grab_cb, state); return RUT_INPUT_EVENT_STATUS_HANDLED; } return RUT_INPUT_EVENT_STATUS_UNHANDLED; }
cg_pixel_buffer_t *cg_pixel_buffer_new(cg_device_t *dev, size_t size, const void *data, cg_error_t **error) { cg_pixel_buffer_t *pixel_buffer = c_slice_new0(cg_pixel_buffer_t); cg_buffer_t *buffer = CG_BUFFER(pixel_buffer); /* parent's constructor */ _cg_buffer_initialize(buffer, dev, size, CG_BUFFER_BIND_TARGET_PIXEL_UNPACK, CG_BUFFER_USAGE_HINT_TEXTURE, CG_BUFFER_UPDATE_HINT_STATIC); _cg_pixel_buffer_object_new(pixel_buffer); if (data) { if (!cg_buffer_set_data( CG_BUFFER(pixel_buffer), 0, data, size, error)) { cg_object_unref(pixel_buffer); return NULL; } } return pixel_buffer; }
static bool _cg_winsys_renderer_connect(cg_renderer_t *renderer, cg_error_t **error) { cg_renderer_egl_t *egl_renderer; cg_xlib_renderer_t *xlib_renderer; renderer->winsys = c_slice_new0(cg_renderer_egl_t); egl_renderer = renderer->winsys; xlib_renderer = _cg_xlib_renderer_get_data(renderer); egl_renderer->platform_vtable = &_cg_winsys_egl_vtable; if (!_cg_xlib_renderer_connect(renderer, error)) goto error; egl_renderer->edpy = eglGetDisplay((NativeDisplayType)xlib_renderer->xdpy); if (!_cg_winsys_egl_renderer_connect_common(renderer, error)) goto error; return true; error: _cg_winsys_renderer_disconnect(renderer); return false; }
rig_selection_tool_t * rig_selection_tool_new(rig_camera_view_t *view, rut_object_t *overlay) { rig_selection_tool_t *tool = c_slice_new0(rig_selection_tool_t); rut_shell_t *shell = view->shell; tool->view = view; tool->shell = shell; /* Note: we don't take a reference on this overlay to avoid creating * a circular reference. */ tool->tool_overlay = overlay; tool->camera = view->view_camera; tool->camera_component = rig_entity_get_component(tool->camera, RIG_COMPONENT_TYPE_CAMERA); c_list_init(&tool->selection_event_cb_list); /* pipeline to draw the tool */ tool->default_pipeline = cg_pipeline_new(shell->cg_device); return tool; }
static bool _cg_winsys_renderer_connect(cg_renderer_t *renderer, cg_error_t **error) { renderer->winsys = c_slice_new0(cg_renderer_webgl_t); return true; }
cg_memory_stack_t * _cg_memory_stack_new(size_t initial_size_bytes) { cg_memory_stack_t *stack = c_slice_new0(cg_memory_stack_t); c_list_init(&stack->sub_stacks); _cg_memory_stack_add_sub_stack(stack, initial_size_bytes); return stack; }
static void objects_selection_event_cb(rig_objects_selection_t *selection, rig_objects_selection_event_t event, rut_object_t *object, void *user_data) { rig_selection_tool_t *tool = user_data; entity_state_t *entity_state; c_llist_t *l; if (!tool->active && event == RIG_OBJECTS_SELECTION_ADD_EVENT) return; if (rut_object_get_type(object) != &rig_entity_type) return; for (l = tool->selected_entities; l; l = l->next) { entity_state = l->data; if (entity_state->entity == object) break; } if (l == NULL) entity_state = NULL; switch (event) { case RIG_OBJECTS_SELECTION_ADD_EVENT: { c_return_if_fail(entity_state == NULL); entity_state = c_slice_new0(entity_state_t); entity_state->tool = tool; entity_state->entity = rut_object_ref(object); entity_state->control_points = NULL; tool->selected_entities = c_llist_prepend(tool->selected_entities, entity_state); entity_state->sizeable = find_sizeable_component(entity_state->entity); if (entity_state->sizeable) create_sizeable_control_points(entity_state); else create_dummy_control_points(entity_state); break; } case RIG_OBJECTS_SELECTION_REMOVE_EVENT: c_return_if_fail(entity_state != NULL); tool->selected_entities = c_llist_remove(tool->selected_entities, entity_state); entity_state_destroy(entity_state); break; } }
static bool _cg_winsys_egl_display_setup(cg_display_t *display, cg_error_t **error) { cg_display_egl_t *egl_display = display->winsys; cg_display_xlib_t *xlib_display; xlib_display = c_slice_new0(cg_display_xlib_t); egl_display->platform = xlib_display; return true; }
static bool _cg_winsys_onscreen_init(cg_onscreen_t *onscreen, cg_error_t **error) { cg_framebuffer_t *framebuffer = CG_FRAMEBUFFER(onscreen); cg_device_t *dev = framebuffer->dev; cg_display_t *display = dev->display; cg_display_egl_t *egl_display = display->winsys; cg_renderer_t *renderer = display->renderer; cg_renderer_egl_t *egl_renderer = renderer->winsys; EGLint attributes[MAX_EGL_CONFIG_ATTRIBS]; EGLConfig egl_config; EGLint config_count = 0; EGLBoolean status; c_return_val_if_fail(egl_display->egl_context, false); egl_attributes_from_framebuffer_config( display, &framebuffer->config, attributes); status = eglChooseConfig( egl_renderer->edpy, attributes, &egl_config, 1, &config_count); if (status != EGL_TRUE || config_count == 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_CREATE_ONSCREEN, "Failed to find a suitable EGL configuration"); return false; } /* Update the real number of samples_per_pixel now that we have * found an egl_config... */ if (framebuffer->config.samples_per_pixel) { EGLint samples; status = eglGetConfigAttrib( egl_renderer->edpy, egl_config, EGL_SAMPLES, &samples); c_return_val_if_fail(status == EGL_TRUE, true); framebuffer->samples_per_pixel = samples; } onscreen->winsys = c_slice_new0(cg_onscreen_egl_t); if (egl_renderer->platform_vtable->onscreen_init && !egl_renderer->platform_vtable->onscreen_init( onscreen, egl_config, error)) { c_slice_free(cg_onscreen_egl_t, onscreen->winsys); return false; } return true; }
static bool _cg_winsys_display_setup(cg_display_t *display, cg_error_t **error) { cg_webgl_display_t *webgl_display; int window; EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context; EmscriptenWebGLContextAttributes attribs; char *id; c_return_val_if_fail(display->winsys == NULL, false); init_webgl_attribs_from_framebuffer_config(&attribs, &display->onscreen_template->config); window = CGlib_Emscripten_CreateWindow(100, 100, 0, 0); if (window < 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "create window failed"); return false; } CGlib_Emscripten_HideWindow(window); id = c_strdup_printf("cg_window_%d", window); context = emscripten_webgl_create_context(id, &attribs); if (context < 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "create context failed"); CGlib_Emscripten_DestroyWindow(window); c_free(id); return false; } emscripten_webgl_make_context_current(context); webgl_display = c_slice_new0(cg_webgl_display_t); display->winsys = webgl_display; webgl_display->window = window; webgl_display->window_id = id; webgl_display->context = context; return true; }
rig_downsampler_t * rig_downsampler_new(rig_engine_t *engine) { rig_downsampler_t *downsampler = c_slice_new0(rig_downsampler_t); cg_pipeline_t *pipeline; downsampler->engine = engine; pipeline = cg_pipeline_new(engine->shell->cg_device); cg_pipeline_set_layer_texture(pipeline, 0, NULL); cg_pipeline_set_blend(pipeline, "RGBA=ADD(SRC_COLOR, 0)", NULL); downsampler->pipeline = pipeline; return downsampler; }
static bool _cg_winsys_renderer_connect(cg_renderer_t *renderer, cg_error_t **error) { if (SDL_VideoInit(NULL) < 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "SDL_Init failed: %s", SDL_GetError()); return false; } renderer->winsys = c_slice_new0(cg_renderer_sdl2_t); return true; }
cg_onscreen_template_t * cg_onscreen_template_new(void) { cg_onscreen_template_t *onscreen_template = c_slice_new0(cg_onscreen_template_t); char *user_config; onscreen_template->config.swap_throttled = true; onscreen_template->config.need_stencil = true; onscreen_template->config.samples_per_pixel = 0; user_config = getenv("CG_POINT_SAMPLES_PER_PIXEL"); if (user_config) { unsigned long samples_per_pixel = strtoul(user_config, NULL, 10); if (samples_per_pixel != ULONG_MAX) onscreen_template->config.samples_per_pixel = samples_per_pixel; } return _cg_onscreen_template_object_new(onscreen_template); }
static bool _cg_winsys_display_setup(cg_display_t *display, cg_error_t **error) { cg_display_egl_t *egl_display; cg_renderer_t *renderer = display->renderer; cg_renderer_egl_t *egl_renderer = renderer->winsys; c_return_val_if_fail(display->winsys == NULL, false); egl_display = c_slice_new0(cg_display_egl_t); display->winsys = egl_display; #ifdef CG_HAS_WAYLAND_EGL_SERVER_SUPPORT if (display->wayland_compositor_display) { struct wl_display *wayland_display = display->wayland_compositor_display; cg_renderer_egl_t *egl_renderer = display->renderer->winsys; if (egl_renderer->pf_eglBindWaylandDisplay) egl_renderer->pf_eglBindWaylandDisplay(egl_renderer->edpy, wayland_display); } #endif if (egl_renderer->platform_vtable->display_setup && !egl_renderer->platform_vtable->display_setup(display, error)) goto error; if (!try_create_context(display, error)) goto error; egl_display->found_egl_config = true; return true; error: _cg_winsys_display_destroy(display); return false; }
cg_xlib_renderer_t * _cg_xlib_renderer_get_data(cg_renderer_t *renderer) { static cg_user_data_key_t key; cg_xlib_renderer_t *data; /* Constructs a cg_xlib_renderer_t struct on demand and attaches it to the object using user data. It's done this way instead of using a subclassing hierarchy in the winsys data because all EGL winsys's need the EGL winsys data but only one of them wants the Xlib data. */ data = cg_object_get_user_data(CG_OBJECT(renderer), &key); if (data == NULL) { data = c_slice_new0(cg_xlib_renderer_t); cg_object_set_user_data( CG_OBJECT(renderer), &key, data, destroy_xlib_renderer_data); } return data; }
static bool _cg_winsys_display_setup(cg_display_t *display, cg_error_t **error) { cg_display_sdl2_t *sdl_display; const char *(*get_string_func)(GLenum name); const char *gl_version; c_return_val_if_fail(display->winsys == NULL, false); sdl_display = c_slice_new0(cg_display_sdl2_t); display->winsys = sdl_display; set_gl_attribs_from_framebuffer_config(&display->onscreen_template->config); if (display->renderer->driver == CG_DRIVER_GLES2) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } else if (display->renderer->driver == CG_DRIVER_GL3) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); } /* Create a dummy 1x1 window that never gets display so that we can * create a GL context */ sdl_display->dummy_window = SDL_CreateWindow("", 0, 0, /* x/y */ 1, 1, /* w/h */ SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); if (sdl_display->dummy_window == NULL) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "SDL_CreateWindow failed: %s", SDL_GetError()); goto error; } sdl_display->context = SDL_GL_CreateContext(sdl_display->dummy_window); if (sdl_display->context == NULL) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "SDL_GL_CreateContext failed: %s", SDL_GetError()); goto error; } /* SDL doesn't seem to provide a way to select between GL and GLES * and instead it will just pick one itself. We can at least try to * verify that it picked the one we were expecting by looking at the * GL version string */ get_string_func = SDL_GL_GetProcAddress("glGetString"); gl_version = get_string_func(GL_VERSION); switch (display->renderer->driver) { case CG_DRIVER_GL: case CG_DRIVER_GL3: /* The first character of the version string will be a digit if * it's normal GL */ if (!c_ascii_isdigit(gl_version[0])) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "The GL driver was requested but SDL is using GLES"); goto error; } if (display->renderer->driver == CG_DRIVER_GL3 && gl_version[0] < '3') { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "The GL3 driver was requested but SDL is using " "GL %c", gl_version[0]); goto error; } break; case CG_DRIVER_GLES2: if (!c_str_has_prefix(gl_version, "OpenGL ES 2") && !c_str_has_prefix(gl_version, "OpenGL ES 3")) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "The GLES2 driver was requested but SDL is " "not using GLES2 or GLES3"); goto error; } break; default: c_assert_not_reached(); } return true; error: _cg_winsys_display_destroy(display); return false; }