static void create_primitives (cg_primitive_t *primitives[2]) { static const Vertex vertex_data[8] = { /* triangle strip 1 */ { 0, 0, 255, 0, 0, 255 }, { 0, 100, 255, 0, 0, 255 }, { 100, 0, 255, 0, 0, 255 }, { 100, 100, 255, 0, 0, 255 }, /* triangle strip 2 */ { 200, 0, 0, 0, 255, 255 }, { 200, 100, 0, 0, 255, 255 }, { 300, 0, 0, 0, 255, 255 }, { 300, 100, 0, 0, 255, 255 }, }; primitives[0] = cg_primitive_new_p2c4 (test_dev, CG_VERTICES_MODE_TRIANGLE_STRIP, C_N_ELEMENTS (vertex_data), vertex_data); cg_primitive_set_n_vertices (primitives[0], 4); primitives[1] = cg_primitive_copy (primitives[0]); cg_primitive_set_first_vertex (primitives[1], 4); cg_primitive_set_n_vertices (primitives[1], 4); }
/* Updates all the function pointers */ static void check_egl_extensions(cg_renderer_t *renderer) { cg_renderer_egl_t *egl_renderer = renderer->winsys; const char *egl_extensions; char **split_extensions; int i; egl_extensions = eglQueryString(egl_renderer->edpy, EGL_EXTENSIONS); split_extensions = c_strsplit(egl_extensions, " ", 0 /* max_tokens */); CG_NOTE(WINSYS, " EGL Extensions: %s", egl_extensions); egl_renderer->private_features = 0; for (i = 0; i < C_N_ELEMENTS(winsys_feature_data); i++) if (_cg_feature_check(renderer, "EGL", winsys_feature_data + i, 0, 0, CG_DRIVER_GL, /* the driver isn't used */ split_extensions, egl_renderer)) { egl_renderer->private_features |= winsys_feature_data[i].feature_flags_private; } c_strfreev(split_extensions); }
static int get_max_activateable_texture_units(cg_device_t *dev) { if (C_UNLIKELY(dev->max_activateable_texture_units == -1)) { GLint values[3]; int n_values = 0; int i; #ifdef CG_HAS_GL_SUPPORT if (!_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_GL_EMBEDDED)) { /* GL_MAX_TEXTURE_COORDS is provided for GLSL. It defines * the number of texture coordinates that can be uploaded * (but doesn't necessarily relate to how many texture * images can be sampled) */ if (cg_has_feature(dev, CG_FEATURE_ID_GLSL)) { /* Previously this code subtracted the value by one but there was no explanation for why it did this and it doesn't seem to make sense so it has been removed */ GE(dev, glGetIntegerv(GL_MAX_TEXTURE_COORDS, values + n_values++)); /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL */ GE(dev, glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, values + n_values++)); } } #endif /* CG_HAS_GL_SUPPORT */ #ifdef CG_HAS_GLES2_SUPPORT if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_GL_EMBEDDED)) { GE(dev, glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, values + n_values)); /* Two of the vertex attribs need to be used for the position and color */ values[n_values++] -= 2; GE(dev, glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, values + n_values++)); } #endif c_assert(n_values <= C_N_ELEMENTS(values) && n_values > 0); /* Use the maximum value */ dev->max_activateable_texture_units = values[0]; for (i = 1; i < n_values; i++) dev->max_activateable_texture_units = MAX(values[i], dev->max_activateable_texture_units); } return dev->max_activateable_texture_units; }
static void run_tests(TestState *state) { int i; for(i = 0; i < C_N_ELEMENTS(tests); i++) { cg_framebuffer_clear4f(test_fb, CG_BUFFER_BIT_COLOR, 0, 0, 0, 1); tests[i](state); } }
int main(int argc, char **argv) { cg_onscreen_t *onscreen; cg_error_t *error = NULL; struct demo demo; float fovy, aspect, z_near, z_2d, z_far; uv_loop_t *loop = uv_default_loop(); demo.dev = cg_device_new (); if (!demo.dev || error != NULL) c_error("Failed to create Cogl context\n"); onscreen = cg_onscreen_new(demo.dev, WIDTH, HEIGHT); demo.fb = onscreen; demo.width = cg_framebuffer_get_width(demo.fb); demo.height = cg_framebuffer_get_height(demo.fb); cg_onscreen_show(onscreen); cg_framebuffer_set_viewport(demo.fb, 0, 0, demo.width, demo.height); fovy = 45; aspect = (float)demo.width / (float)demo.height; z_near = 0.1; z_2d = 1000; z_far = 2000; cg_framebuffer_perspective(demo.fb, fovy, aspect, z_near, z_far); c_matrix_init_identity(&demo.view); c_matrix_view_2d_in_perspective(&demo.view, fovy, aspect, z_near, z_2d, demo.width, demo.height); cg_framebuffer_set_modelview_matrix(demo.fb, &demo.view); demo.swap_ready = true; cg_onscreen_add_frame_callback(demo.fb, frame_event_cb, &demo, NULL); init_particle_emitters(&demo); demo.timer = c_timer_new(); demo.spin_rate = 0; demo.angle_between_emitters = 2 * M_PI / C_N_ELEMENTS(demo.emitter); uv_idle_init(loop, &demo.idle); demo.idle.data = &demo; uv_idle_start(&demo.idle, paint_cb); cg_uv_set_mainloop(demo.dev, loop); uv_run(loop, UV_RUN_DEFAULT); return 0; }
static const cg_blend_string_function_info_t * get_function_info(const char *mark, const char *p) { size_t len = p - mark; cg_blend_string_function_info_t *functions; size_t array_len; int i; functions = blend_functions; array_len = C_N_ELEMENTS(blend_functions); for (i = 0; i < array_len; i++) { if (len >= functions[i].name_len && strncmp(mark, functions[i].name, functions[i].name_len) == 0) return &functions[i]; } return NULL; }
static void paint_cb(uv_idle_t *idle) { struct demo *demo = idle->data; unsigned int i; update_catherine_wheel(demo); cg_framebuffer_clear4f(demo->fb, CG_BUFFER_BIT_COLOR | CG_BUFFER_BIT_DEPTH, 0, 0, 0, 1); for (i = 0; i < C_N_ELEMENTS(demo->emitter); i++) particle_emitter_paint(demo->emitter[i]); cg_onscreen_swap_buffers(demo->fb); uv_idle_stop(&demo->idle); }
static void init_particle_emitters(struct demo *demo) { unsigned int i; for (i = 0; i < C_N_ELEMENTS(demo->emitter); i++) { demo->emitter[i] = particle_emitter_new(demo->dev, demo->fb); demo->emitter[i]->particle_count = 80000; demo->emitter[i]->particle_size = 1.0f; demo->emitter[i]->new_particles_per_ms = demo->emitter[i]->particle_count / 2; /* Global force */ demo->emitter[i]->acceleration[1] = 14; /* Particle position */ demo->emitter[i]->particle_position.value[0] = WIDTH / 2; demo->emitter[i]->particle_position.value[1] = HEIGHT / 2; demo->emitter[i]->particle_position.type = VECTOR_VARIANCE_NONE; /* Particle speed */ demo->emitter[i]->particle_speed.value = 22; demo->emitter[i]->particle_speed.variance = 0.6; demo->emitter[i]->particle_speed.type = FLOAT_VARIANCE_PROPORTIONAL; /* Direction */ demo->emitter[i]->particle_direction.variance[0] = 0.7; demo->emitter[i]->particle_direction.variance[1] = 0.7; demo->emitter[i]->particle_direction.type = VECTOR_VARIANCE_IRWIN_HALL; /* Lifespan */ demo->emitter[i]->particle_lifespan.value = 1.5; demo->emitter[i]->particle_lifespan.variance = 0.95; demo->emitter[i]->particle_lifespan.type = DOUBLE_VARIANCE_PROPORTIONAL; /* Color */ demo->emitter[i]->particle_color.hue.value = 32; demo->emitter[i]->particle_color.hue.variance = 20; demo->emitter[i]->particle_color.hue.type = FLOAT_VARIANCE_LINEAR; demo->emitter[i]->particle_color.saturation.value = 1; demo->emitter[i]->particle_color.luminance.value = 0.6; demo->emitter[i]->particle_color.luminance.variance = 0.4; demo->emitter[i]->particle_color.luminance.type = FLOAT_VARIANCE_LINEAR; } }
static const cg_blend_string_color_source_info_t * get_color_src_info(const char *mark, const char *p) { size_t len = p - mark; cg_blend_string_color_source_info_t *sources; size_t array_len; int i; sources = blending_color_sources; array_len = C_N_ELEMENTS(blending_color_sources); for (i = 0; i < array_len; i++) { if (len >= sources[i].name_len && strncmp(mark, sources[i].name, sources[i].name_len) == 0) return &sources[i]; } return NULL; }
static void update_catherine_wheel(struct demo *demo) { unsigned int i; double elapsed_time = c_timer_elapsed(demo->timer, NULL); double spin = demo->spin_rate * elapsed_time; if (demo->spin_rate < RATE_MAX) demo->spin_rate += RATE_INC; for (i = 0; i < C_N_ELEMENTS(demo->emitter); i++) { double x = i * demo->angle_between_emitters + spin; double x_cos = cos(x); double x_sin = sin(x); demo->emitter[i]->particle_position.value[0] = WIDTH / 2 + WHEEL_RADIUS * x_cos; demo->emitter[i]->particle_position.value[1] = HEIGHT / 2 - WHEEL_RADIUS * x_sin; demo->emitter[i]->particle_direction.value[0] = x_sin; demo->emitter[i]->particle_direction.value[1] = x_cos; } }
bool cg_device_connect(cg_device_t *dev, cg_error_t **error) { uint8_t white_pixel[] = { 0xff, 0xff, 0xff, 0xff }; const cg_winsys_vtable_t *winsys; int i; cg_error_t *internal_error = NULL; if (dev->connected) return true; /* Mark as connected now to avoid recursion issues, * but revert in error paths */ dev->connected = true; if (!dev->renderer) { cg_renderer_t *renderer = cg_renderer_new(); if (!cg_renderer_connect(renderer, error)) { cg_object_unref(renderer); dev->connected = false; return false; } cg_device_set_renderer(dev, renderer); } if (!dev->display) { cg_display_t *display = cg_display_new(dev->renderer, NULL); if (!cg_display_setup(display, error)) { cg_object_unref(display); dev->connected = false; return false; } cg_device_set_display(dev, display); } /* This is duplicated data, but it's much more convenient to have the driver attached to the context and the value is accessed a lot throughout CGlib */ dev->driver = dev->renderer->driver; /* Again this is duplicated data, but it convenient to be able * access these from the context. */ dev->driver_vtable = dev->renderer->driver_vtable; dev->texture_driver = dev->renderer->texture_driver; for (i = 0; i < C_N_ELEMENTS(dev->private_features); i++) dev->private_features[i] |= dev->renderer->private_features[i]; winsys = _cg_device_get_winsys(dev); if (!winsys->device_init(dev, error)) { dev->connected = false; return false; } dev->attribute_name_states_hash = c_hash_table_new_full(c_str_hash, c_str_equal, c_free, c_free); dev->attribute_name_index_map = NULL; dev->n_attribute_names = 0; /* The "cg_color_in" attribute needs a deterministic name_index * so we make sure it's the first attribute name we register */ _cg_attribute_register_attribute_name(dev, "cg_color_in"); dev->uniform_names = c_ptr_array_new_with_free_func((c_destroy_func_t)c_free); dev->uniform_name_hash = c_hash_table_new(c_str_hash, c_str_equal); dev->n_uniform_names = 0; /* Initialise the driver specific state */ _cg_init_feature_overrides(dev); /* XXX: ONGOING BUG: Intel viewport scissor * * Intel gen6 drivers don't currently correctly handle offset * viewports, since primitives aren't clipped within the bounds of * the viewport. To workaround this we push our own clip for the * viewport that will use scissoring to ensure we clip as expected. * * TODO: file a bug upstream! */ if (dev->gpu.driver_package == CG_GPU_INFO_DRIVER_PACKAGE_MESA && dev->gpu.architecture == CG_GPU_INFO_ARCHITECTURE_SANDYBRIDGE && !getenv("CG_DISABLE_INTEL_VIEWPORT_SCISSORT_WORKAROUND")) dev->needs_viewport_scissor_workaround = true; else dev->needs_viewport_scissor_workaround = false; dev->sampler_cache = _cg_sampler_cache_new(dev); _cg_pipeline_init_default_pipeline(); _cg_pipeline_init_default_layers(); _cg_pipeline_init_state_hash_functions(); _cg_pipeline_init_layer_state_hash_functions(); dev->current_clip_stack_valid = false; dev->current_clip_stack = NULL; c_matrix_init_identity(&dev->identity_matrix); c_matrix_init_identity(&dev->y_flip_matrix); c_matrix_scale(&dev->y_flip_matrix, 1, -1, 1); dev->texture_units = c_array_new(false, false, sizeof(cg_texture_unit_t)); if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_ANY_GL)) { /* See cg-pipeline.c for more details about why we leave texture unit * 1 * active by default... */ dev->active_texture_unit = 1; GE(dev, glActiveTexture(GL_TEXTURE1)); } dev->opaque_color_pipeline = cg_pipeline_new(dev); dev->codegen_header_buffer = c_string_new(""); dev->codegen_source_buffer = c_string_new(""); dev->default_gl_texture_2d_tex = NULL; dev->default_gl_texture_3d_tex = NULL; dev->framebuffers = NULL; dev->current_draw_buffer = NULL; dev->current_read_buffer = NULL; dev->current_draw_buffer_state_flushed = 0; dev->current_draw_buffer_changes = CG_FRAMEBUFFER_STATE_ALL; c_list_init(&dev->onscreen_events_queue); c_list_init(&dev->onscreen_dirty_queue); c_queue_init(&dev->gles2_context_stack); dev->current_pipeline = NULL; dev->current_pipeline_changes_since_flush = 0; dev->current_pipeline_with_color_attrib = false; _cg_bitmask_init(&dev->enabled_custom_attributes); _cg_bitmask_init(&dev->enable_custom_attributes_tmp); _cg_bitmask_init(&dev->changed_bits_tmp); dev->max_texture_units = -1; dev->max_activateable_texture_units = -1; dev->current_gl_program = 0; dev->current_gl_dither_enabled = true; dev->current_gl_color_mask = CG_COLOR_MASK_ALL; dev->gl_blend_enable_cache = false; dev->depth_test_enabled_cache = false; dev->depth_test_function_cache = CG_DEPTH_TEST_FUNCTION_LESS; dev->depth_writing_enabled_cache = true; dev->depth_range_near_cache = 0; dev->depth_range_far_cache = 1; dev->pipeline_cache = _cg_pipeline_cache_new(); for (i = 0; i < CG_BUFFER_BIND_TARGET_COUNT; i++) dev->current_buffer[i] = NULL; dev->stencil_pipeline = cg_pipeline_new(dev); dev->rectangle_byte_indices = NULL; dev->rectangle_short_indices = NULL; dev->rectangle_short_indices_len = 0; dev->texture_download_pipeline = NULL; dev->blit_texture_pipeline = NULL; #if defined(CG_HAS_GL_SUPPORT) if ((dev->driver == CG_DRIVER_GL3)) { GLuint vertex_array; /* In a forward compatible context, GL 3 doesn't support rendering * using the default vertex array object. CGlib doesn't use vertex * array objects yet so for now we just create a dummy array * object that we will use as our own default object. Eventually * it could be good to attach the vertex array objects to * cg_primitive_ts */ dev->glGenVertexArrays(1, &vertex_array); dev->glBindVertexArray(vertex_array); } #endif dev->current_modelview_entry = NULL; dev->current_projection_entry = NULL; _cg_matrix_entry_identity_init(&dev->identity_entry); _cg_matrix_entry_cache_init(&dev->builtin_flushed_projection); _cg_matrix_entry_cache_init(&dev->builtin_flushed_modelview); /* Create default textures used for fall backs */ dev->default_gl_texture_2d_tex = cg_texture_2d_new_from_data(dev, 1, 1, CG_PIXEL_FORMAT_RGBA_8888_PRE, 0, /* rowstride */ white_pixel, NULL); /* abort on error */ /* If 3D or rectangle textures aren't supported then these will * return errors that we can simply ignore. */ internal_error = NULL; dev->default_gl_texture_3d_tex = cg_texture_3d_new_from_data(dev, 1, 1, 1, /* width, height, depth */ CG_PIXEL_FORMAT_RGBA_8888_PRE, 0, /* rowstride */ 0, /* image stride */ white_pixel, &internal_error); if (internal_error) cg_error_free(internal_error); dev->buffer_map_fallback_array = c_byte_array_new(); dev->buffer_map_fallback_in_use = false; c_list_init(&dev->fences); dev->atlas_set = cg_atlas_set_new(dev); cg_atlas_set_set_components(dev->atlas_set, CG_TEXTURE_COMPONENTS_RGBA); cg_atlas_set_set_premultiplied(dev->atlas_set, false); cg_atlas_set_add_atlas_callback(dev->atlas_set, _cg_atlas_texture_atlas_event_handler, NULL, /* user data */ NULL); /* destroy */ return true; }