int main(int argc, char **argv) { Data data; cg_onscreen_t *onscreen; cg_error_t *error = NULL; cg_vertex_p2c4_t triangle_vertices[] = { { 0, 0.7, 0xff, 0x00, 0x00, 0xff }, { -0.7, -0.7, 0x00, 0xff, 0x00, 0xff }, { 0.7, -0.7, 0x00, 0x00, 0xff, 0xff } }; cg_renderer_t *renderer; cg_display_t *display; uv_loop_t *loop = uv_default_loop(); renderer = cg_renderer_new(); cg_renderer_add_constraint(renderer, CG_RENDERER_CONSTRAINT_SUPPORTS_CG_GLES2); if (!cg_renderer_connect(renderer, &error)) { c_error("%s", error->message); exit(1); } display = cg_display_new(renderer, NULL); data.dev = cg_device_new(); cg_device_set_display(data.dev, display); if (!cg_device_connect(data.dev, &error)) { c_error("%s", error->message); exit(1); } onscreen = cg_onscreen_new(data.dev, 640, 480); cg_onscreen_show(onscreen); data.fb = onscreen; /* Prepare onscreen primitive */ data.triangle = cg_primitive_new_p2c4( data.dev, CG_VERTICES_MODE_TRIANGLES, 3, triangle_vertices); data.pipeline = cg_pipeline_new(data.dev); data.offscreen_texture = cg_texture_2d_new_with_size( data.dev, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT); data.offscreen = cg_offscreen_new_with_texture(data.offscreen_texture); data.gles2_ctx = cg_gles2_context_new(data.dev, &error); if (!data.gles2_ctx) { c_error("Failed to create GLES2 context: %s\n", error->message); } data.gles2_vtable = cg_gles2_context_get_vtable(data.gles2_ctx); /* Draw scene with GLES2 */ if (!cg_push_gles2_context( data.dev, data.gles2_ctx, data.fb, data.fb, &error)) { c_error("Failed to push gles2 context: %s\n", error->message); } cg_pop_gles2_context(data.dev); cg_onscreen_add_frame_callback( CG_ONSCREEN(data.fb), frame_event_cb, &data, NULL); /* destroy notify */ uv_idle_init(loop, &data.idle); data.idle.data = &data; uv_idle_start(&data.idle, paint_cb); cg_uv_set_mainloop(data.dev, loop); uv_run(loop, UV_RUN_DEFAULT); return 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; }