static CoglBool _cogl_winsys_set_gles2_context (CoglGLES2Context *gles2_ctx, CoglError **error) { CoglContext *ctx = gles2_ctx->context; CoglDisplayEGL *egl_display = ctx->display->winsys; CoglBool status; if (gles2_ctx->write_buffer && cogl_is_onscreen (gles2_ctx->write_buffer)) status = bind_onscreen_with_context (COGL_ONSCREEN (gles2_ctx->write_buffer), gles2_ctx->winsys); else status = _cogl_winsys_egl_make_current (ctx->display, egl_display->dummy_surface, egl_display->dummy_surface, gles2_ctx->winsys); if (!status) { _cogl_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_MAKE_CURRENT, "Failed to make gles2 context current"); return FALSE; } return TRUE; }
static gboolean paint_cb (void *user_data) { Data *data = user_data; CoglError *error = NULL; const CoglGLES2Vtable *gles2 = data->gles2_vtable; /* Draw scene with GLES2 */ if (!cogl_push_gles2_context (data->ctx, data->gles2_ctx, data->fb, data->fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } /* Clear offscreen framebuffer with a random color */ gles2->glClearColor (g_random_double (), g_random_double (), g_random_double (), 1.0f); gles2->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (data->ctx); /* Draw scene with Cogl */ cogl_primitive_draw (data->triangle, data->fb, data->pipeline); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); return FALSE; /* remove the callback */ }
static void _set_up_pipeline (gpointer instance, gpointer user_data) { Data* data = (Data*) user_data; /* The cogl-gst sink, depending on the video format, can use up to 3 texture layers to render a frame. To avoid overwriting frame data, the first free layer in the cogl pipeline needs to be queried before adding any additional textures. */ int free_layer = cogl_gst_video_sink_get_free_layer (data->sink); data->video_pipeline = cogl_gst_video_sink_get_pipeline (data->sink); while (free_layer > 0) { free_layer--; cogl_pipeline_set_layer_filters (data->video_pipeline, free_layer, COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR, COGL_PIPELINE_FILTER_LINEAR); } /* disable blending... */ cogl_pipeline_set_blend (data->video_pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); /* Now that we know the video size we can perform letterboxing */ _resize_callback (COGL_ONSCREEN (data->fb), data->onscreen_width, data->onscreen_height, data); cogl_onscreen_add_frame_callback (COGL_ONSCREEN (data->fb), _frame_callback, data, NULL); /* The cogl-gst-new-frame signal is emitted when the cogl-gst sink has retrieved a new frame and attached it to the cogl pipeline. This can be used to make sure cogl doesn't do any unnecessary drawing i.e. keeps to the frame-rate of the video. */ g_signal_connect (data->sink, "new-frame", G_CALLBACK (_new_frame_cb), data); }
static void pre_paint_windows (MetaCompositor *compositor) { GList *l; MetaWindowActor *top_window; if (compositor->onscreen == NULL) { compositor->onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer ()); compositor->frame_closure = cogl_onscreen_add_frame_callback (compositor->onscreen, frame_callback, compositor, NULL); } if (compositor->windows == NULL) return; top_window = g_list_last (compositor->windows)->data; if (meta_window_actor_should_unredirect (top_window) && compositor->disable_unredirect_count == 0) set_unredirected_window (compositor, meta_window_actor_get_meta_window (top_window)); else set_unredirected_window (compositor, NULL); for (l = compositor->windows; l; l = l->next) meta_window_actor_pre_paint (l->data); if (compositor->frame_has_updated_xsurfaces) { /* We need to make sure that any X drawing that happens before * the XDamageSubtract() for each window above is visible to * subsequent GL rendering; the only standardized way to do this * is EXT_x11_sync_object, which isn't yet widely available. For * now, we count on details of Xorg and the open source drivers, * and hope for the best otherwise. * * Xorg and open source driver specifics: * * The X server makes sure to flush drawing to the kernel before * sending out damage events, but since we use * DamageReportBoundingBox there may be drawing between the last * damage event and the XDamageSubtract() that needs to be * flushed as well. * * Xorg always makes sure that drawing is flushed to the kernel * before writing events or responses to the client, so any * round trip request at this point is sufficient to flush the * GLX buffers. */ XSync (compositor->display->xdisplay, False); compositor->frame_has_updated_xsurfaces = FALSE; } }
static CoglBool paint_cb (void *user_data) { Data *data = user_data; cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); return FALSE; /* remove the callback */ }
static void handle_allocate(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) { gdk_window_resize(g_GdkWindow, allocation->width, allocation->height); g_Callbacks->resize(g_GdkWindow, COGL_ONSCREEN(g_Framebuffer), allocation->width, allocation->height, allocation->x, allocation->y); }
static CoglOnscreen * find_onscreen_for_xid (CoglContext *context, uint32_t xid) { GList *l; for (l = context->framebuffers; l; l = l->next) { CoglFramebuffer *framebuffer = l->data; CoglOnscreenEGL *egl_onscreen; CoglOnscreenXlib *xlib_onscreen; if (!framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) continue; egl_onscreen = COGL_ONSCREEN (framebuffer)->winsys; xlib_onscreen = egl_onscreen->platform; if (xlib_onscreen->xwin == (Window)xid) return COGL_ONSCREEN (framebuffer); } return NULL; }
static gboolean paint_cb (void *user_data) { Data *data = user_data; double elapsed = g_timer_elapsed (data->timer, NULL); double dt = elapsed - data->last_elapsed; GError *error = NULL; /* Draw scene with GLES2 */ if (!cogl_push_gles2_context (data->ctx, data->gles2_ctx, data->fb, data->fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gears_draw (); cogl_pop_gles2_context (data->ctx); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); /* advance rotation for next frame */ angle += 70.0 * dt; /* 70 degrees per second */ if (angle > 3600.0) angle -= 3600.0; data->frames++; if (elapsed > 5.0) { GLfloat fps = data->frames / elapsed; printf ("%d frames in %3.1f seconds = %6.3f FPS\n", data->frames, elapsed, fps); g_timer_reset (data->timer); data->last_elapsed = 0; data->frames = 0; }else data->last_elapsed = elapsed; /* If the driver can deliver swap complete events then we can remove * the idle paint callback until we next get a swap complete event * otherwise we keep the idle paint callback installed and simply * paint as fast as the driver will allow... */ if (cogl_has_feature (data->ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) return FALSE; /* remove the callback */ else return TRUE; }
static void redraw (Data *data) { CoglFramebuffer *fb = data->fb; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_push_matrix (fb); cogl_framebuffer_translate (fb, data->center_x, -data->center_y, 0.0f); cogl_primitive_draw (data->triangle, fb, data->pipeline); cogl_framebuffer_pop_matrix (fb); cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); }
static CoglBool paint_cb (void *user_data) { CoglandCompositor *compositor = user_data; GList *l; for (l = compositor->outputs; l; l = l->next) { CoglandOutput *output = l->data; CoglFramebuffer *fb = COGL_FRAMEBUFFER (output->onscreen); GList *l2; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_draw_primitive (fb, compositor->triangle_pipeline, compositor->triangle); for (l2 = compositor->surfaces; l2; l2 = l2->next) { CoglandSurface *surface = l2->data; if (surface->buffer) { CoglTexture2D *texture = surface->buffer->texture; CoglPipeline *pipeline = cogl_pipeline_new (compositor->cogl_context); cogl_pipeline_set_layer_texture (pipeline, 0, COGL_TEXTURE (texture)); cogl_framebuffer_draw_rectangle (fb, pipeline, -1, 1, 1, -1); cogl_object_unref (pipeline); } } cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } while (!g_queue_is_empty (&compositor->frame_callbacks)) { CoglandFrameCallback *callback = g_queue_peek_head (&compositor->frame_callbacks); wl_resource_post_event (&callback->resource, WL_CALLBACK_DONE, get_time ()); wl_resource_destroy (&callback->resource, 0); } return TRUE; }
static CoglBool paint_cb (void *user_data) { CoglandCompositor *compositor = user_data; GList *l; for (l = compositor->outputs; l; l = l->next) { CoglandOutput *output = l->data; CoglFramebuffer *fb = output->onscreen; GList *l2; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_primitive_draw (compositor->triangle, fb, compositor->triangle_pipeline); for (l2 = compositor->surfaces; l2; l2 = l2->next) { CoglandSurface *surface = l2->data; if (surface->texture) { CoglTexture2D *texture = surface->texture; CoglPipeline *pipeline = cogl_pipeline_new (compositor->cogl_context); cogl_pipeline_set_layer_texture (pipeline, 0, texture); cogl_framebuffer_draw_rectangle (fb, pipeline, -1, 1, 1, -1); cogl_object_unref (pipeline); } } cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } while (!wl_list_empty (&compositor->frame_callbacks)) { CoglandFrameCallback *callback = wl_container_of (compositor->frame_callbacks.next, callback, link); wl_callback_send_done (callback->resource, get_time ()); wl_resource_destroy (callback->resource); } compositor->redraw_idle = 0; return G_SOURCE_REMOVE; }
int main (int argc, char **argv) { Data data; CoglOnscreen *onscreen; CoglError *error = NULL; CoglVertexP2C4 triangle_vertices[] = { {0, 0.7, 0xff, 0x00, 0x00, 0x80}, {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} }; GSource *cogl_source; GMainLoop *loop; data.ctx = cogl_context_new (NULL, &error); if (!data.ctx) { fprintf (stderr, "Failed to create context: %s\n", error->message); return 1; } onscreen = cogl_onscreen_new (data.ctx, 640, 480); cogl_onscreen_show (onscreen); data.fb = COGL_FRAMEBUFFER (onscreen); cogl_onscreen_set_resizable (onscreen, TRUE); data.triangle = cogl_primitive_new_p2c4 (data.ctx, COGL_VERTICES_MODE_TRIANGLES, 3, triangle_vertices); data.pipeline = cogl_pipeline_new (data.ctx); cogl_source = cogl_glib_source_new (data.ctx, G_PRIORITY_DEFAULT); g_source_attach (cogl_source, NULL); if (cogl_has_feature (data.ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (data.fb), swap_complete_cb, &data); g_idle_add (paint_cb, &data); loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); return 0; }
static void flush_pending_resize_notifications_cb (void *data, void *user_data) { CoglFramebuffer *framebuffer = data; if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) { CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); CoglOnscreenEGL *egl_onscreen = onscreen->winsys; if (egl_onscreen->pending_resize_notify) { _cogl_onscreen_notify_resize (onscreen); egl_onscreen->pending_resize_notify = FALSE; } } }
static CoglBool paint_cb (void *user_data) { Data *data = user_data; cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); /* If the driver can deliver swap complete events then we can remove * the idle paint callback until we next get a swap complete event * otherwise we keep the idle paint callback installed and simply * paint as fast as the driver will allow... */ if (cogl_has_feature (data->ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) return FALSE; /* remove the callback */ else return TRUE; }
static gboolean paint_cb (void *user_data) { Data *data = user_data; double elapsed = g_timer_elapsed (data->timer, NULL); double dt = elapsed - data->last_elapsed; CoglError *error = NULL; /* Draw scene with GLES2 */ if (!cogl_push_gles2_context (data->ctx, data->gles2_ctx, data->fb, data->fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gears_draw (); cogl_pop_gles2_context (data->ctx); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); /* advance rotation for next frame */ angle += 70.0 * dt; /* 70 degrees per second */ if (angle > 3600.0) angle -= 3600.0; data->frames++; if (elapsed > 5.0) { GLfloat fps = data->frames / elapsed; printf ("%d frames in %3.1f seconds = %6.3f FPS\n", data->frames, elapsed, fps); g_timer_reset (data->timer); data->last_elapsed = 0; data->frames = 0; }else data->last_elapsed = elapsed; return FALSE; /* remove the callback */ }
static CoglFilterReturn sdl_event_filter_cb (SDL_Event *event, void *data) { if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { CoglContext *context = data; CoglDisplay *display = context->display; CoglDisplaySdl2 *sdl_display = display->winsys; float width = event->window.data1; float height = event->window.data2; CoglFramebuffer *framebuffer; CoglOnscreenSdl2 *sdl_onscreen; SDL_Window *window; window = SDL_GetWindowFromID (event->window.windowID); if (window == NULL) return COGL_FILTER_CONTINUE; framebuffer = SDL_GetWindowData (window, COGL_SDL_WINDOW_DATA_KEY); if (framebuffer == NULL || framebuffer->context != context) return COGL_FILTER_CONTINUE; _cogl_framebuffer_winsys_update_size (framebuffer, width, height); sdl_onscreen = COGL_ONSCREEN (framebuffer)->winsys; /* We only want to notify that a resize happened when the application calls cogl_context_dispatch so instead of immediately notifying we'll set a flag to remember to notify later */ sdl_display->pending_resize_notify = TRUE; sdl_onscreen->pending_resize_notify = TRUE; return COGL_FILTER_CONTINUE; } return COGL_FILTER_CONTINUE; }
static void flush_pending_swap_notify_cb (void *data, void *user_data) { CoglFramebuffer *framebuffer = data; if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) { CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); CoglOnscreenEGL *egl_onscreen = onscreen->winsys; CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform; if (kms_onscreen->pending_swap_notify) { CoglFrameInfo *info = g_queue_pop_head (&onscreen->pending_frame_infos); _cogl_onscreen_notify_frame_sync (onscreen, info); _cogl_onscreen_notify_complete (onscreen, info); kms_onscreen->pending_swap_notify = FALSE; cogl_object_unref (info); } } }
int main (int argc, char **argv) { Data data; CoglOnscreen *onscreen; GError *error = NULL; GSource *cogl_source; GMainLoop *loop; CoglRenderer *renderer; CoglDisplay *display; renderer = cogl_renderer_new (); cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2); display = cogl_display_new (renderer, NULL); data.ctx = cogl_context_new (display, NULL); onscreen = cogl_onscreen_new (data.ctx, 300, 300); cogl_onscreen_show (onscreen); data.fb = COGL_FRAMEBUFFER (onscreen); data.gles2_ctx = cogl_gles2_context_new (data.ctx, &error); if (!data.gles2_ctx) g_error ("Failed to create GLES2 context: %s\n", error->message); /* Draw scene with GLES2 */ if (!cogl_push_gles2_context (data.ctx, data.gles2_ctx, data.fb, data.fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gears_reshape (cogl_framebuffer_get_width (data.fb), cogl_framebuffer_get_height (data.fb)); /* Initialize the gears */ gears_init(); cogl_pop_gles2_context (data.ctx); cogl_source = cogl_glib_source_new (data.ctx, G_PRIORITY_DEFAULT); g_source_attach (cogl_source, NULL); if (cogl_has_feature (data.ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (data.fb), swap_complete_cb, &data); g_idle_add (paint_cb, &data); data.timer = g_timer_new (); data.frames = 0; data.last_elapsed = 0; loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); return 0; }
static void handle_repaint(GdkFrameClock *clock, void *data) { g_Callback(COGL_ONSCREEN(g_Framebuffer), g_CallbackData); }
CoglOnscreen* ImGui_ImplGtk3Cogl_Init(GtkWidget* widget, void (*callback)(CoglOnscreen *onscreen, void *data), void *data) { g_clear_pointer(&g_GtkWidget, g_object_unref); g_clear_pointer(&g_GdkWindow, g_object_unref); g_clear_pointer(&g_Framebuffer, cogl_object_unref); g_clear_pointer(&g_Context, cogl_object_unref); g_GtkWidget = GTK_WIDGET(g_object_ref(widget)); gtk_widget_realize(widget); GdkWindow *parent_window = gtk_widget_get_window(widget); GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); g_Callbacks = get_backend_callbacks(parent_window); GdkWindowAttr attributes; memset(&attributes, 0, sizeof(attributes)); attributes.x = 0; attributes.y = 0; attributes.width = allocation.width; attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = g_Callbacks->winsys == COGL_WINSYS_ID_EGL_WAYLAND ? GDK_WINDOW_SUBSURFACE : GDK_WINDOW_CHILD; GdkDisplay *display = gdk_window_get_display(parent_window); attributes.visual = gtk_widget_get_visual(widget); g_GdkWindow = gdk_window_new(parent_window, &attributes, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL); gdk_window_set_transient_for(g_GdkWindow, parent_window); gdk_window_set_pass_through(g_GdkWindow, TRUE); cairo_rectangle_int_t empty_rect; memset(&empty_rect, 0, sizeof(empty_rect)); cairo_region_t *input_region = cairo_region_create_rectangle(&empty_rect); gdk_window_input_shape_combine_region(g_GdkWindow, input_region, 0, 0); cairo_region_destroy(input_region); cairo_region_t *region = get_window_region(g_GdkWindow); gdk_window_set_opaque_region(g_GdkWindow, region); cairo_region_destroy(region); CoglRenderer *renderer = cogl_renderer_new(); cogl_renderer_set_winsys_id(renderer, g_Callbacks->winsys); g_Callbacks->init(renderer, display, g_GdkWindow); gdk_window_ensure_native(g_GdkWindow); g_Context = cogl_context_new(cogl_display_new(renderer, NULL), NULL); CoglOnscreen *onscreen = cogl_onscreen_new(g_Context, 1, 1); cogl_object_unref(renderer); g_Callbacks->resize(g_GdkWindow, onscreen, allocation.width, allocation.height, allocation.x, allocation.y); gtk_widget_add_events(widget, EVENT_MASK); g_signal_connect(widget, "event", G_CALLBACK(handle_gdk_event), NULL); g_signal_connect(widget, "size-allocate", G_CALLBACK(handle_allocate), NULL); g_Callbacks->set_window(onscreen, g_GdkWindow); if (!cogl_framebuffer_allocate(COGL_FRAMEBUFFER(onscreen), NULL)) g_warning("Unable to allocate framebuffer"); g_Framebuffer = COGL_FRAMEBUFFER(onscreen); ImGuiIO& io = ImGui::GetIO(); for (int i = 0; i < ImGuiKey_COUNT; i++) { io.KeyMap[i] = i; } io.SetClipboardTextFn = ImGui_ImplGtk3Cogl_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGtk3Cogl_GetClipboardText; io.ClipboardUserData = gtk_widget_get_clipboard(g_GtkWidget, GDK_SELECTION_CLIPBOARD); g_Callback = callback; g_CallbackData = data; GdkFrameClock *clock = gdk_window_get_frame_clock(g_GdkWindow); g_signal_connect(clock, "paint", G_CALLBACK(handle_repaint), NULL); gdk_frame_clock_request_phase(clock, GDK_FRAME_CLOCK_PHASE_PAINT); gdk_window_show(g_GdkWindow); return COGL_ONSCREEN(g_Framebuffer); }
int main (int argc, char **argv) { CoglContext *ctx; CoglOnscreen *onscreen; CoglFramebuffer *fb; GError *error = NULL; Data data; PangoRectangle hello_label_size; float fovy, aspect, z_near, z_2d, z_far; CoglDepthState depth_state; CoglBool has_swap_notify; ctx = cogl_context_new (NULL, &error); if (!ctx) { fprintf (stderr, "Failed to create context: %s\n", error->message); return 1; } onscreen = cogl_onscreen_new (ctx, 640, 480); fb = COGL_FRAMEBUFFER (onscreen); data.fb = fb; data.framebuffer_width = cogl_framebuffer_get_width (fb); data.framebuffer_height = cogl_framebuffer_get_height (fb); data.timer = g_timer_new (); cogl_onscreen_show (onscreen); cogl_framebuffer_set_viewport (fb, 0, 0, data.framebuffer_width, data.framebuffer_height); fovy = 60; /* y-axis field of view */ aspect = (float)data.framebuffer_width/(float)data.framebuffer_height; z_near = 0.1; /* distance to near clipping plane */ z_2d = 1000; /* position to 2d plane */ z_far = 2000; /* distance to far clipping plane */ cogl_framebuffer_perspective (fb, fovy, aspect, z_near, z_far); /* Since the pango renderer emits geometry in pixel/device coordinates * and the anti aliasing is implemented with the assumption that the * geometry *really* does end up pixel aligned, we setup a modelview * matrix so that for geometry in the plane z = 0 we exactly map x * coordinates in the range [0,stage_width] and y coordinates in the * range [0,stage_height] to the framebuffer extents with (0,0) being * the top left. * * This is roughly what Clutter does for a ClutterStage, but this * demonstrates how it is done manually using Cogl. */ cogl_matrix_init_identity (&data.view); cogl_matrix_view_2d_in_perspective (&data.view, fovy, aspect, z_near, z_2d, data.framebuffer_width, data.framebuffer_height); cogl_framebuffer_set_modelview_matrix (fb, &data.view); /* Initialize some convenient constants */ cogl_matrix_init_identity (&identity); cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff); /* rectangle indices allow the GPU to interpret a list of quads (the * faces of our cube) as a list of triangles. * * Since this is a very common thing to do * cogl_get_rectangle_indices() is a convenience function for * accessing internal index buffers that can be shared. */ data.indices = cogl_get_rectangle_indices (ctx, 6 /* n_rectangles */); data.prim = cogl_primitive_new_p3t2 (ctx, COGL_VERTICES_MODE_TRIANGLES, G_N_ELEMENTS (vertices), vertices); /* Each face will have 6 indices so we have 6 * 6 indices in total... */ cogl_primitive_set_indices (data.prim, data.indices, 6 * 6); /* Load a jpeg crate texture from a file */ printf ("crate.jpg (CC by-nc-nd http://bit.ly/9kP45T) ShadowRunner27 http://bit.ly/m1YXLh\n"); data.texture = cogl_texture_new_from_file (COGL_EXAMPLES_DATA "crate.jpg", COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!data.texture) g_error ("Failed to load texture: %s", error->message); /* a CoglPipeline conceptually describes all the state for vertex * processing, fragment processing and blending geometry. When * drawing the geometry for the crate this pipeline says to sample a * single texture during fragment processing... */ data.crate_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_layer_texture (data.crate_pipeline, 0, data.texture); /* Since the box is made of multiple triangles that will overlap * when drawn and we don't control the order they are drawn in, we * enable depth testing to make sure that triangles that shouldn't * be visible get culled by the GPU. */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (data.crate_pipeline, &depth_state, NULL); /* Setup a Pango font map and context */ data.pango_font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new (ctx)); cogl_pango_font_map_set_use_mipmapping (data.pango_font_map, TRUE); data.pango_context = pango_font_map_create_context (PANGO_FONT_MAP (data.pango_font_map)); data.pango_font_desc = pango_font_description_new (); pango_font_description_set_family (data.pango_font_desc, "Sans"); pango_font_description_set_size (data.pango_font_desc, 30 * PANGO_SCALE); /* Setup the "Hello Cogl" text */ data.hello_label = pango_layout_new (data.pango_context); pango_layout_set_font_description (data.hello_label, data.pango_font_desc); pango_layout_set_text (data.hello_label, "Hello Cogl", -1); pango_layout_get_extents (data.hello_label, NULL, &hello_label_size); data.hello_label_width = PANGO_PIXELS (hello_label_size.width); data.hello_label_height = PANGO_PIXELS (hello_label_size.height); data.swap_ready = TRUE; has_swap_notify = cogl_has_feature (ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT); if (has_swap_notify) cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (fb), swap_notify_cb, &data); while (1) { CoglPollFD *poll_fds; int n_poll_fds; int64_t timeout; if (data.swap_ready) { paint (&data); cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout); if (!has_swap_notify) { /* If the winsys doesn't support swap event notification then we'll just redraw constantly */ data.swap_ready = TRUE; timeout = 0; } g_poll ((GPollFD *) poll_fds, n_poll_fds, timeout == -1 ? -1 : timeout / 1000); cogl_poll_dispatch (ctx, poll_fds, n_poll_fds); } return 0; }
static gboolean meta_pre_paint_func (gpointer data) { GList *l; MetaWindowActor *top_window; MetaCompositor *compositor = data; if (compositor->onscreen == NULL) { compositor->onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer ()); compositor->frame_closure = cogl_onscreen_add_frame_callback (compositor->onscreen, frame_callback, compositor, NULL); } if (compositor->windows == NULL) return TRUE; top_window = g_list_last (compositor->windows)->data; if (meta_window_actor_should_unredirect (top_window) && compositor->disable_unredirect_count == 0) set_unredirected_window (compositor, meta_window_actor_get_meta_window (top_window)); else set_unredirected_window (compositor, NULL); for (l = compositor->windows; l; l = l->next) meta_window_actor_pre_paint (l->data); if (compositor->frame_has_updated_xsurfaces) { /* We need to make sure that any X drawing that happens before * the XDamageSubtract() for each window above is visible to * subsequent GL rendering; the standardized way to do this is * GL_EXT_X11_sync_object. Since this isn't implemented yet in * mesa, we also have a path that relies on the implementation * of the open source drivers. * * Anything else, we just hope for the best. * * Xorg and open source driver specifics: * * The X server makes sure to flush drawing to the kernel before * sending out damage events, but since we use * DamageReportBoundingBox there may be drawing between the last * damage event and the XDamageSubtract() that needs to be * flushed as well. * * Xorg always makes sure that drawing is flushed to the kernel * before writing events or responses to the client, so any * round trip request at this point is sufficient to flush the * GLX buffers. */ if (compositor->have_x11_sync_object) compositor->have_x11_sync_object = meta_sync_ring_insert_wait (); else XSync (compositor->display->xdisplay, False); } return TRUE; }
static void _draw (Data *data) { /* The cogl pipeline needs to be retrieved from the sink before every draw. This is due to the cogl-gst sink creating a new cogl pipeline for each frame by copying the previous one and attaching the new frame to it. */ CoglPipeline* current = cogl_gst_video_sink_get_pipeline (data->sink); data->video_pipeline = current; if (data->video_output.x) { int x = data->video_output.x; /* Letterboxed with vertical borders */ cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, 0, 0, x, data->onscreen_height); cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, data->onscreen_width - x, 0, data->onscreen_width, data->onscreen_height); cogl_framebuffer_draw_rectangle (data->fb, data->video_pipeline, x, 0, x + data->video_output.width, data->onscreen_height); } else if (data->video_output.y) { int y = data->video_output.y; /* Letterboxed with horizontal borders */ cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, 0, 0, data->onscreen_width, y); cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, 0, data->onscreen_height - y, data->onscreen_width, data->onscreen_height); cogl_framebuffer_draw_rectangle (data->fb, data->video_pipeline, 0, y, data->onscreen_width, y + data->video_output.height); } else { cogl_framebuffer_draw_rectangle (data->fb, data->video_pipeline, 0, 0, data->onscreen_width, data->onscreen_height); } cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); }
int main (int argc, char **argv) { Data data; CoglOnscreen *onscreen; CoglError *error = NULL; CoglVertexP2C4 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} }; GSource *cogl_source; GMainLoop *loop; CoglRenderer *renderer; CoglDisplay *display; renderer = cogl_renderer_new (); cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2); display = cogl_display_new (renderer, NULL); data.ctx = cogl_context_new (display, NULL); onscreen = cogl_onscreen_new (data.ctx, 640, 480); cogl_onscreen_show (onscreen); data.fb = COGL_FRAMEBUFFER (onscreen); /* Prepare onscreen primitive */ data.triangle = cogl_primitive_new_p2c4 (data.ctx, COGL_VERTICES_MODE_TRIANGLES, 3, triangle_vertices); data.pipeline = cogl_pipeline_new (data.ctx); data.offscreen_texture = COGL_TEXTURE ( cogl_texture_2d_new_with_size (data.ctx, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, COGL_PIXEL_FORMAT_ANY)); data.offscreen = cogl_offscreen_new_to_texture (data.offscreen_texture); data.gles2_ctx = cogl_gles2_context_new (data.ctx, &error); if (!data.gles2_ctx) { g_error ("Failed to create GLES2 context: %s\n", error->message); } data.gles2_vtable = cogl_gles2_context_get_vtable (data.gles2_ctx); /* Draw scene with GLES2 */ if (!cogl_push_gles2_context (data.ctx, data.gles2_ctx, data.fb, data.fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } cogl_pop_gles2_context (data.ctx); cogl_source = cogl_glib_source_new (data.ctx, G_PRIORITY_DEFAULT); g_source_attach (cogl_source, NULL); cogl_onscreen_add_frame_callback (COGL_ONSCREEN (data.fb), frame_event_cb, &data, NULL); /* destroy notify */ g_idle_add (paint_cb, &data); loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); return 0; }