diff --git a/src/macosx/osxgl.m b/src/macosx/osxgl.m index 316f9c33f0..89120a1c85 100644 --- a/src/macosx/osxgl.m +++ b/src/macosx/osxgl.m @@ -767,8 +767,6 @@ static void osx_set_opengl_pixelformat_attributes(ALLEGRO_DISPLAY_OSX_WIN *dpy) // Take over the screen. *a = NSOpenGLPFAScreenMask; a++; *a = CGDisplayIDToOpenGLDisplayMask(dpy->display_id); a++; - } else { - *a = NSOpenGLPFAWindow; a++; } /* Find the requested colour depth */ @@ -846,9 +844,21 @@ static void osx_set_opengl_pixelformat_attributes(ALLEGRO_DISPLAY_OSX_WIN *dpy) /* Accelerated is always preferred, so we only set this for required not * for suggested. */ - if (extras->required & ALLEGRO_RENDER_METHOD) { + if (extras->required & (1UL << ALLEGRO_RENDER_METHOD)) { *a++ = NSOpenGLPFAAccelerated; } + /* + * OpenGL 3+ support + * Newer versions of macos support modern OpenGL, but won't create a view + * that supports it unless explicitly requested to. Note that even though + * this looks like 3.2 core, it is really >= 3.2, and it is quite strict + * about removing support for legacy OpenGL features, and requires versioned + * shaders. + */ + if (dpy->parent.flags & ALLEGRO_OPENGL_3_0) { + *a++ = NSOpenGLPFAOpenGLProfile; + *a++ = (NSOpenGLPixelFormatAttribute) NSOpenGLProfileVersion3_2Core; + } } @@ -1244,7 +1254,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) [dpy->win setTitle: title]; [dpy->win setAcceptsMouseMovedEvents:YES]; [dpy->win setViewsNeedDisplay:NO]; - + NSView *window_view = [[NSView alloc] initWithFrame:rect]; [window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; [[dpy->win contentView] addSubview:window_view]; @@ -1543,7 +1553,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) mask |= NSWindowStyleMaskResizable; if (display->flags & ALLEGRO_FULLSCREEN) mask |= NSWindowStyleMaskResizable; - + if ((adapter >= 0) && (adapter < al_get_num_video_adapters())) { screen = [[NSScreen screens] objectAtIndex: adapter]; @@ -1578,7 +1588,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) ALLEGRO_DEBUG("Could not create rendering context\n"); [view release]; [fmt release]; - + return; } /* Hook up the view to its display */ @@ -1596,7 +1606,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) */ [win setMinSize: NSMakeSize(MINIMUM_WIDTH / screen_scale_factor, MINIMUM_HEIGHT / screen_scale_factor)]; - + /* Maximize the window and update its width & height information */ if (display->flags & ALLEGRO_MAXIMIZED) { [win setFrame: [screen visibleFrame] display: true animate: false]; @@ -1604,7 +1614,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) display->w = content.size.width; display->h = content.size.height; } - + /* Place the window, respecting the location set by the user with * al_set_new_window_position(). * If the user never called al_set_new_window_position, we simply let @@ -1614,7 +1624,7 @@ static void init_new_vsync(ALLEGRO_DISPLAY_OSX_WIN *dpy) * the range -16000 ... 16000 (approximately, probably the range of a * signed 16 bit integer). Should we check for this? */ - + if ((x != INT_MAX) && (y != INT_MAX)) { /* The user gave us window coordinates */ NSRect rc = [win frame]; @@ -1711,13 +1721,13 @@ static void destroy_display(ALLEGRO_DISPLAY* d) ALLEGRO_DISPLAY_OSX_WIN* dpy = (ALLEGRO_DISPLAY_OSX_WIN*) d; ALLEGRO_DISPLAY_OSX_WIN* other = NULL; unsigned int i; - + // Set the display as the current display; needed because we need to // make the context current. if (old_dpy != d) { _al_set_current_display_only(d); } - + /* First of all, save video bitmaps attached to this display. */ // Check for other displays in this display group _AL_VECTOR* dpys = &al_get_system_driver()->displays; @@ -1788,7 +1798,7 @@ static void destroy_display(ALLEGRO_DISPLAY* d) [dpy->cursor release]; _al_event_source_free(&d->es); al_free(d->ogl_extras); - + // Restore original display from before this function was called. // If the display we just destroyed is actually current, set the current // display to NULL. @@ -1798,7 +1808,7 @@ static void destroy_display(ALLEGRO_DISPLAY* d) // Is this redundant? --pw _al_set_current_display_only(NULL); } - + if (dpy->flip_mutex) { al_destroy_mutex(dpy->flip_mutex); al_destroy_cond(dpy->flip_cond); @@ -2260,7 +2270,7 @@ static void get_window_position(ALLEGRO_DISPLAY* display, int* px, int* py) ASSERT_USER_THREAD(); ALLEGRO_DISPLAY_OSX_WIN* d = (ALLEGRO_DISPLAY_OSX_WIN*) display; NSWindow* window = d->win; - + int primary_y = _al_osx_get_primary_screen_y(); float global_scale_factor = _al_osx_get_global_scale_factor(); dispatch_sync(dispatch_get_main_queue(), ^{ diff --git a/src/opengl/ogl_shader.c b/src/opengl/ogl_shader.c index 21762c2ae7..d01cd7f6d7 100644 --- a/src/opengl/ogl_shader.c +++ b/src/opengl/ogl_shader.c @@ -124,7 +124,22 @@ static bool glsl_attach_shader_source(ALLEGRO_SHADER *shader, if ((*handle) == 0) { return false; } +#ifdef ALLEGRO_MACOSX + { + const char *version_string = glGetString(GL_SHADING_LANGUAGE_VERSION); + int version[2]; + sscanf(version_string, "%d.%d", &version[0], &version[1]); + char version_line[] = "#version XXXXXXXXXX"; + ASSERT(version[0] < 10 && version[1] < 100); + snprintf(version_line, sizeof(version_line), "#version %d%d\n", version[0], version[1]); + + const char *sources[] = {version_line, source}; + + glShaderSource(*handle, 2, sources, NULL); + } +#else glShaderSource(*handle, 1, &source, NULL); +#endif glCompileShader(*handle); glGetShaderiv(*handle, GL_COMPILE_STATUS, &status); if (status == 0) { diff --git a/src/shader.c b/src/shader.c index a0a51b7acb..51d2847db6 100644 --- a/src/shader.c +++ b/src/shader.c @@ -415,14 +415,28 @@ char const *al_get_default_shader_source(ALLEGRO_SHADER_PLATFORM platform, ALLEGRO_SHADER_TYPE type) { (void)type; + bool use_gl3_shader = false; +#ifdef ALLEGRO_MACOSX + { + ALLEGRO_DISPLAY *display = al_get_current_display(); + + + /* Apple's glsl implementation supports either 1.20 shaders, or strictly + * versioned 3.2+ shaders which do not use deprecated features. + */ + if (display && (display->flags & ALLEGRO_OPENGL_3_0)) { + use_gl3_shader = true; + } + } +#endif switch (resolve_platform(al_get_current_display(), platform)) { case ALLEGRO_SHADER_GLSL: #ifdef ALLEGRO_CFG_SHADER_GLSL switch (type) { case ALLEGRO_VERTEX_SHADER: - return default_glsl_vertex_source; + return use_gl3_shader ? default_glsl_vertex_source_gl3 : default_glsl_vertex_source; case ALLEGRO_PIXEL_SHADER: - return default_glsl_pixel_source; + return use_gl3_shader ? default_glsl_pixel_source_gl3 : default_glsl_pixel_source; } #endif break; @@ -430,9 +444,9 @@ char const *al_get_default_shader_source(ALLEGRO_SHADER_PLATFORM platform, #ifdef ALLEGRO_CFG_SHADER_GLSL switch (type) { case ALLEGRO_VERTEX_SHADER: - return default_glsl_vertex_source; + return use_gl3_shader ? default_glsl_vertex_source_gl3 : default_glsl_vertex_source; case ALLEGRO_PIXEL_SHADER: - return default_glsl_minimal_pixel_source; + return use_gl3_shader ? default_glsl_minimal_pixel_source_gl3 : default_glsl_minimal_pixel_source; } #endif break; diff --git a/src/shader_source.inc b/src/shader_source.inc index f2dbd98f0a..03826a031e 100644 --- a/src/shader_source.inc +++ b/src/shader_source.inc @@ -98,6 +98,90 @@ static const char *default_glsl_minimal_pixel_source = " gl_FragColor = c;\n" "}\n"; +static const char *default_glsl_vertex_source_gl3 = + "in vec4 " ALLEGRO_SHADER_VAR_POS ";\n" + "in vec4 " ALLEGRO_SHADER_VAR_COLOR ";\n" + "in vec2 " ALLEGRO_SHADER_VAR_TEXCOORD ";\n" + "uniform mat4 " ALLEGRO_SHADER_VAR_PROJVIEW_MATRIX ";\n" + "uniform bool " ALLEGRO_SHADER_VAR_USE_TEX_MATRIX ";\n" + "uniform mat4 " ALLEGRO_SHADER_VAR_TEX_MATRIX ";\n" + "out vec4 varying_color;\n" + "out vec2 varying_texcoord;\n" + "void main()\n" + "{\n" + " varying_color = " ALLEGRO_SHADER_VAR_COLOR ";\n" + " if (" ALLEGRO_SHADER_VAR_USE_TEX_MATRIX ") {\n" + " vec4 uv = " ALLEGRO_SHADER_VAR_TEX_MATRIX " * vec4(" ALLEGRO_SHADER_VAR_TEXCOORD ", 0, 1);\n" + " varying_texcoord = vec2(uv.x, uv.y);\n" + " }\n" + " else\n" + " varying_texcoord = " ALLEGRO_SHADER_VAR_TEXCOORD";\n" + " gl_Position = " ALLEGRO_SHADER_VAR_PROJVIEW_MATRIX " * " ALLEGRO_SHADER_VAR_POS ";\n" + "}\n"; + +static const char *default_glsl_pixel_source_gl3 = + "#ifdef GL_ES\n" + "precision lowp float;\n" + "#endif\n" + "uniform sampler2D " ALLEGRO_SHADER_VAR_TEX ";\n" + "uniform bool " ALLEGRO_SHADER_VAR_USE_TEX ";\n" + "uniform bool " ALLEGRO_SHADER_VAR_ALPHA_TEST ";\n" + "uniform int " ALLEGRO_SHADER_VAR_ALPHA_FUNCTION ";\n" + "uniform float " ALLEGRO_SHADER_VAR_ALPHA_TEST_VALUE ";\n" + "in vec4 varying_color;\n" + "in vec2 varying_texcoord;\n" + "layout(location = 0) out vec4 diffuseColor;\n" + "\n" + "bool alpha_test_func(float x, int op, float compare);\n" + "\n" + "void main()\n" + "{\n" + " vec4 c;\n" + " if (" ALLEGRO_SHADER_VAR_USE_TEX ")\n" + " c = varying_color * texture(" ALLEGRO_SHADER_VAR_TEX ", varying_texcoord);\n" + " else\n" + " c = varying_color;\n" + " if (!" ALLEGRO_SHADER_VAR_ALPHA_TEST " || alpha_test_func(c.a, " ALLEGRO_SHADER_VAR_ALPHA_FUNCTION ", " + ALLEGRO_SHADER_VAR_ALPHA_TEST_VALUE "))\n" + " diffuseColor = c;\n" + " else\n" + " discard;\n" + "}\n" + "\n" + "bool alpha_test_func(float x, int op, float compare)\n" + "{\n" + // Note: These must be aligned with the ALLEGRO_RENDER_FUNCTION enum values. + " if (op == 0) return false;\n" // ALLEGRO_RENDER_NEVER + " else if (op == 1) return true;\n" // ALLEGRO_RENDER_ALWAYS + " else if (op == 2) return x < compare;\n" // ALLEGRO_RENDER_LESS + " else if (op == 3) return x == compare;\n" // ALLEGRO_RENDER_EQUAL + " else if (op == 4) return x <= compare;\n" // ALLEGRO_RENDER_LESS_EQUAL + " else if (op == 5) return x > compare;\n" // ALLEGRO_RENDER_GREATER + " else if (op == 6) return x != compare;\n" // ALLEGRO_RENDER_NOT_EQUAL + " else if (op == 7) return x >= compare;\n" // ALLEGRO_RENDER_GREATER_EQUAL + " return false;\n" + "}\n"; + +static const char *default_glsl_minimal_pixel_source_gl3 = + "#ifdef GL_ES\n" + "precision lowp float;\n" + "#endif\n" + "uniform sampler2D " ALLEGRO_SHADER_VAR_TEX ";\n" + "uniform bool " ALLEGRO_SHADER_VAR_USE_TEX ";\n" + "in vec4 varying_color;\n" + "in vec2 varying_texcoord;\n" + "layout(location = 0) out vec4 diffuseColor;\n" + "\n" + "void main()\n" + "{\n" + " vec4 c;\n" + " if (" ALLEGRO_SHADER_VAR_USE_TEX ")\n" + " c = varying_color * texture2D(" ALLEGRO_SHADER_VAR_TEX ", varying_texcoord);\n" + " else\n" + " c = varying_color;\n" + " diffuseColor = c;\n" + "}\n"; + #endif /* ALLEGRO_CFG_SHADER_GLSL */