diff --git a/metal/4ed_metal_render.mm b/metal/4ed_metal_render.mm index 147af602..d5126396 100644 --- a/metal/4ed_metal_render.mm +++ b/metal/4ed_metal_render.mm @@ -263,8 +263,10 @@ metal__make_buffer(u32 size, id device){ [capture_scope beginScope]; - i32 width = _target->width; - i32 height = _target->height; + // HACK(yuval): This is the best way I found to force valid width and height without drawing on the next drawing cycle (1 frame delay). + CGSize drawable_size = [view drawableSize]; + i32 width = (i32)Min(_target->width, drawable_size.width); + i32 height = (i32)Min(_target->height, drawable_size.height); Font_Set *font_set = (Font_Set*)_target->font_set; @@ -332,6 +334,7 @@ metal__make_buffer(u32 size, id device){ { Rect_i32 box = Ri32(group->clip_box); + NSUInteger x0 = (NSUInteger)Min(Max(0, box.x0), width - 1); NSUInteger x1 = (NSUInteger)Min(Max(0, box.x1), width); NSUInteger y0 = (NSUInteger)Min(Max(0, box.y0), height - 1); diff --git a/opengl/4ed_opengl_render.cpp b/opengl/4ed_opengl_render.cpp index 2246eaeb..69071502 100644 --- a/opengl/4ed_opengl_render.cpp +++ b/opengl/4ed_opengl_render.cpp @@ -129,7 +129,7 @@ sd = abs(sd + half_thickness) - half_thickness; float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd); shape_value *= has_thickness; -out_color = fragment_color;//vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value)); +out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value)); } )foo"; @@ -285,8 +285,6 @@ gl_render(Render_Target *t){ t->free_texture_first = 0; t->free_texture_last = 0; - u32 all_vertex_count = 0; - u64 begin_draw = system_now_time(); for (Render_Group *group = t->group_first; group != 0; @@ -342,18 +340,9 @@ gl_render(Render_Target *t){ glDisableVertexAttribArray(gpu_program.vertex_c); glDisableVertexAttribArray(gpu_program.vertex_ht); } - - all_vertex_count += vertex_count; } - u64 end_draw = system_now_time(); - printf("Draw time: %fs\n", mac_get_time_diff_sec(begin_draw, end_draw)); - u64 begin_flush = system_now_time(); glFlush(); - u64 end_flush = system_now_time(); - printf("Flush time: %fs\n", mac_get_time_diff_sec(begin_flush, end_flush)); - - printf("Drawn %d Vertices\n", all_vertex_count); } // BOTTOM diff --git a/platform_mac/mac_4ed.mm b/platform_mac/mac_4ed.mm index 05d07a2a..33f645f7 100644 --- a/platform_mac/mac_4ed.mm +++ b/platform_mac/mac_4ed.mm @@ -132,8 +132,6 @@ struct Mac_Input_Chunk{ //////////////////////////////// -//////////////////////////////// - typedef i32 Mac_Object_Kind; enum{ MacObjectKind_ERROR = 0, @@ -203,7 +201,12 @@ struct Mac_Vars { //////////////////////////////// +#include "mac_4ed_renderer.h" + +//////////////////////////////// + global Mac_Vars mac_vars; +global Mac_Renderer *renderer; global Render_Target target; global App_Functions app; @@ -269,30 +272,6 @@ mac_to_object(Plat_Handle handle){ //////////////////////////////// -#include -#include -#import "mac_4ed_opengl.mm" - -#import "mac_4ed_metal.mm" - -#include "4ed_font_provider_freetype.h" -#include "4ed_font_provider_freetype.cpp" - -#import "mac_4ed_functions.mm" - - - -//////////////////////////////// - -global Key_Code keycode_lookup_table[255]; - -function void -mac_key_code_init(void){ - -} - -//////////////////////////////// - function void mac_error_box(char *msg, b32 shutdown = true){ NSAlert *alert = [[[NSAlert alloc] init] autorelease]; @@ -309,6 +288,26 @@ mac_error_box(char *msg, b32 shutdown = true){ } } +//////////////////////////////// + +#import "mac_4ed_renderer.mm" + +#include "4ed_font_provider_freetype.h" +#include "4ed_font_provider_freetype.cpp" + +#import "mac_4ed_functions.mm" + +//////////////////////////////// + +global Key_Code keycode_lookup_table[255]; + +function void +mac_key_code_init(void){ + +} + +//////////////////////////////// + function b32 mac_file_can_be_made(u8* filename){ b32 result = access((char*)filename, W_OK) == 0; @@ -389,7 +388,7 @@ mac_resize(NSWindow *window){ } - (void)viewDidChangeBackingProperties{ - // NOTE(yuval): Screen scale factor calculation + // TODO(yuval): Screen scale factor calculation printf("Backing changed!\n"); mac_resize(mac_vars.window); } @@ -449,7 +448,8 @@ this only gets called for window creation and other extraordinary events. } //mac_gl_render(&target); - mac_metal_render(&target); + //mac_metal_render(&target); + renderer->render(renderer, &target); mac_vars.first = false; @@ -707,8 +707,9 @@ main(int arg_count, char **args){ [mac_vars.window makeKeyAndOrderFront:nil]; // NOTE(yuval): Initialize the renderer - mac_gl_init(mac_vars.window); - mac_metal_init(mac_vars.window); + //mac_gl_init(mac_vars.window); + //mac_metal_init(mac_vars.window, &target); + renderer = mac_init_renderer(MacRenderer_OpenGL, mac_vars.window, &target); mac_resize(w, h); diff --git a/platform_mac/mac_4ed_functions.mm b/platform_mac/mac_4ed_functions.mm index 11dac318..c1c37bae 100644 --- a/platform_mac/mac_4ed_functions.mm +++ b/platform_mac/mac_4ed_functions.mm @@ -804,13 +804,13 @@ system_get_keyboard_modifiers_sig(){ function graphics_get_texture_sig(){ - u32 result = mac_metal_get_texture(dim, texture_kind); + u32 result = renderer->get_texture(renderer, dim, texture_kind); return(result); } function graphics_fill_texture_sig(){ - b32 result = mac_metal_fill_texture(texture_kind, texture, p, dim, data); + b32 result = renderer->fill_texture(renderer, texture_kind, texture, p, dim, data); return(result); } diff --git a/platform_mac/mac_4ed_metal.mm b/platform_mac/mac_4ed_metal.mm index 063e618a..ba44930b 100644 --- a/platform_mac/mac_4ed_metal.mm +++ b/platform_mac/mac_4ed_metal.mm @@ -4,7 +4,7 @@ global Metal_Renderer *metal_renderer; global MTKView *metal_view; function void -mac_metal_init(NSWindow *window){ +mac_metal_init(NSWindow *window, Render_Target *target){ // NOTE(yuval): Create Metal view NSView *content_view = [window contentView]; @@ -26,11 +26,8 @@ mac_metal_init(NSWindow *window){ function void mac_metal_render(Render_Target* target){ - u64 begin_time = system_now_time(); metal_renderer.target = target; [metal_view draw]; - u64 end_time = system_now_time(); - printf("Metal Render Time: %fs\n\n", mac_get_time_diff_sec(begin_time, end_time)); } function u32 @@ -50,4 +47,4 @@ mac_metal_fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_ data:data]; return result; -} \ No newline at end of file +} diff --git a/platform_mac/mac_4ed_opengl.mm b/platform_mac/mac_4ed_opengl.mm index ba1f4dee..0a73c9c9 100644 --- a/platform_mac/mac_4ed_opengl.mm +++ b/platform_mac/mac_4ed_opengl.mm @@ -1,24 +1,38 @@ /* Mac OpenGL layer for 4coder */ +#include "mac_4ed_renderer.h" + +//////////////////////////////// +#include +#include + #include "opengl/4ed_opengl_defines.h" #define GL_FUNC(N,R,P) typedef R (CALL_CONVENTION N##_Function)P; N##_Function *N = 0; #include "mac_4ed_opengl_funcs.h" -f64 mac_get_time_diff_sec(u64 begin, u64 end){ - f64 result = ((end - begin) / 1000000.0); - return result; -} +//////////////////////////////// #include "opengl/4ed_opengl_render.cpp" -@interface OpenGLView : NSOpenGLView -- (void)initGL; +//////////////////////////////// + +@interface OpenGL_View : NSOpenGLView +- (void)init_gl; - (void)render:(Render_Target*)target; @end -@implementation OpenGLView{ - b32 glIsInitialized; +//////////////////////////////// + +struct Mac_OpenGL_Renderer{ + Mac_Renderer base; + OpenGL_View *opengl_view; +}; + +//////////////////////////////// + +@implementation OpenGL_View{ + b32 gl_is_initialized; } - (id)init{ @@ -27,8 +41,8 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){ return nil; } - glIsInitialized = false; - [self initGL]; + gl_is_initialized = false; + [self init_gl]; return self; } @@ -43,13 +57,13 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){ [[self openGLContext] makeCurrentContext]; // NOTE(yuval): Setup vsync - GLint swapInt = 1; - printf("Using vsync: %d\n", swapInt); - [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; + GLint swap_int = 1; + printf("Using vsync: %d\n", swap_int); + [[self openGLContext] setValues:&swap_int forParameter:NSOpenGLCPSwapInterval]; } - (void)awakeFromNib{ - [self initGL]; + [self init_gl]; } - (void)reshape{ @@ -59,8 +73,8 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){ [[self openGLContext] update]; } -- (void)initGL{ - if (glIsInitialized){ +- (void)init_gl{ + if (gl_is_initialized){ return; } @@ -92,65 +106,78 @@ f64 mac_get_time_diff_sec(u64 begin, u64 end){ [pixel_format release]; - glIsInitialized = true; + gl_is_initialized = true; } - (void)render:(Render_Target*)target{ - Assert(glIsInitialized); + Assert(gl_is_initialized); - u64 context_lock_begin = system_now_time(); CGLLockContext([[self openGLContext] CGLContextObj]); - u64 context_lock_end = system_now_time(); - printf("Context lock time: %fs\n", mac_get_time_diff_sec(context_lock_begin, context_lock_end)); - - u64 make_current_context_begin = system_now_time(); [[self openGLContext] makeCurrentContext]; - u64 make_current_context_end = system_now_time(); - printf("Make current context time: %fs\n", mac_get_time_diff_sec(make_current_context_begin, make_current_context_end)); - u64 gl_render_begin = system_now_time(); gl_render(target); - u64 gl_render_end = system_now_time(); - printf("GL render time: %fs\n", mac_get_time_diff_sec(gl_render_begin, gl_render_end)); - u64 gl_flush_buffer_begin = system_now_time(); [[self openGLContext] flushBuffer]; - u64 gl_flush_buffer_end = system_now_time(); - printf("GL flush buffer time: %fs\n", mac_get_time_diff_sec(gl_flush_buffer_begin, gl_flush_buffer_end)); - - u64 context_unlock_begin = system_now_time(); CGLUnlockContext([[self openGLContext] CGLContextObj]); - u64 context_unlock_end = system_now_time(); - printf("Context unlock time: %fs\n", mac_get_time_diff_sec(context_unlock_begin, context_unlock_end)); } @end -global OpenGLView *opengl_view; +//////////////////////////////// -function void -mac_gl_init(NSWindow *window){ - // NOTE(yuval): Create OpenGLView +function +mac_render_sig(mac_gl_render){ + printf("Rendering using OpenGL!\n"); + + Mac_OpenGL_Renderer *gl = (Mac_OpenGL_Renderer*)renderer; + [gl->opengl_view render:target]; +} + +function +mac_get_texture_sig(mac_gl_get_texture){ + u32 result = gl__get_texture(dim, texture_kind); + return(result); +} + +function +mac_fill_texture_sig(mac_gl_fill_texture){ + b32 result = gl__fill_texture(texture_kind, texture, p, dim, data); + return(result); +} + +function Mac_OpenGL_Renderer* +mac_gl__init(NSWindow *window, Render_Target *target){ + // NOTE(yuval): Create the Mac Renderer + Mac_OpenGL_Renderer *gl = (Mac_OpenGL_Renderer*)system_memory_allocate(sizeof(Mac_OpenGL_Renderer), + file_name_line_number_lit_u8); + gl->base.render = mac_gl_render; + gl->base.get_texture = mac_gl_get_texture; + gl->base.fill_texture = mac_gl_fill_texture; + + // NOTE(yuval): Create the OpenGL view NSView *content_view = [window contentView]; - opengl_view = [[OpenGLView alloc] init]; - [opengl_view setFrame:[content_view bounds]]; - [opengl_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [opengl_view setWantsBestResolutionOpenGLSurface:YES]; + gl->opengl_view = [[OpenGL_View alloc] init]; + [gl->opengl_view setFrame:[content_view bounds]]; + [gl->opengl_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [gl->opengl_view setWantsBestResolutionOpenGLSurface:YES]; // NOTE(yuval): Add the OpenGL view as a subview of the window - [content_view addSubview:opengl_view]; + [content_view addSubview:gl->opengl_view]; // NOTE(yuval): Load gl functions void *gl_image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); #define GL_FUNC(f,R,P) ((f) = (f##_Function*)dlsym(gl_image, #f)); #include "mac_4ed_opengl_funcs.h" + + return(gl); } -function void -mac_gl_render(Render_Target* target){ - u64 begin_time = system_now_time(); - [opengl_view render:target]; - u64 end_time = system_now_time(); - printf("Render Time: %fs\n\n", mac_get_time_diff_sec(begin_time, end_time)); -} \ No newline at end of file +// TODO(yuval): This function should be exported to a DLL +function +mac_load_renderer_sig(mac_load_opengl_renderer){ + printf("Initializing The OpenGL Renderer!\n"); + + Mac_Renderer *renderer = (Mac_Renderer*)mac_gl__init(window, target); + return(renderer); +} diff --git a/platform_mac/mac_4ed_renderer.h b/platform_mac/mac_4ed_renderer.h new file mode 100644 index 00000000..0d1d4caf --- /dev/null +++ b/platform_mac/mac_4ed_renderer.h @@ -0,0 +1,42 @@ +/* Mac Renderer Abstraction */ + +#if !defined(FRED_MAC_RENDERER_H) +#define FRED_MAC_RENDERER_H + +//////////////////////////////// + +// TODO(yuval): This should be refactored into a platform independent renderer + +struct Mac_Renderer; + +#define mac_render_sig(name) void name(Mac_Renderer *renderer, Render_Target *target) +typedef mac_render_sig(mac_render_type); + +#define mac_get_texture_sig(name) u32 name(Mac_Renderer *renderer, Vec3_i32 dim, Texture_Kind texture_kind) +typedef mac_get_texture_sig(mac_get_texture_type); + +#define mac_fill_texture_sig(name) b32 name(Mac_Renderer *renderer, Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 dim, void* data) +typedef mac_fill_texture_sig(mac_fill_texture_type); + +typedef i32 Mac_Renderer_Kind; +enum{ + MacRenderer_OpenGL, + MacRenderer_Metal +}; + +struct Mac_Renderer{ + mac_render_type *render; + + mac_get_texture_type *get_texture; + mac_fill_texture_type *fill_texture; +}; + +//////////////////////////////// + +// NOTE(yuval): This is the actual platform dependent function that each renderer implementation implements and should be exported into a DLL +#define mac_load_renderer_sig(name) Mac_Renderer* name(NSWindow *window, Render_Target *target) +typedef mac_load_renderer_sig(mac_load_renderer_type); + +//////////////////////////////// + +#endif \ No newline at end of file diff --git a/platform_mac/mac_4ed_renderer.mm b/platform_mac/mac_4ed_renderer.mm new file mode 100644 index 00000000..f1b18967 --- /dev/null +++ b/platform_mac/mac_4ed_renderer.mm @@ -0,0 +1,33 @@ +/* Mac Renderer Abstraction Implementation */ + +// TODO(yuval): This should NOT be included here once the renderer is exported to a DLL +#import "mac_4ed_opengl.mm" +#import "mac_4ed_metal.mm" + +function Mac_Renderer* +mac_init_renderer(Mac_Renderer_Kind kind, NSWindow *window, Render_Target *target){ + // TODO(yuval): Import renderer load function from a DLL instead of using a switch statement and a renderer kind. This would allow us to switch the renderer backend and implemented new backends with ease. + + Mac_Renderer *result = 0; + + switch (kind){ + case MacRenderer_OpenGL: + { + result = mac_load_opengl_renderer(window, target); + } break; + + case MacRenderer_Metal: + { + //result = mac_load_metal_renderer(window, target); + } break; + + default: InvalidPath; + } + + if (!result){ + mac_error_box("Unable to initialize the renderer!"); + } + + return result; +} +