cg_indices_t * cg_indices_new(cg_device_t *dev, cg_indices_type_t type, const void *indices_data, int n_indices) { size_t buffer_bytes = sizeof_indices_type(type) * n_indices; cg_index_buffer_t *index_buffer = cg_index_buffer_new(dev, buffer_bytes); cg_buffer_t *buffer = CG_BUFFER(index_buffer); cg_indices_t *indices; cg_error_t *ignore_error = NULL; cg_buffer_set_data(buffer, 0, indices_data, buffer_bytes, &ignore_error); if (ignore_error) { cg_error_free(ignore_error); cg_object_unref(index_buffer); return NULL; } indices = cg_indices_new_for_buffer(type, index_buffer, 0); cg_object_unref(index_buffer); return indices; }
int main(int argc, char **argv) { cg_renderer_t *renderer; cg_device_t *dev; 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 } }; Data data; SDL_Event event; renderer = cg_renderer_new(); dev = cg_device_new(); cg_renderer_set_winsys_id(renderer, CG_WINSYS_ID_SDL); if (cg_renderer_connect(renderer, &error)) cg_device_set_renderer(dev, renderer); else { cg_error_free(error); fprintf(stderr, "Failed to create device: %s\n", error->message); return 1; } onscreen = cg_onscreen_new(dev, 800, 600); data.fb = onscreen; cg_onscreen_add_frame_callback( onscreen, frame_cb, &data, NULL /* destroy callback */); cg_onscreen_add_dirty_callback( onscreen, dirty_cb, &data, NULL /* destroy callback */); data.center_x = 0.0f; data.center_y = 0.0f; data.quit = false; /* In SDL2, setting resizable only works before allocating the * onscreen */ cg_onscreen_set_resizable(onscreen, true); cg_onscreen_show(onscreen); data.triangle = cg_primitive_new_p2c4(dev, CG_VERTICES_MODE_TRIANGLES, 3, triangle_vertices); data.pipeline = cg_pipeline_new(dev); data.redraw_queued = false; data.ready_to_draw = true; while (!data.quit) { if (!SDL_PollEvent(&event)) { if (data.redraw_queued && data.ready_to_draw) { redraw(&data); data.redraw_queued = false; data.ready_to_draw = false; continue; } cg_sdl_idle(dev); if (!SDL_WaitEvent(&event)) { fprintf(stderr, "Error waiting for SDL events"); return 1; } } handle_event(&data, &event); cg_sdl_handle_event(dev, &event); } cg_object_unref(dev); 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; }