static cg_filter_return_t sdl_window_event_filter(SDL_WindowEvent *event, cg_device_t *dev) { SDL_Window *window; cg_framebuffer_t *framebuffer; window = SDL_GetWindowFromID(event->windowID); if (window == NULL) return CG_FILTER_CONTINUE; framebuffer = SDL_GetWindowData(window, CG_SDL_WINDOW_DATA_KEY); if (framebuffer == NULL || framebuffer->dev != dev) return CG_FILTER_CONTINUE; if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) { cg_display_t *display = dev->display; cg_renderer_t *renderer = display->renderer; cg_renderer_sdl2_t *sdl_renderer = renderer->winsys; float width = event->data1; float height = event->data2; cg_onscreen_sdl2_t *sdl_onscreen; _cg_framebuffer_winsys_update_size(framebuffer, width, height); /* We only want to notify that a resize happened when the * application calls cg_device_dispatch so instead of * immediately notifying we queue an idle callback */ if (!sdl_renderer->resize_notify_idle) { sdl_renderer->resize_notify_idle = _cg_loop_add_idle( renderer, flush_pending_resize_notifications_idle, dev, NULL); } sdl_onscreen = CG_ONSCREEN(framebuffer)->winsys; sdl_onscreen->pending_resize_notify = true; } else if (event->event == SDL_WINDOWEVENT_EXPOSED) { cg_onscreen_dirty_info_t info; /* Sadly SDL doesn't seem to report the rectangle of the expose * event so we'll just queue the whole window */ info.x = 0; info.y = 0; info.width = framebuffer->width; info.height = framebuffer->height; _cg_onscreen_queue_dirty(CG_ONSCREEN(framebuffer), &info); } return CG_FILTER_CONTINUE; }
static bool _cg_winsys_set_gles2_context(cg_gles2_context_t *gles2_ctx, cg_error_t **error) { cg_device_t *dev = gles2_ctx->dev; cg_display_egl_t *egl_display = dev->display->winsys; bool status; if (gles2_ctx->write_buffer && cg_is_onscreen(gles2_ctx->write_buffer)) status = bind_onscreen_with_context( CG_ONSCREEN(gles2_ctx->write_buffer), gles2_ctx->winsys); else status = _cg_winsys_egl_make_current(dev->display, egl_display->dummy_surface, egl_display->dummy_surface, gles2_ctx->winsys); if (!status) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_MAKE_CURRENT, "Failed to make gles2 context current"); return false; } return true; }
static void paint_cb(uv_idle_t *idle) { Data *data = idle->data; cg_error_t *error = NULL; const cg_gles2_vtable_t *gles2 = data->gles2_vtable; /* 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); } /* Clear offscreen framebuffer with a random color */ gles2->glClearColor( c_random_double(), c_random_double(), c_random_double(), 1.0f); gles2->glClear(GL_COLOR_BUFFER_BIT); cg_pop_gles2_context(data->dev); /* Draw scene with Cogl */ cg_primitive_draw(data->triangle, data->fb, data->pipeline); cg_onscreen_swap_buffers(CG_ONSCREEN(data->fb)); uv_idle_stop(&data->idle); }
static cg_onscreen_t * find_onscreen_for_xid(cg_device_t *dev, uint32_t xid) { c_llist_t *l; for (l = dev->framebuffers; l; l = l->next) { cg_framebuffer_t *framebuffer = l->data; cg_onscreen_egl_t *egl_onscreen; cg_onscreen_xlib_t *xlib_onscreen; if (!framebuffer->type == CG_FRAMEBUFFER_TYPE_ONSCREEN) continue; egl_onscreen = CG_ONSCREEN(framebuffer)->winsys; xlib_onscreen = egl_onscreen->platform; if (xlib_onscreen->xwin == (Window)xid) return CG_ONSCREEN(framebuffer); } return NULL; }
static void flush_pending_notifications_cb(void *data, void *user_data) { cg_framebuffer_t *framebuffer = data; if (framebuffer->type == CG_FRAMEBUFFER_TYPE_ONSCREEN) { cg_onscreen_t *onscreen = CG_ONSCREEN(framebuffer); cg_onscreen_sdl2_t *sdl_onscreen = onscreen->winsys; if (sdl_onscreen->pending_resize_notify) { _cg_onscreen_notify_resize(onscreen); sdl_onscreen->pending_resize_notify = false; } } }
static void redraw(Data *data) { cg_framebuffer_t *fb = data->fb; cg_framebuffer_clear4f(fb, CG_BUFFER_BIT_COLOR, 0, 0, 0, 1); cg_framebuffer_push_matrix(fb); cg_framebuffer_translate(fb, data->center_x, -data->center_y, 0.0f); cg_primitive_draw(data->triangle, fb, data->pipeline); cg_framebuffer_pop_matrix(fb); cg_onscreen_swap_buffers(CG_ONSCREEN(fb)); }
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; }