Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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];
}
Beispiel #6
0
size_t
cg_indices_get_offset(cg_indices_t *indices)
{
    c_return_val_if_fail(cg_is_indices(indices), 0);

    return indices->offset;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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);
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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);
}
Beispiel #12
0
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;
}
Beispiel #13
0
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);
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
/* 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);
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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);
}
Beispiel #21
0
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;
}
Beispiel #22
0
cg_device_t *
_cg_device_get_default(void)
{
    c_return_val_if_fail(_cg_device != NULL, NULL);
    return _cg_device;
}
Beispiel #23
0
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;
}