Beispiel #1
0
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);
}
Beispiel #2
0
/* 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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
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;
}
Beispiel #6
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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
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;
    }
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
    }
}
Beispiel #11
0
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;
}