YaGL: modify native configs enumerator in OS X
authorJinhyung Jo <jinhyung.jo@samsung.com>
Wed, 20 Jan 2016 08:03:46 +0000 (17:03 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 27 Jan 2016 06:29:35 +0000 (15:29 +0900)
Some apps want to get the config without multisampling.
Currently, YaGL module provides only one config with multisampling attribute.
So the apps fail because they can not find the matched config in OS X.
So add one more pixelformat without multisampling attribute & add related tasks.

Change-Id: Ibf41243110d9212b9a62e4006dfa6f9c4356291f
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
(cherry picked from commit 2c9de13bde79583b1f6dfe78fc16f3cfcec99973)

hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c

index 561c8203668fa3d5e591c10ead4fcbfe27bd909c..0f398babde77d77119762a7d9b3b75fae9d80add 100644 (file)
 #   define kCGLOGLPVersion_Legacy 0x1000
 #endif
 
+#define YAGL_EGL_CGL_GET_CONFIG_ATTRIB_RET(index, attribute, value) \
+    error = CGLDescribePixelFormat(pixel_format, (index), (attribute), (value)); \
+    if (error) { \
+        YAGL_LOG_WARN("CGLDescribePixelFormat failed to get " #attribute); \
+        YAGL_LOG_FUNC_EXIT(NULL); \
+        return false; \
+    }
+
 static const CGLPixelFormatAttribute prefered_pixel_format_legacy_attrs[] =
 {
     kCGLPFAAccelerated,
@@ -106,7 +114,9 @@ struct yagl_egl_cgl
     struct yagl_egl_driver base;
 
     CGLPixelFormatObj pixel_format_legacy;
+    CGLPixelFormatObj pixel_format_legacy_ms;
     CGLPixelFormatObj pixel_format_3_2_core;
+    CGLPixelFormatObj pixel_format_3_2_core_ms;
 };
 
 struct yagl_egl_cgl_context
@@ -126,30 +136,6 @@ static const char *gl_3_2_check_funcs[] =
     "glVertexAttribDivisor"
 };
 
-static CGLError yagl_egl_cgl_choose_pixel_format(const CGLPixelFormatAttribute prefered_attrs[],
-                                                 const CGLPixelFormatAttribute fallback_attrs[],
-                                                 CGLPixelFormatObj *pix,
-                                                 int *n)
-{
-    CGLError error;
-
-    YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_choose_pixel_format, NULL);
-
-    error = CGLChoosePixelFormat(prefered_attrs, pix, n);
-
-    if (error) {
-        YAGL_LOG_WARN("CGLChoosePixelFormat: error occurs (%s)",
-                      CGLErrorString(error));
-        return CGLChoosePixelFormat(fallback_attrs, pix, n);
-    } else if (*pix == NULL || *n == 0) {
-        YAGL_LOG_WARN("CGLChoosePixelFormat: no suitable prefered format found");
-        return CGLChoosePixelFormat(fallback_attrs, pix, n);
-    } else {
-        return error;
-    }
-
-}
-
 static bool yagl_egl_cgl_get_gl_version(struct yagl_egl_cgl *egl_cgl,
                                         const char *gl_version,
                                         yagl_gl_version *version)
@@ -242,32 +228,39 @@ static void yagl_egl_cgl_display_close(struct yagl_egl_driver *driver,
     YAGL_LOG_FUNC_EXIT(NULL);
 }
 
-static struct yagl_egl_native_config
-    *yagl_egl_cgl_config_enum(struct yagl_egl_driver *driver,
-                              EGLNativeDisplayType dpy,
-                              int *num_configs)
+static bool yagl_egl_cgl_config_fill(CGLPixelFormatObj pixel_format,
+                                     struct yagl_egl_native_config *cfg,
+                                     int screen_idx, int cfg_idx)
 {
-    struct yagl_egl_cgl *egl_cgl = (struct yagl_egl_cgl*)driver;
-    struct yagl_egl_native_config *cfg = NULL;
+    int buffer_size = 0;
+    int alpha_size = 0;
+    int depth_size = 0;
+    int stencil_size = 0;
+    int samples_per_pixel = 0;
     CGLError error;
 
-    YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_config_enum, "%p", dpy);
+    YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_config_fill, NULL);
 
-    YAGL_LOG_TRACE("got 1 config");
+    YAGL_EGL_CGL_GET_CONFIG_ATTRIB_RET(screen_idx, kCGLPFAAlphaSize, &alpha_size);
+    YAGL_EGL_CGL_GET_CONFIG_ATTRIB_RET(screen_idx, kCGLPFADepthSize, &depth_size);
+    YAGL_EGL_CGL_GET_CONFIG_ATTRIB_RET(screen_idx, kCGLPFAStencilSize, &stencil_size);
+    YAGL_EGL_CGL_GET_CONFIG_ATTRIB_RET(screen_idx, kCGLPFAColorSize, &buffer_size);
 
-    cfg = g_malloc0(sizeof(*cfg));
+    YAGL_EGL_CGL_GET_CONFIG_ATTRIB_RET(screen_idx, kCGLPFASamples, &samples_per_pixel);
 
     yagl_egl_native_config_init(cfg);
 
+    cfg->config_id = cfg_idx;
     cfg->red_size = 8;
     cfg->green_size = 8;
     cfg->blue_size = 8;
-    cfg->alpha_size = 8;
-    cfg->buffer_size = 32;
+    cfg->alpha_size = alpha_size;
+    cfg->buffer_size = buffer_size;
+    cfg->stencil_size = stencil_size;
+    cfg->depth_size = depth_size;
+    cfg->samples_per_pixel = samples_per_pixel;
     cfg->caveat = EGL_NONE;
-    cfg->config_id = 1;
     cfg->frame_buffer_level = 0;
-    cfg->depth_size = 24;
     cfg->max_pbuffer_width = 4096;
     cfg->max_pbuffer_height = 4096;
     cfg->max_pbuffer_size = 4096 * 4096;
@@ -275,37 +268,95 @@ static struct yagl_egl_native_config
     cfg->min_swap_interval = 0;
     cfg->native_visual_id = 0;
     cfg->native_visual_type = EGL_NONE;
+    cfg->transparent_type = EGL_NONE;
+    cfg->trans_red_val = 0;
+    cfg->trans_green_val = 0;
+    cfg->trans_blue_val = 0;
+    cfg->driver_data = pixel_format;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return true;
+}
+
+static struct yagl_egl_native_config
+    *yagl_egl_cgl_config_enum(struct yagl_egl_driver *driver,
+                              EGLNativeDisplayType dpy,
+                              int *num_configs)
+{
+    struct yagl_egl_cgl *egl_cgl = (struct yagl_egl_cgl*)driver;
+    struct yagl_egl_native_config *cfgs = NULL;
+    CGLPixelFormatObj pixel_format = NULL, pixel_format_ms = NULL;
+    int n = 0, n_ms = 0;
+    int screen_idx, cfg_idx;
+    CGLError error;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_config_enum, "%p", dpy);
+
+    *num_configs = 0;
 
     if (egl_cgl->base.gl_version >= yagl_gl_3_2) {
-        error = CGLDescribePixelFormat(egl_cgl->pixel_format_3_2_core,
-                                       0,
-                                       kCGLPFASamples,
-                                       &cfg->samples_per_pixel);
+        pixel_format = egl_cgl->pixel_format_3_2_core;
+        pixel_format_ms = egl_cgl->pixel_format_3_2_core_ms;
     } else {
-        error = CGLDescribePixelFormat(egl_cgl->pixel_format_legacy,
-                                       0,
-                                       kCGLPFASamples,
-                                       &cfg->samples_per_pixel);
+        pixel_format = egl_cgl->pixel_format_legacy;
+        pixel_format_ms = egl_cgl->pixel_format_legacy_ms;
     }
 
+    error = CGLDescribePixelFormat(pixel_format,
+                                   0,
+                                   kCGLPFAVirtualScreenCount,
+                                   &n);
     if (error) {
-        YAGL_LOG_WARN("CGLDescribePixelFormat(kCGLPFASamples) failed: %s",
-                      CGLErrorString(error));
-        cfg->samples_per_pixel = 0;
+        YAGL_LOG_ERROR("CGLDescribePixelFormat failed: %s",
+                       CGLErrorString(error));
+        return NULL;
     }
 
-    cfg->stencil_size = 8;
-    cfg->transparent_type = EGL_NONE;
-    cfg->trans_red_val = 0;
-    cfg->trans_green_val = 0;
-    cfg->trans_blue_val = 0;
-    cfg->driver_data = NULL;
+    if (pixel_format_ms) {
+        error = CGLDescribePixelFormat(pixel_format_ms,
+                                       0,
+                                       kCGLPFAVirtualScreenCount,
+                                       &n_ms);
+        if (error) {
+            YAGL_LOG_ERROR("CGLDescribePixelFormat failed: %s",
+                           CGLErrorString(error));
+            return NULL;
+        }
+    }
+
+    YAGL_LOG_TRACE("got %d config", n + n_ms);
+
+    cfgs = g_new0(struct yagl_egl_native_config, n + n_ms);
+
+    for (screen_idx = 0, cfg_idx = 0; screen_idx < n; ++screen_idx) {
+        if (yagl_egl_cgl_config_fill(pixel_format,
+                                     &cfgs[cfg_idx],
+                                     screen_idx, cfg_idx)) {
+            ++cfg_idx;
+        }
+    }
+    if (pixel_format_ms) {
+        for (screen_idx = 0; screen_idx < n_ms; ++screen_idx) {
+            if (yagl_egl_cgl_config_fill(pixel_format_ms,
+                                         &cfgs[cfg_idx],
+                                         screen_idx, cfg_idx)) {
+                ++cfg_idx;
+            }
+        }
+    }
 
-    *num_configs = 1;
+    if (cfg_idx < n + n_ms) {
+        cfgs = g_renew(struct yagl_egl_native_config,
+                       cfgs,
+                       cfg_idx);
+    }
+
+    *num_configs = cfg_idx;
 
     YAGL_LOG_FUNC_EXIT(NULL);
 
-    return cfg;
+    return cfgs;
 }
 
 static void yagl_egl_cgl_config_cleanup(struct yagl_egl_driver *driver,
@@ -395,16 +446,13 @@ static EGLContext yagl_egl_cgl_context_create(struct yagl_egl_driver *driver,
     }
 
     if ((egl_cgl->base.gl_version > yagl_gl_2) && (version != 1)) {
-        error = CGLCreateContext(egl_cgl->pixel_format_3_2_core,
-                                 share_ctx,
-                                 &ctx->base);
         ctx->is_3_2_core = true;
     } else {
-        error = CGLCreateContext(egl_cgl->pixel_format_legacy,
-                                 share_ctx,
-                                 &ctx->base);
         ctx->is_3_2_core = false;
     }
+    error = CGLCreateContext((CGLPixelFormatObj)cfg->driver_data,
+                             share_ctx,
+                             &ctx->base);
 
     if (error) {
         YAGL_LOG_ERROR("CGLCreateContext failed: %s", CGLErrorString(error));
@@ -501,9 +549,15 @@ static void yagl_egl_cgl_destroy(struct yagl_egl_driver *driver)
     YAGL_LOG_FUNC_ENTER(yagl_egl_cgl_destroy, NULL);
 
     CGLDestroyPixelFormat(egl_cgl->pixel_format_legacy);
+    if (egl_cgl->pixel_format_legacy_ms) {
+        CGLDestroyPixelFormat(egl_cgl->pixel_format_legacy_ms);
+    }
     if (egl_cgl->pixel_format_3_2_core) {
         CGLDestroyPixelFormat(egl_cgl->pixel_format_3_2_core);
     }
+    if (egl_cgl->pixel_format_3_2_core_ms) {
+        CGLDestroyPixelFormat(egl_cgl->pixel_format_3_2_core_ms);
+    }
 
     yagl_egl_driver_cleanup(&egl_cgl->base);
 
@@ -543,33 +597,35 @@ struct yagl_egl_driver *yagl_egl_driver_create(void *display,
         goto fail;
     }
 
-    error = yagl_egl_cgl_choose_pixel_format(prefered_pixel_format_legacy_attrs,
-                                             pixel_format_legacy_attrs,
-                                             &egl_cgl->pixel_format_legacy,
-                                             &n);
-
-    if (error) {
-        YAGL_LOG_ERROR("CGLChoosePixelFormat failed for legacy attrs: %s", CGLErrorString(error));
-        goto fail;
+    error = CGLChoosePixelFormat(prefered_pixel_format_legacy_attrs,
+                                 &egl_cgl->pixel_format_legacy_ms,
+                                 &n);
+    if (error || !egl_cgl->pixel_format_legacy_ms || n == 0) {
+        YAGL_LOG_WARN("CGLChoosePixelFormat failed for legacy attrs with multisampling");
+        egl_cgl->pixel_format_legacy_ms = NULL;
     }
 
-    if (!egl_cgl->pixel_format_legacy) {
+    error = CGLChoosePixelFormat(pixel_format_legacy_attrs,
+                                 &egl_cgl->pixel_format_legacy,
+                                 &n);
+    if (error || !egl_cgl->pixel_format_legacy || n == 0) {
         YAGL_LOG_ERROR("CGLChoosePixelFormat failed to find formats for legacy attrs");
         goto fail;
     }
 
     if (egl_cgl->base.gl_version >= yagl_gl_3_2) {
-        error = yagl_egl_cgl_choose_pixel_format(prefered_pixel_format_3_2_core_attrs,
-                                                 pixel_format_3_2_core_attrs,
-                                                 &egl_cgl->pixel_format_3_2_core,
-                                                 &n);
-
-        if (error) {
-            YAGL_LOG_ERROR("CGLChoosePixelFormat failed for 3_2_core attrs: %s", CGLErrorString(error));
-            goto fail;
+        error = CGLChoosePixelFormat(prefered_pixel_format_3_2_core_attrs,
+                                     &egl_cgl->pixel_format_3_2_core_ms,
+                                     &n);
+        if (error || !egl_cgl->pixel_format_3_2_core_ms || n == 0) {
+            YAGL_LOG_ERROR("CGLChoosePixelFormat failed for 3_2_core attrs with multisampling");
+            egl_cgl->pixel_format_3_2_core_ms = NULL;
         }
 
-        if (!egl_cgl->pixel_format_3_2_core) {
+        error = CGLChoosePixelFormat(pixel_format_3_2_core_attrs,
+                                     &egl_cgl->pixel_format_3_2_core,
+                                     &n);
+        if (error || !egl_cgl->pixel_format_3_2_core || n == 0) {
             YAGL_LOG_ERROR("CGLChoosePixelFormat failed to find formats for 3_2_core attrs");
             goto fail;
         }