Пример #1
0
static bool
parse_context_forward_compatible(struct wcore_config_attrs *attrs,
                                 const int32_t attrib_list[])
{
    if (!parse_bool(attrib_list, WAFFLE_CONTEXT_FORWARD_COMPATIBLE,
                    &attrs->context_forward_compatible, false)) {
        return false;
    }

    if (!attrs->context_forward_compatible) {
        /* It's always valid to request a non-forward-compatible context. */
        return true;
    }

    if (attrs->context_api != WAFFLE_CONTEXT_OPENGL) {
        wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                     "To request a forward-compatible context, the context "
                     "API must be WAFFLE_CONTEXT_OPENGL");
        return false;

    }

    if (attrs->context_full_version < 30) {
        wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                     "To request a forward-compatible context, the context "
                     "version must be at least 3.0");
        return false;
    }

    return true;
}
Пример #2
0
extern "C" bool
nacl_container_window_resize(struct nacl_container *nc, int32_t width, int32_t height)
{
    waffle::nacl_container *cpp_nc =
        reinterpret_cast<waffle::nacl_container*>(nc);

    int32_t error = cpp_nc->ctx->ResizeBuffers(width, height);

    if (error == PP_OK)
       return true;

    switch (error) {
        case PP_ERROR_BADRESOURCE:
            wcore_errorf(WAFFLE_ERROR_FATAL, "Invalid NaCl 3D context.");
            break;
        case PP_ERROR_BADARGUMENT:
            wcore_errorf(WAFFLE_ERROR_BAD_PARAMETER,
                         "Invalid values given for resize (w %d h %d)",
                         width, height);
            break;
        default:
            wcore_errorf(WAFFLE_ERROR_UNKNOWN, "NaCl resize failed.");
    }
    return false;
}
Пример #3
0
static bool
parse_context_api(struct wcore_config_attrs *attrs,
                  const int32_t attrib_list[])
{
    bool found;

    found = wcore_attrib_list_get(attrib_list,
                                  WAFFLE_CONTEXT_API, &attrs->context_api);
    if (!found) {
        wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                     "required attribute WAFFLE_CONTEXT_API is missing");
        return false;
    }

    switch (attrs->context_api) {
        case WAFFLE_CONTEXT_OPENGL:
        case WAFFLE_CONTEXT_OPENGL_ES1:
        case WAFFLE_CONTEXT_OPENGL_ES2:
        case WAFFLE_CONTEXT_OPENGL_ES3:
            break;
        default:
            wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                         "WAFFLE_CONTEXT_API has bad value %#x",
                         attrs->context_api);
            return false;
    }

    return true;
}
Пример #4
0
static bool
nacl_container_context_init(waffle::nacl_container *nc, struct nacl_config *cfg)
{
    // There is no way currently to pass a pp::Instance for Waffle, so
    // we fetch a map of all instances and if there's only one we select
    // that one, otherwise we fail.
    const pp::Module::InstanceMap instances =
        pp::Module::Get()->current_instances();

    if (instances.size() != 1) {
        wcore_errorf(WAFFLE_ERROR_FATAL,
                    "Could not find a pp::Instance for Waffle to use.");
        return false;
    }

    pp::Instance *pp_instance = instances.begin()->second;
    nc->ctx = new pp::Graphics3D(pp_instance, pp::Graphics3D(), cfg->attribs);

    if (nc->ctx->is_null()) {
        wcore_errorf(WAFFLE_ERROR_FATAL, "Unable to create NaCl 3D context.");
        return false;
    }

    // We need to fetch NaCl specific init, makecurrent and terminate
    // functions that communicate with the browser interface. As nacl_config
    // currently supports only ES2, this is hardcoded for ES2.
    nc->glapi = dlopen(NACL_GLES2_LIBRARY, RTLD_LAZY);
    if (!nc->glapi) {
        wcore_errorf(WAFFLE_ERROR_FATAL, "dlopen failed: %s", dlerror());
        return false;
    }

#define RESOLVE(func) \
    nc->func = (typeof(nc->func)) dlsym(nc->glapi, (#func)); \
    if (!nc->func) { \
        wcore_errorf(WAFFLE_ERROR_FATAL, "failed to resolve %s", #func); \
        return false; \
    }

    RESOLVE(glInitializePPAPI);
    RESOLVE(glSetCurrentContextPPAPI);
    RESOLVE(glTerminatePPAPI);

#undef RESOLVE

    if (!nc->glInitializePPAPI(pp::Module::Get()->get_browser_interface())) {
        wcore_errorf(WAFFLE_ERROR_FATAL,
                    "Unable to initialize GL PPAPI!");
        return false;
    }

    if (!pp_instance->BindGraphics(*nc->ctx)) {
        wcore_errorf(WAFFLE_ERROR_FATAL, "Unable to bind NaCl 3D context.");
        return false;
    }

    nc->swapper = new NaclSwapThread(pp_instance, nc->ctx);
    return true;
}
Пример #5
0
static void
test_wcore_error_first_call_with_message_wins(void **state) {
    wcore_error_reset();
    wcore_errorf(WAFFLE_ERROR_UNKNOWN, "cookies");
    wcore_errorf(WAFFLE_NO_ERROR, "all is well");
    assert_int_equal(wcore_error_get_code(), WAFFLE_ERROR_UNKNOWN);
    assert_string_equal(wcore_error_get_info()->message, "cookies");
}
Пример #6
0
struct wcore_window*
wgbm_window_create(struct wcore_platform *wc_plat,
                   struct wcore_config *wc_config,
                   int32_t width,
                   int32_t height,
                   const intptr_t attrib_list[])
{
    struct wgbm_display *dpy = wgbm_display(wc_config->display);
    struct wgbm_platform *plat = wgbm_platform(wegl_platform(wc_plat));
    struct wgbm_window *self;
    uint32_t gbm_format;
    bool ok = true;

    if (width == -1 && height == -1) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "fullscreen window not supported");
        return NULL;
    }

    if (wcore_attrib_list_length(attrib_list) > 0) {
        wcore_error_bad_attribute(attrib_list[0]);
        return NULL;
    }

    self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    gbm_format = wgbm_config_get_gbm_format(wc_plat, wc_config->display,
                                            wc_config);
    assert(gbm_format != 0);
    self->gbm_surface = plat->gbm_surface_create(dpy->gbm_device,
                                                 width, height, gbm_format,
                                                 GBM_BO_USE_RENDERING);
    if (!self->gbm_surface) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "gbm_surface_create failed");
        goto error;
    }

    ok = wegl_window_init(&self->wegl, wc_config,
                          (intptr_t) self->gbm_surface);
    if (!ok)
        goto error;

    return &self->wegl.wcore;

error:
    wgbm_window_destroy(&self->wegl.wcore);
    return NULL;
}
Пример #7
0
static bool
glx_platform_destroy(struct wcore_platform *wc_self)
{
    struct glx_platform *self = glx_platform(wc_self);
    bool ok = true;
    int error = 0;

    if (!self)
        return true;

    if (self->linux)
        ok &= linux_platform_destroy(self->linux);

    if (self->glxHandle) {
        error = dlclose(self->glxHandle);
        if (error) {
            ok &= false;
            wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                         "dlclose(\"%s\") failed: %s",
                         libGL_filename, dlerror());
        }
    }

    ok &= wcore_platform_teardown(wc_self);
    free(self);
    return ok;
}
Пример #8
0
struct wcore_window*
sl_window_create(struct wcore_platform *wc_plat,
                   struct wcore_config *wc_config,
                   int32_t width,
                   int32_t height,
                   const intptr_t attrib_list[])
{
    struct sl_window *self;
    bool ok = true;

    if (width == -1 && height == -1) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "fullscreen window not supported");
        return NULL;
    }

    if (wcore_attrib_list_length(attrib_list) > 0) {
        wcore_error_bad_attribute(attrib_list[0]);
        return NULL;
    }

    self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    ok = wegl_pbuffer_init(&self->wegl, wc_config, width, height);
    if (!ok)
        goto error;

    return &self->wegl.wcore;

error:
    sl_window_destroy(&self->wegl.wcore);
    return NULL;
}
Пример #9
0
static void
test_wcore_error_with_message(void **state) {
    wcore_error_reset();
    wcore_errorf(WAFFLE_ERROR_BAD_PARAMETER, "bad %s (0x%x)", "gl_api", 0x17);
    assert_int_equal(wcore_error_get_code(), WAFFLE_ERROR_BAD_PARAMETER);
    assert_string_equal(wcore_error_get_info()->message, "bad gl_api (0x17)");
}
Пример #10
0
static bool
wayland_platform_destroy(struct wcore_platform *wc_self)
{
    struct wayland_platform *self = wayland_platform(wegl_platform(wc_self));
    bool ok = true;
    int error;

    if (!self)
        return true;

    if (self->linux)
        ok &= linux_platform_destroy(self->linux);

    if (self->dl_wl_egl) {
        error = dlclose(self->dl_wl_egl);
        if (error) {
            ok &= false;
            wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                         "dlclose(\"%s\") failed: %s",
                         libwl_egl_filename, dlerror());
        }
    }

    ok &= wayland_wrapper_teardown();
    ok &= wegl_platform_teardown(&self->wegl);
    free(self);
    return ok;
}
Пример #11
0
static bool
parse_bool(const int32_t attrib_list[],
		   int32_t attrib_name,
		   bool *value,
		   bool default_value)
{
	int32_t raw_value;

	wcore_attrib_list_get_with_default(attrib_list, attrib_name,
                                       &raw_value, default_value);

	if (raw_value == WAFFLE_DONT_CARE) {
		*value = default_value;
	} else if (raw_value == true || raw_value == false) {
		*value = raw_value;
	} else {
		wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
					 "%s has bad value 0x%x. "
					 "Must be true(1), false(0), or WAFFLE_DONT_CARE(-1)",
					 wcore_enum_to_string(attrib_name), raw_value);
		return false;
	}

    return true;
}
Пример #12
0
WAFFLE_API bool
waffle_display_supports_context_api(
        struct waffle_display *self,
        int32_t context_api)
{
    struct wcore_display *wc_self = wcore_display(self);

    const struct api_object *obj_list[] = {
        wc_self ? &wc_self->api : NULL,
    };

    if (!api_check_entry(obj_list, 1))
        return false;

    switch (context_api) {
        case WAFFLE_CONTEXT_OPENGL:
        case WAFFLE_CONTEXT_OPENGL_ES1:
        case WAFFLE_CONTEXT_OPENGL_ES2:
        case WAFFLE_CONTEXT_OPENGL_ES3:
            break;
        default:
            wcore_errorf(WAFFLE_ERROR_BAD_PARAMETER,
                         "context_api has bad value %#x", context_api);
            return false;
    }

    return api_platform->vtbl->display.supports_context_api(wc_self,
                                                            context_api);
}
Пример #13
0
static void
test_wcore_error_first_call_without_message_wins(void **state) {
    wcore_error_reset();
    wcore_errorf(WAFFLE_ERROR_UNKNOWN, "cookies");
    wcore_error(WAFFLE_ERROR_BAD_ATTRIBUTE);
    assert_int_equal(wcore_error_get_code(), WAFFLE_ERROR_UNKNOWN);
    assert_string_equal(wcore_error_get_info()->message, "cookies");
}
Пример #14
0
static bool
parse_context_profile(struct wcore_config_attrs *attrs,
                      const int32_t attrib_list[])
{
    wcore_attrib_list_get_with_default(attrib_list,
                                       WAFFLE_CONTEXT_PROFILE,
                                       &attrs->context_profile,
                                       attrs->context_profile);

    switch (attrs->context_api) {
        case WAFFLE_CONTEXT_OPENGL:
            if (attrs->context_full_version >= 32
                && attrs->context_profile != WAFFLE_CONTEXT_CORE_PROFILE
                && attrs->context_profile != WAFFLE_CONTEXT_COMPATIBILITY_PROFILE) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL >= 3.2,"
                             "WAFFLE_CONTEXT_PROFILE must be either "
                             "WAFFLE_CONTEXT_CORE_PROFILE or "
                             "WAFFLE_CONTEXT_COMPATIBILITY_PROFILE");
                return false;
            }
            else if (attrs->context_full_version < 32
                     && attrs->context_profile != WAFFLE_NONE) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL < 3.2, WAFFLE_CONTEXT_PROFILE must be "
                             "WAFFLE_NONE");
                return false;
            }
            break;
        case WAFFLE_CONTEXT_OPENGL_ES1:
        case WAFFLE_CONTEXT_OPENGL_ES2:
        case WAFFLE_CONTEXT_OPENGL_ES3:
            if (attrs->context_profile != WAFFLE_NONE) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL ES, WAFFLE_CONTEXT_PROFILE must be "
                             "WAFFLE_NONE");
                return false;
            }
            break;
        default:
            assert(false);
            return false;
    }

    return true;
}
Пример #15
0
struct wcore_platform*
glx_platform_create(void)
{
    struct glx_platform *self;
    bool ok = true;

    self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    ok = wcore_platform_init(&self->wcore);
    if (!ok)
        goto error;

    self->glxHandle = dlopen(libGL_filename, RTLD_LAZY | RTLD_LOCAL);
    if (!self->glxHandle) {
        wcore_errorf(WAFFLE_ERROR_FATAL,
                     "dlopen(\"%s\") failed: %s",
                     libGL_filename, dlerror());
        goto error;
    }

#define RETRIEVE_GLX_SYMBOL(function)                                  \
    self->function = dlsym(self->glxHandle, #function);                \
    if (!self->function) {                                             \
        wcore_errorf(WAFFLE_ERROR_FATAL,                             \
                     "dlsym(\"%s\", \"" #function "\") failed: %s",    \
                     libGL_filename, dlerror());                      \
        goto error;                                                    \
    }

    RETRIEVE_GLX_SYMBOL(glXCreateNewContext);
    RETRIEVE_GLX_SYMBOL(glXDestroyContext);
    RETRIEVE_GLX_SYMBOL(glXMakeCurrent);

    RETRIEVE_GLX_SYMBOL(glXQueryExtensionsString);
    RETRIEVE_GLX_SYMBOL(glXGetProcAddress);

    RETRIEVE_GLX_SYMBOL(glXGetVisualFromFBConfig);
    RETRIEVE_GLX_SYMBOL(glXGetFBConfigAttrib);
    RETRIEVE_GLX_SYMBOL(glXChooseFBConfig);

    RETRIEVE_GLX_SYMBOL(glXSwapBuffers);
#undef RETRIEVE_GLX_SYMBOL

    self->linux = linux_platform_create();
    if (!self->linux)
        goto error;

    self->glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) self->glXGetProcAddress((const uint8_t*) "glXCreateContextAttribsARB");

    self->wcore.vtbl = &glx_platform_vtbl;
    return &self->wcore;

error:
    glx_platform_destroy(&self->wcore);
    return NULL;
}
Пример #16
0
struct wcore_platform*
wayland_platform_create(void)
{
    struct wayland_platform *self;
    bool ok = true;

    self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    ok = wegl_platform_init(&self->wegl, EGL_PLATFORM_WAYLAND_KHR);
    if (!ok)
        goto error;

    ok = wayland_wrapper_init();
    if (!ok)
        goto error;

    self->dl_wl_egl = dlopen(libwl_egl_filename, RTLD_LAZY | RTLD_LOCAL);
    if (!self->dl_wl_egl) {
        wcore_errorf(WAFFLE_ERROR_FATAL,
                     "dlopen(\"%s\") failed: %s",
                     libwl_egl_filename, dlerror());
        goto error;
    }

#define RETRIEVE_WL_EGL_SYMBOL(function)                                  \
    self->function = dlsym(self->dl_wl_egl, #function);                \
    if (!self->function) {                                             \
        wcore_errorf(WAFFLE_ERROR_FATAL,                             \
                     "dlsym(\"%s\", \"" #function "\") failed: %s",    \
                     libwl_egl_filename, dlerror());                      \
        goto error;                                                    \
    }

    RETRIEVE_WL_EGL_SYMBOL(wl_egl_window_create);
    RETRIEVE_WL_EGL_SYMBOL(wl_egl_window_destroy);
    RETRIEVE_WL_EGL_SYMBOL(wl_egl_window_resize);

#undef RETRIEVE_WL_EGL_SYMBOL

    self->linux = linux_platform_create();
    if (!self->linux)
        goto error;

    self->wegl.wcore.vtbl = &wayland_platform_vtbl;
    return &self->wegl.wcore;

error:
    wayland_platform_destroy(&self->wegl.wcore);
    return NULL;
}
Пример #17
0
static bool
check_final(struct wcore_config_attrs *attrs)
{
    if (attrs->context_api == WAFFLE_CONTEXT_OPENGL
        && attrs->context_profile == WAFFLE_CONTEXT_CORE_PROFILE
        && attrs->context_full_version >= 32
        && attrs->accum_buffer) {
        wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                     "%s", "WAFFLE_ACCUM_BUFFER must be false for"
                     "OpenGL Core profile");
        return false;
    }

    return true;
}
Пример #18
0
static bool
wgl_dl_open(struct wgl_platform *plat)
{
    plat->dl_gl = LoadLibraryA(wgl_gl_path);

    if (plat->dl_gl)
        return true;

    int error = GetLastError();

    if (error) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "LoadLibraryA(\"%s\") failed: %d",
                     wgl_gl_path, error);
    }

    return false;
}
Пример #19
0
void*
linux_dl_sym(struct linux_dl *self, const char *symbol)
{
    // Clear any previous error.
    dlerror();

    void *sym = dlsym(self->dl, symbol);

    const char *error = dlerror();
    if (error) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "dlsym(libname=\"%s\", \"%s\") failed: %s",
                     self->name, symbol, error);
        return NULL;
    }

    return sym;
}
Пример #20
0
static bool
glx_platform_make_current(struct wcore_platform *wc_self,
                          struct wcore_display *wc_dpy,
                          struct wcore_window *wc_window,
                          struct wcore_context *wc_ctx)
{
    struct glx_platform *self = glx_platform(wc_self);
    Display *dpy = glx_display(wc_dpy)->x11.xlib;
    GLXDrawable win = wc_window ? glx_window(wc_window)->x11.xcb : 0;
    GLXContext ctx = wc_ctx ? glx_context(wc_ctx)->glx : NULL;
    bool ok;

    ok = wrapped_glXMakeCurrent(self, dpy, win, ctx);
    if (!ok) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN, "glXMakeCurrent failed");
    }

    return ok;
}
Пример #21
0
bool
linux_dl_close(struct linux_dl *self)
{
    int error = 0;

    if (!self)
        return true;

    if (self->dl) {
        error = dlclose(self->dl);
        if (error) {
            wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                         "dlclose(libname=\"%s\") failed: %s",
                         self->name, dlerror());
        }
    }

    free(self);
    return error == 0;
}
Пример #22
0
static bool
check_keys(const int32_t attrib_list[])
{
    if (attrib_list == NULL)
        return true;

    for (int32_t i = 0; attrib_list[i]; i += 2) {
        int32_t key = attrib_list[i];

        switch (key) {
            case WAFFLE_CONTEXT_API:
            case WAFFLE_CONTEXT_MAJOR_VERSION:
            case WAFFLE_CONTEXT_MINOR_VERSION:
            case WAFFLE_CONTEXT_PROFILE:
            case WAFFLE_CONTEXT_FORWARD_COMPATIBLE:
            case WAFFLE_CONTEXT_DEBUG:
            case WAFFLE_RED_SIZE:
            case WAFFLE_GREEN_SIZE:
            case WAFFLE_BLUE_SIZE:
            case WAFFLE_ALPHA_SIZE:
            case WAFFLE_DEPTH_SIZE:
            case WAFFLE_STENCIL_SIZE:
            case WAFFLE_SAMPLES:
            case WAFFLE_SAMPLE_BUFFERS:
            case WAFFLE_DOUBLE_BUFFERED:
            case WAFFLE_ACCUM_BUFFER:
                break;
            default:
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "unrecognized attribute 0x%x at attrib_list[%d]",
                             key, i);
                return false;
        }
    }

    return true;
}
Пример #23
0
bool
api_check_entry(const struct api_object *obj_list[], int length)
{
    wcore_error_reset();

    if (!api_platform) {
        wcore_error(WAFFLE_ERROR_NOT_INITIALIZED);
        return false;
    }

    for (int i = 0; i < length; ++i) {
        if (obj_list[i] == NULL) {
            wcore_errorf(WAFFLE_ERROR_BAD_PARAMETER, "null pointer");
            return false;
        }

        if (obj_list[i]->display_id != obj_list[0]->display_id) {
            wcore_error(WAFFLE_ERROR_BAD_DISPLAY_MATCH);
            return false;
        }
    }

    return true;
}
Пример #24
0
void
wegl_emit_error(struct wegl_platform *plat, const char *egl_func_call)
{
    EGLint egl_error_code = plat->eglGetError();
    const char *egl_error_name;

    switch (egl_error_code) {
#define CASE(x) case x: egl_error_name = #x; break
        CASE(EGL_FALSE);
        CASE(EGL_TRUE);
        CASE(EGL_DONT_CARE);
        CASE(EGL_SUCCESS);
        CASE(EGL_NOT_INITIALIZED);
        CASE(EGL_BAD_ACCESS);
        CASE(EGL_BAD_ALLOC);
        CASE(EGL_BAD_ATTRIBUTE);
        CASE(EGL_BAD_CONFIG);
        CASE(EGL_BAD_CONTEXT);
        CASE(EGL_BAD_CURRENT_SURFACE);
        CASE(EGL_BAD_DISPLAY);
        CASE(EGL_BAD_MATCH);
        CASE(EGL_BAD_NATIVE_PIXMAP);
        CASE(EGL_BAD_NATIVE_WINDOW);
        CASE(EGL_BAD_PARAMETER);
        CASE(EGL_BAD_SURFACE);
        CASE(EGL_CONTEXT_LOST);
        default: egl_error_name = ""; break;
#undef CASE
    }

    wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                 "%s failed with error %s(0x%x)",
                 egl_func_call,
                 egl_error_name,
                 egl_error_code);
}
Пример #25
0
struct linux_dl*
linux_dl_open(int32_t waffle_dl)
{
    struct linux_dl *self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    self->name = linux_dl_get_name(waffle_dl);
    if (!self->name)
        goto error;

    self->dl = dlopen(self->name, RTLD_LAZY);
    if (!self->dl) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "dlopen(\"%s\") failed: %s", self->name, dlerror());
        goto error;
    }

    return self;

error:
    free(self);
    return NULL;
}
Пример #26
0
/// @brief Check the values of `attrs->context_*`.
static bool
glx_config_check_context_attrs(struct glx_display *dpy,
                               const struct wcore_config_attrs *attrs)
{
    struct glx_platform *plat = glx_platform(dpy->wcore.platform);

    if (attrs->context_forward_compatible) {
        assert(attrs->context_api == WAFFLE_CONTEXT_OPENGL);
        assert(wcore_config_attrs_version_ge(attrs, 30));
    }

    if (attrs->context_debug && !dpy->ARB_create_context) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "GLX_ARB_create_context is required in order to "
                     "request a debug context");
        return false;
    }

    if (attrs->context_robust && !dpy->ARB_create_context_robustness) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "GLX_ARB_create_context_robustness is required in order to "
                     "request a robust access context");
        return false;
    }

    switch (attrs->context_api) {
        case WAFFLE_CONTEXT_OPENGL:
            if (!wcore_config_attrs_version_eq(attrs, 10) && !dpy->ARB_create_context) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_ARB_create_context is required in order to "
                             "request an OpenGL version not equal to the default "
                             "value 1.0");
                return false;
            }
            else if (wcore_config_attrs_version_ge(attrs, 32) && !dpy->ARB_create_context_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_ARB_create_context_profile is required "
                             "to create a context with version >= 3.2");
                return false;
            }
            else if (wcore_config_attrs_version_ge(attrs, 32)) {
                assert(attrs->context_profile == WAFFLE_CONTEXT_CORE_PROFILE ||
                       attrs->context_profile == WAFFLE_CONTEXT_COMPATIBILITY_PROFILE);
            }

            if (attrs->context_forward_compatible && !dpy->ARB_create_context) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_ARB_create_context is required in order to "
                             "request a forward-compatible context");
                return false;
            }

            return true;

        case WAFFLE_CONTEXT_OPENGL_ES1:
            assert(wcore_config_attrs_version_eq(attrs, 10) ||
                   wcore_config_attrs_version_eq(attrs, 11));
            assert(!attrs->context_forward_compatible);

            if (!dpy->EXT_create_context_es_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_EXT_create_context_es_profile is required "
                             "to create an OpenGL ES1 context");
                return false;
            }
            else if (!linux_platform_dl_can_open(plat->linux,
                                            WAFFLE_DL_OPENGL_ES1)) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "failed to open the OpenGL ES1 library");
                return false;
            }

            return true;

        case WAFFLE_CONTEXT_OPENGL_ES2:
            assert(attrs->context_major_version == 2);
            assert(!attrs->context_forward_compatible);

            if (!dpy->EXT_create_context_es_profile
                && !dpy->EXT_create_context_es2_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_EXT_create_context_es_profile or "
                             "GLX_EXT_create_context_es2_profile is required "
                             "to create an OpenGL ES2 context");
                return false;
            }
            if (!linux_platform_dl_can_open(plat->linux,
                                            WAFFLE_DL_OPENGL_ES2)) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "failed to open the OpenGL ES2 library");
                return false;
            }
            return true;

        case WAFFLE_CONTEXT_OPENGL_ES3:
            assert(attrs->context_major_version == 3);

            if (!dpy->EXT_create_context_es_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_EXT_create_context_es_profile is required "
                             "to create an OpenGL ES3 context");
                return false;
            }

            if (!linux_platform_dl_can_open(plat->linux,
                                            WAFFLE_DL_OPENGL_ES3)) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "failed to open the OpenGL ES3 library");
                return false;
            }

            return true;

        default:
            wcore_error_internal("context_api has bad value %#x",
                                 attrs->context_api);
            return false;
    }
}
Пример #27
0
struct wcore_config*
glx_config_choose(struct wcore_platform *wc_plat,
                  struct wcore_display *wc_dpy,
                  const struct wcore_config_attrs *attrs)
{
    struct glx_config *self;
    struct glx_display *dpy = glx_display(wc_dpy);
    struct glx_platform *plat = glx_platform(wc_plat);

    GLXFBConfig *configs = NULL;
    int num_configs = 0;
    XVisualInfo *vi = NULL;

    bool ok = true;

    if (!glx_config_check_context_attrs(dpy, attrs))
        return NULL;

    self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    ok = wcore_config_init(&self->wcore, wc_dpy, attrs);
    if (!ok)
        goto error;

    int attrib_list[] = {
        // From page 12 (18 of pdf) of the GLX 1.4 spec:
        //
        //    For GLXFBConfigs that correspond to a TrueColor or DirectColor
        //    visual, GLX BUFFER SIZE is the sum of GLX RED SIZE, GLX GREEN
        //    SIZE, GLX BLUE SIZE, and GLX ALPHA SIZE.
        GLX_BUFFER_SIZE,        attrs->rgba_size,
        GLX_RED_SIZE,           attrs->red_size,
        GLX_GREEN_SIZE,         attrs->green_size,
        GLX_BLUE_SIZE,          attrs->blue_size,
        GLX_ALPHA_SIZE,         attrs->alpha_size,

        GLX_DEPTH_SIZE,         attrs->depth_size,
        GLX_STENCIL_SIZE,       attrs->stencil_size,

        GLX_SAMPLE_BUFFERS,     attrs->sample_buffers,
        GLX_SAMPLES,            attrs->samples,

        GLX_DOUBLEBUFFER,       attrs->double_buffered,

        GLX_ACCUM_RED_SIZE,     attrs->accum_buffer,
        GLX_ACCUM_GREEN_SIZE,   attrs->accum_buffer,
        GLX_ACCUM_BLUE_SIZE,    attrs->accum_buffer,
        GLX_ACCUM_ALPHA_SIZE,   attrs->accum_buffer,

        // According to the GLX 1.4 spec Table 3.4, the default value of
        // GLX_DRAWABLE_TYPE is GLX_WINDOW_BIT. Explicitly set the default
        // here for the sake of self-documentation.
        GLX_DRAWABLE_TYPE,      GLX_WINDOW_BIT,

        0,
    };

    // Set glx_fbconfig.
    configs = wrapped_glXChooseFBConfig(plat, dpy->x11.xlib,
                                        dpy->x11.screen,
                                        attrib_list,
                                        &num_configs);
    if (!configs || num_configs == 0) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "glXChooseFBConfig returned no matching configs");
        goto error;
    }
    // Simply take the first.
    self->glx_fbconfig = configs[0];

    // Set glx_fbconfig_id.
    ok = !wrapped_glXGetFBConfigAttrib(plat, dpy->x11.xlib,
                                       self->glx_fbconfig,
                                       GLX_FBCONFIG_ID,
                                       &self->glx_fbconfig_id);
    if (!ok) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN, "glxGetFBConfigAttrib failed");
        goto error;
    }

    // Set xcb_visual_id.
    vi = wrapped_glXGetVisualFromFBConfig(plat, dpy->x11.xlib,
                                          self->glx_fbconfig);
    if (!vi) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "glXGetVisualInfoFromFBConfig failed with "
                     "GLXFBConfigID=0x%x\n", self->glx_fbconfig_id);
        goto error;
    }
    self->xcb_visual_id = vi->visualid;

    goto cleanup;

error:
    glx_config_destroy(&self->wcore);
    self = NULL;

cleanup:
    if (configs)
        XFree(configs);
    if (vi)
        XFree(vi);

    return &self->wcore;
}
Пример #28
0
static bool
parse_context_version(struct wcore_config_attrs *attrs,
                      const int32_t attrib_list[])
{
    wcore_attrib_list_get_with_default(attrib_list,
                                       WAFFLE_CONTEXT_MAJOR_VERSION,
                                       &attrs->context_major_version,
                                       attrs->context_major_version);
    wcore_attrib_list_get_with_default(attrib_list,
                                       WAFFLE_CONTEXT_MINOR_VERSION,
                                       &attrs->context_minor_version,
                                       attrs->context_minor_version);

    if (attrs->context_major_version < 1) {
        wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                     "WAFFLE_CONTEXT_MAJOR_VERSION must be >= 1");
        return false;
    }

    if (attrs->context_minor_version < 0) {
        wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                     "WAFFLE_CONTEXT_MINOR_VERSION must be >= 0");
        return false;
    }

    attrs->context_full_version =
            10 * attrs->context_major_version
            + attrs->context_minor_version;

    switch (attrs->context_api) {
        case WAFFLE_CONTEXT_OPENGL:
            if (attrs->context_full_version < 10) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL, the requested context version "
                             "must be >= 1.0");
                return false;
            }
            break;

        case WAFFLE_CONTEXT_OPENGL_ES1:
            if (attrs->context_full_version != 10 &&
                attrs->context_full_version != 11) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL ES1, the requested context version "
                             "must be 1.0 or 1.1");
                return false;
            }
            break;

        case WAFFLE_CONTEXT_OPENGL_ES2:
            if (attrs->context_major_version != 2) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL ES2, the requested major context "
                             "version must be 2");
                return false;
            }
            break;

        case WAFFLE_CONTEXT_OPENGL_ES3:
            if (attrs->context_major_version != 3) {
                wcore_errorf(WAFFLE_ERROR_BAD_ATTRIBUTE,
                             "for OpenGL ES3, the requested major context "
                             "version must be 3");
                return false;
            }
            break;

        default:
            wcore_error_internal("attrs->context_api has bad value 0x%x",
                                 attrs->context_api);
            return false;
    }

    return true;
}
Пример #29
0
struct wcore_config*
nacl_config_choose(struct wcore_platform *wc_plat,
                  struct wcore_display *wc_dpy,
                  const struct wcore_config_attrs *attrs)
{
    struct nacl_config *self;
    bool ok = true;

    self = wcore_calloc(sizeof(*self));
    if (self == NULL)
        return NULL;

    // Currently only OpenGL ES 2.0 is supported.
    if (attrs->context_api != WAFFLE_CONTEXT_OPENGL_ES2) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "NaCl does no support context type %s.",
                     wcore_enum_to_string(attrs->context_api));
        goto error;
    }

    if (attrs->context_robust) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "NaCl does not support robust contexts.");
        goto error;
    }

    unsigned attr = 0;

    // Max amount of attribs is hardcoded in nacl_config.h (64)
#define PUSH_ATTRIB(a, val) \
    if (val != WAFFLE_DONT_CARE) {\
        self->attribs[attr++] = a; \
        self->attribs[attr++] = val;\
    }

    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_ALPHA_SIZE,     attrs->alpha_size);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_BLUE_SIZE,      attrs->blue_size);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_GREEN_SIZE,     attrs->green_size);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_RED_SIZE,       attrs->red_size);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_DEPTH_SIZE,     attrs->depth_size);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_STENCIL_SIZE,   attrs->stencil_size);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_SAMPLES,        attrs->samples);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, attrs->sample_buffers);

    // Note, we have to have at least 1x1 size so that initial context
    // backing surface creation will succeed without errors. Later on
    // it is resized by window creation/resize.
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_WIDTH,  1);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_HEIGHT, 1);
    PUSH_ATTRIB(PP_GRAPHICS3DATTRIB_NONE, 0);

#undef PUSH_ATTRIB

    ok = wcore_config_init(&self->wcore, wc_dpy, attrs);
    if (!ok)
        goto error;

    return &self->wcore;

error:
    nacl_config_destroy(&self->wcore);
    self = NULL;
    return NULL;
}
Пример #30
0
/// @brief Check the values of `attrs->context_*`.
static bool
glx_config_check_context_attrs(struct glx_display *dpy,
                               const struct wcore_config_attrs *attrs)
{
    if (attrs->context_forward_compatible) {
        assert(attrs->context_api == WAFFLE_CONTEXT_OPENGL);
        assert(wcore_config_attrs_version_ge(attrs, 30));
    }

    if (attrs->context_debug && !dpy->ARB_create_context) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "GLX_ARB_create_context is required in order to "
                     "request a debug context");
        return false;
    }

    if (attrs->context_robust && !dpy->ARB_create_context_robustness) {
        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                     "GLX_ARB_create_context_robustness is required in order to "
                     "request a robust access context");
        return false;
    }

    switch (attrs->context_api) {
        case WAFFLE_CONTEXT_OPENGL:
            if (glx_context_needs_arb_create_context(attrs) &&
                !dpy->ARB_create_context) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_ARB_create_context is required in order to "
                             "request an OpenGL version greater or equal than 3.2");
                return false;
            }
            else if (wcore_config_attrs_version_ge(attrs, 32) && !dpy->ARB_create_context_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_ARB_create_context_profile is required "
                             "to create a context with version >= 3.2");
                return false;
            }
            else if (wcore_config_attrs_version_ge(attrs, 32)) {
                assert(attrs->context_profile == WAFFLE_CONTEXT_CORE_PROFILE ||
                       attrs->context_profile == WAFFLE_CONTEXT_COMPATIBILITY_PROFILE);
            }

            if (attrs->context_forward_compatible && !dpy->ARB_create_context) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_ARB_create_context is required in order to "
                             "request a forward-compatible context");
                return false;
            }

            return true;

        case WAFFLE_CONTEXT_OPENGL_ES1:
            if (!dpy->EXT_create_context_es_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_EXT_create_context_es_profile is required "
                             "to create an OpenGL ES1 context");
                return false;
            }

            return true;

        case WAFFLE_CONTEXT_OPENGL_ES2:
            if (!dpy->EXT_create_context_es_profile
                && !dpy->EXT_create_context_es2_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_EXT_create_context_es_profile or "
                             "GLX_EXT_create_context_es2_profile is required "
                             "to create an OpenGL ES2 context");
                return false;
            }

            return true;

        case WAFFLE_CONTEXT_OPENGL_ES3:
            if (!dpy->EXT_create_context_es_profile) {
                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                             "GLX_EXT_create_context_es_profile is required "
                             "to create an OpenGL ES3 context");
                return false;
            }

            return true;

        default:
            assert(false);
            return false;
    }
}