cg_texture_2d_t * cg_texture_2d_gl_new_from_foreign(cg_device_t *dev, unsigned int gl_handle, int width, int height, cg_pixel_format_t format) { cg_texture_loader_t *loader; /* NOTE: width, height and internal format are not queriable * in GLES, hence such a function prototype. */ /* Note: We always trust the given width and height without querying * the texture object because the user may be creating a CGlib * texture for a texture_from_pixmap object where glTexImage2D may * not have been called and the texture_from_pixmap spec doesn't * clarify that it is reliable to query back the size from OpenGL. */ /* Assert it is a valid GL texture object */ c_return_val_if_fail(dev->glIsTexture(gl_handle), false); /* Validate width and height */ c_return_val_if_fail(width > 0 && height > 0, NULL); loader = _cg_texture_create_loader(dev); loader->src_type = CG_TEXTURE_SOURCE_TYPE_GL_FOREIGN; loader->src.gl_foreign.gl_handle = gl_handle; loader->src.gl_foreign.width = width; loader->src.gl_foreign.height = height; loader->src.gl_foreign.format = format; return _cg_texture_2d_create_base(dev, width, height, format, loader); }
bool c_vector4_equal (const void *v0, const void *v1) { c_return_val_if_fail (v1 != NULL, false); c_return_val_if_fail (v2 != NULL, false); return memcmp (v1, v2, sizeof (float) * 4) == 0 ? true : false; }
static bool _cg_winsys_onscreen_init(cg_onscreen_t *onscreen, cg_error_t **error) { cg_framebuffer_t *framebuffer = CG_FRAMEBUFFER(onscreen); cg_device_t *dev = framebuffer->dev; cg_display_t *display = dev->display; cg_display_egl_t *egl_display = display->winsys; cg_renderer_t *renderer = display->renderer; cg_renderer_egl_t *egl_renderer = renderer->winsys; EGLint attributes[MAX_EGL_CONFIG_ATTRIBS]; EGLConfig egl_config; EGLint config_count = 0; EGLBoolean status; c_return_val_if_fail(egl_display->egl_context, false); egl_attributes_from_framebuffer_config( display, &framebuffer->config, attributes); status = eglChooseConfig( egl_renderer->edpy, attributes, &egl_config, 1, &config_count); if (status != EGL_TRUE || config_count == 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_CREATE_ONSCREEN, "Failed to find a suitable EGL configuration"); return false; } /* Update the real number of samples_per_pixel now that we have * found an egl_config... */ if (framebuffer->config.samples_per_pixel) { EGLint samples; status = eglGetConfigAttrib( egl_renderer->edpy, egl_config, EGL_SAMPLES, &samples); c_return_val_if_fail(status == EGL_TRUE, true); framebuffer->samples_per_pixel = samples; } onscreen->winsys = c_slice_new0(cg_onscreen_egl_t); if (egl_renderer->platform_vtable->onscreen_init && !egl_renderer->platform_vtable->onscreen_init( onscreen, egl_config, error)) { c_slice_free(cg_onscreen_egl_t, onscreen->winsys); return false; } return true; }
bool c_vector3_equal_with_epsilon(const float *vector0, const float *vector1, float epsilon) { c_return_val_if_fail(vector0 != NULL, false); c_return_val_if_fail(vector1 != NULL, false); if (fabsf(vector0[X] - vector1[X]) < epsilon && fabsf(vector0[Y] - vector1[Y]) < epsilon && fabsf(vector0[Z] - vector1[Z]) < epsilon) return true; else return false; }
bool c_vector3_equal(const void *v1, const void *v2) { float *vector0 = (float *)v1; float *vector1 = (float *)v2; c_return_val_if_fail(v1 != NULL, false); c_return_val_if_fail(v2 != NULL, false); /* There's no point picking an arbitrary epsilon that's appropriate * for comparing the components so we just use == that will at least * consider -0 and 0 to be equal. */ return vector0[X] == vector1[X] && vector0[Y] == vector1[Y] && vector0[Z] == vector1[Z]; }
size_t cg_indices_get_offset(cg_indices_t *indices) { c_return_val_if_fail(cg_is_indices(indices), 0); return indices->offset; }
cg_indices_type_t cg_indices_get_type(cg_indices_t *indices) { c_return_val_if_fail(cg_is_indices(indices), CG_INDICES_TYPE_UNSIGNED_BYTE); return indices->type; }
bool _cg_texture_2d_gl_allocate(cg_texture_t *tex, cg_error_t **error) { cg_texture_2d_t *tex_2d = CG_TEXTURE_2D(tex); cg_texture_loader_t *loader = tex->loader; c_return_val_if_fail(loader, false); switch (loader->src_type) { case CG_TEXTURE_SOURCE_TYPE_SIZED: return allocate_with_size(tex_2d, loader, error); case CG_TEXTURE_SOURCE_TYPE_BITMAP: return allocate_from_bitmap(tex_2d, loader, error); case CG_TEXTURE_SOURCE_TYPE_EGL_IMAGE: #if defined(CG_HAS_EGL_SUPPORT) && defined(EGL_KHR_image_base) return allocate_from_egl_image(tex_2d, loader, error); #else c_return_val_if_reached(false); #endif case CG_TEXTURE_SOURCE_TYPE_WEBGL_IMAGE: #ifdef CG_HAS_WEBGL_SUPPORT return allocate_from_webgl_image(tex_2d, loader, error); #else c_return_val_if_reached(false); #endif case CG_TEXTURE_SOURCE_TYPE_GL_FOREIGN: return allocate_from_gl_foreign(tex_2d, loader, error); } c_return_val_if_reached(false); }
static rut_input_event_status_t control_point_input_cb( rut_input_region_t *region, rut_input_event_t *event, void *user_data) { control_point_t *point = user_data; entity_state_t *entity_state = point->entity_state; rig_selection_tool_t *tool = entity_state->tool; c_return_val_if_fail(tool->selected_entities != NULL, RUT_INPUT_EVENT_STATUS_UNHANDLED); if (rut_input_event_get_type(event) == RUT_INPUT_EVENT_TYPE_MOTION && rut_motion_event_get_action(event) == RUT_MOTION_EVENT_ACTION_DOWN && rut_motion_event_get_button_state(event) == RUT_BUTTON_STATE_1) { // float x = rut_motion_event_get_x (event); // float y = rut_motion_event_get_y (event); grab_state_t *state = c_slice_new0(grab_state_t); state->tool = tool; state->entity_state = entity_state; state->point = point; rut_shell_grab_input(tool->shell, rut_input_event_get_camera(event), control_point_grab_cb, state); return RUT_INPUT_EVENT_STATUS_HANDLED; } return RUT_INPUT_EVENT_STATUS_UNHANDLED; }
cg_indices_t * _cg_indices_immutable_ref(cg_indices_t *indices) { c_return_val_if_fail(cg_is_indices(indices), NULL); indices->immutable_ref++; _cg_buffer_immutable_ref(CG_BUFFER(indices->buffer)); return indices; }
EGLDisplay cg_egl_context_get_egl_display(cg_device_t *dev) { const cg_winsys_vtable_t *winsys = _cg_device_get_winsys(dev); /* This should only be called for EGL contexts */ c_return_val_if_fail(winsys->device_egl_get_egl_display != NULL, NULL); return winsys->device_egl_get_egl_display(dev); }
Display * cg_xlib_renderer_get_display(cg_renderer_t *renderer) { cg_xlib_renderer_t *xlib_renderer; c_return_val_if_fail(cg_is_renderer(renderer), NULL); xlib_renderer = _cg_xlib_renderer_get_data(renderer); return xlib_renderer->xdpy; }
bool _cg_egl_query_wayland_buffer(cg_device_t *dev, struct wl_resource *buffer, int attribute, int *value) { cg_renderer_egl_t *egl_renderer = dev->display->renderer->winsys; c_return_val_if_fail(egl_renderer->pf_eglQueryWaylandBuffer, false); return egl_renderer->pf_eglQueryWaylandBuffer( egl_renderer->edpy, buffer, attribute, value); }
static bool _cg_winsys_display_setup(cg_display_t *display, cg_error_t **error) { cg_webgl_display_t *webgl_display; int window; EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context; EmscriptenWebGLContextAttributes attribs; char *id; c_return_val_if_fail(display->winsys == NULL, false); init_webgl_attribs_from_framebuffer_config(&attribs, &display->onscreen_template->config); window = CGlib_Emscripten_CreateWindow(100, 100, 0, 0); if (window < 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "create window failed"); return false; } CGlib_Emscripten_HideWindow(window); id = c_strdup_printf("cg_window_%d", window); context = emscripten_webgl_create_context(id, &attribs); if (context < 0) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "create context failed"); CGlib_Emscripten_DestroyWindow(window); c_free(id); return false; } emscripten_webgl_make_context_current(context); webgl_display = c_slice_new0(cg_webgl_display_t); display->winsys = webgl_display; webgl_display->window = window; webgl_display->window_id = id; webgl_display->context = context; return true; }
SDL_Window * cg_sdl_onscreen_get_window(cg_onscreen_t *onscreen) { cg_onscreen_sdl2_t *sdl_onscreen; c_return_val_if_fail(cg_is_onscreen(onscreen), NULL); if (!cg_framebuffer_allocate(CG_FRAMEBUFFER(onscreen), NULL)) return NULL; sdl_onscreen = onscreen->winsys; return sdl_onscreen->window; }
/* XXX: This is a particularly hacky _cg_winsys interface... */ static XVisualInfo * _cg_winsys_xlib_get_visual_info(void) { cg_display_egl_t *egl_display; _CG_GET_DEVICE(dev, NULL); c_return_val_if_fail(dev->display->winsys, false); egl_display = dev->display->winsys; if (!egl_display->found_egl_config) return NULL; return get_visual_info(dev->display, egl_display->egl_config); }
static bool _cg_winsys_device_init(cg_device_t *dev, cg_error_t **error) { cg_renderer_t *renderer = dev->display->renderer; cg_display_egl_t *egl_display = dev->display->winsys; cg_renderer_egl_t *egl_renderer = renderer->winsys; dev->winsys = c_new0(cg_device_egl_t, 1); c_return_val_if_fail(egl_display->egl_context, false); memset(dev->winsys_features, 0, sizeof(dev->winsys_features)); check_egl_extensions(renderer); if (!_cg_device_update_features(dev, error)) return false; if (egl_renderer->private_features & CG_EGL_WINSYS_FEATURE_SWAP_REGION) { CG_FLAGS_SET(dev->winsys_features, CG_WINSYS_FEATURE_SWAP_REGION, true); CG_FLAGS_SET(dev->winsys_features, CG_WINSYS_FEATURE_SWAP_REGION_THROTTLE, true); } if ((egl_renderer->private_features & CG_EGL_WINSYS_FEATURE_FENCE_SYNC) && _cg_has_private_feature(dev, CG_PRIVATE_FEATURE_OES_EGL_SYNC)) CG_FLAGS_SET(dev->features, CG_FEATURE_ID_FENCE, true); if (egl_renderer->private_features & CG_EGL_WINSYS_FEATURE_BUFFER_AGE) CG_FLAGS_SET(dev->winsys_features, CG_WINSYS_FEATURE_BUFFER_AGE, true); /* NB: We currently only support creating standalone GLES2 contexts * for offscreen rendering and so we need a dummy (non-visible) * surface to be able to bind those contexts */ if (egl_display->dummy_surface != EGL_NO_SURFACE && dev->driver == CG_DRIVER_GLES2) CG_FLAGS_SET(dev->features, CG_FEATURE_ID_GLES2_CONTEXT, true); if (egl_renderer->platform_vtable->device_init && !egl_renderer->platform_vtable->device_init(dev, error)) return false; return true; }
bool c_path_is_absolute(const char *filename) { c_return_val_if_fail(filename != NULL, false); if (filename[0] != '\0' && filename[1] != '\0') { if (filename[1] == ':' && filename[2] != '\0' && (filename[2] == '\\' || filename[2] == '/')) return true; /* UNC paths */ else if (filename[0] == '\\' && filename[1] == '\\' && filename[2] != '\0') return true; } return false; }
static bool _cg_winsys_display_setup(cg_display_t *display, cg_error_t **error) { cg_display_egl_t *egl_display; cg_renderer_t *renderer = display->renderer; cg_renderer_egl_t *egl_renderer = renderer->winsys; c_return_val_if_fail(display->winsys == NULL, false); egl_display = c_slice_new0(cg_display_egl_t); display->winsys = egl_display; #ifdef CG_HAS_WAYLAND_EGL_SERVER_SUPPORT if (display->wayland_compositor_display) { struct wl_display *wayland_display = display->wayland_compositor_display; cg_renderer_egl_t *egl_renderer = display->renderer->winsys; if (egl_renderer->pf_eglBindWaylandDisplay) egl_renderer->pf_eglBindWaylandDisplay(egl_renderer->edpy, wayland_display); } #endif if (egl_renderer->platform_vtable->display_setup && !egl_renderer->platform_vtable->display_setup(display, error)) goto error; if (!try_create_context(display, error)) goto error; egl_display->found_egl_config = true; return true; error: _cg_winsys_display_destroy(display); return false; }
EGLImageKHR _cg_egl_create_image(cg_device_t *dev, EGLenum target, EGLClientBuffer buffer, const EGLint *attribs) { cg_display_egl_t *egl_display = dev->display->winsys; cg_renderer_egl_t *egl_renderer = dev->display->renderer->winsys; EGLContext egl_ctx; c_return_val_if_fail(egl_renderer->pf_eglCreateImage, EGL_NO_IMAGE_KHR); /* The EGL_KHR_image_pixmap spec explicitly states that EGL_NO_CONTEXT must * always be used in conjunction with the EGL_NATIVE_PIXMAP_KHR target */ #ifdef EGL_KHR_image_pixmap if (target == EGL_NATIVE_PIXMAP_KHR) egl_ctx = EGL_NO_CONTEXT; else #endif egl_ctx = egl_display->egl_context; return egl_renderer->pf_eglCreateImage( egl_renderer->edpy, egl_ctx, target, buffer, attribs); }
static bool _cg_winsys_display_setup(cg_display_t *display, cg_error_t **error) { cg_display_sdl2_t *sdl_display; const char *(*get_string_func)(GLenum name); const char *gl_version; c_return_val_if_fail(display->winsys == NULL, false); sdl_display = c_slice_new0(cg_display_sdl2_t); display->winsys = sdl_display; set_gl_attribs_from_framebuffer_config(&display->onscreen_template->config); if (display->renderer->driver == CG_DRIVER_GLES2) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } else if (display->renderer->driver == CG_DRIVER_GL3) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); } /* Create a dummy 1x1 window that never gets display so that we can * create a GL context */ sdl_display->dummy_window = SDL_CreateWindow("", 0, 0, /* x/y */ 1, 1, /* w/h */ SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN); if (sdl_display->dummy_window == NULL) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "SDL_CreateWindow failed: %s", SDL_GetError()); goto error; } sdl_display->context = SDL_GL_CreateContext(sdl_display->dummy_window); if (sdl_display->context == NULL) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "SDL_GL_CreateContext failed: %s", SDL_GetError()); goto error; } /* SDL doesn't seem to provide a way to select between GL and GLES * and instead it will just pick one itself. We can at least try to * verify that it picked the one we were expecting by looking at the * GL version string */ get_string_func = SDL_GL_GetProcAddress("glGetString"); gl_version = get_string_func(GL_VERSION); switch (display->renderer->driver) { case CG_DRIVER_GL: case CG_DRIVER_GL3: /* The first character of the version string will be a digit if * it's normal GL */ if (!c_ascii_isdigit(gl_version[0])) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "The GL driver was requested but SDL is using GLES"); goto error; } if (display->renderer->driver == CG_DRIVER_GL3 && gl_version[0] < '3') { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "The GL3 driver was requested but SDL is using " "GL %c", gl_version[0]); goto error; } break; case CG_DRIVER_GLES2: if (!c_str_has_prefix(gl_version, "OpenGL ES 2") && !c_str_has_prefix(gl_version, "OpenGL ES 3")) { _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_INIT, "The GLES2 driver was requested but SDL is " "not using GLES2 or GLES3"); goto error; } break; default: c_assert_not_reached(); } return true; error: _cg_winsys_display_destroy(display); return false; }
cg_device_t * _cg_device_get_default(void) { c_return_val_if_fail(_cg_device != NULL, NULL); return _cg_device; }
static bool try_create_context(cg_display_t *display, cg_error_t **error) { cg_renderer_t *renderer = display->renderer; cg_display_egl_t *egl_display = display->winsys; cg_renderer_egl_t *egl_renderer = renderer->winsys; EGLDisplay edpy; EGLConfig config; EGLint config_count = 0; EGLBoolean status; EGLint attribs[9]; EGLint cfg_attribs[MAX_EGL_CONFIG_ATTRIBS]; const char *error_message; c_return_val_if_fail(egl_display->egl_context == NULL, true); if (renderer->driver == CG_DRIVER_GL || renderer->driver == CG_DRIVER_GL3) eglBindAPI(EGL_OPENGL_API); egl_attributes_from_framebuffer_config( display, &display->onscreen_template->config, cfg_attribs); edpy = egl_renderer->edpy; status = eglChooseConfig(edpy, cfg_attribs, &config, 1, &config_count); if (status != EGL_TRUE || config_count == 0) { error_message = "Unable to find a usable EGL configuration"; goto fail; } egl_display->egl_config = config; if (display->renderer->driver == CG_DRIVER_GL3) { if (!(egl_renderer->private_features & CG_EGL_WINSYS_FEATURE_CREATE_CONTEXT)) { error_message = "Driver does not support GL 3 contexts"; goto fail; } /* Try to get a core profile 3.1 context with no deprecated features */ attribs[0] = EGL_CONTEXT_MAJOR_VERSION_KHR; attribs[1] = 3; attribs[2] = EGL_CONTEXT_MINOR_VERSION_KHR; attribs[3] = 1; attribs[4] = EGL_CONTEXT_FLAGS_KHR; attribs[5] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; attribs[6] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; attribs[7] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; attribs[8] = EGL_NONE; } else if (display->renderer->driver == CG_DRIVER_GLES2) { attribs[0] = EGL_CONTEXT_CLIENT_VERSION; attribs[1] = 2; attribs[2] = EGL_NONE; } else attribs[0] = EGL_NONE; egl_display->egl_context = eglCreateContext(edpy, config, EGL_NO_CONTEXT, attribs); if (egl_display->egl_context == EGL_NO_CONTEXT) { error_message = "Unable to create a suitable EGL context"; goto fail; } if (egl_renderer->platform_vtable->device_created && !egl_renderer->platform_vtable->device_created(display, error)) return false; return true; fail: _cg_set_error(error, CG_WINSYS_ERROR, CG_WINSYS_ERROR_CREATE_CONTEXT, "%s", error_message); cleanup_device(display); return false; }