diff --git a/src/WindowData.h b/src/WindowData.h index ce69fd2..983086d 100644 --- a/src/WindowData.h +++ b/src/WindowData.h @@ -28,15 +28,16 @@ typedef struct { uint32_t buffer_width; uint32_t buffer_height; uint32_t buffer_stride; - uint32_t mod_keys; - bool close; - - bool is_active; + int32_t mouse_pos_x; int32_t mouse_pos_y; float mouse_wheel_x; float mouse_wheel_y; uint8_t mouse_button_status[8]; uint8_t key_status[512]; - + uint32_t mod_keys; + + bool is_active; + + bool close; } SWindowData; diff --git a/src/macosx/MacMiniFB.m b/src/macosx/MacMiniFB.m index 1234554..59414a8 100644 --- a/src/macosx/MacMiniFB.m +++ b/src/macosx/MacMiniFB.m @@ -15,72 +15,61 @@ void init_keycodes(); +//------------------------------------- #if defined(USE_METAL_API) -id g_metal_device; -id g_library; -Vertex gVertices[4] = { +id g_metal_device = nil; +id g_library = nil; + +Vertex g_vertices[4] = { {-1.0, -1.0, 0, 1}, {-1.0, 1.0, 0, 1}, { 1.0, -1.0, 0, 1}, { 1.0, 1.0, 0, 1}, }; -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//------------------------------------- +#define kShader(inc, src) @inc#src -NSString* g_shadersSrc = @ -" #include \n" - "using namespace metal;\n" +NSString *g_shader_src = kShader( + "#include \n", + using namespace metal; - "struct VertexOutput {\n" - "float4 pos [[position]];\n" - "float2 texcoord;\n" - "};\n" + //--------------------- + struct VertexOutput { + float4 pos [[position]]; + float2 texcoord; + }; - "vertex VertexOutput vertFunc(unsigned int vID[[vertex_id]])\n" - "{\n" - "VertexOutput out;\n" + struct Vertex { + float4 position [[position]]; + }; - "out.pos.x = (float)(vID / 2) * 4.0 - 1.0;\n" - "out.pos.y = (float)(vID % 2) * 4.0 - 1.0;\n" - "out.pos.z = 0.0;\n" - "out.pos.w = 1.0;\n" + //--------------------- + vertex VertexOutput + vertFunc(unsigned int vID[[vertex_id]], const device Vertex *pos [[ buffer(0) ]]) { + VertexOutput out; - "out.texcoord.x = (float)(vID / 2) * 2.0;\n" - "out.texcoord.y = 1.0 - (float)(vID % 2) * 2.0;\n" + out.pos = pos[vID].position; - "return out;\n" - "}\n" + out.texcoord.x = (float) (vID / 2); + out.texcoord.y = 1.0 - (float) (vID % 2); - "struct Vertex\n" - "{\n" - "float4 position [[position]];\n" - "};\n" + return out; + } - "vertex VertexOutput vertFunc2(unsigned int vID[[vertex_id]], const device Vertex *pos [[buffer(0)]])\n" - "{\n" - "VertexOutput out;\n" - - "out.pos = pos[vID].position;\n" - - "out.texcoord.x = (float)(vID / 2);\n" - "out.texcoord.y = 1.0 - (float)(vID % 2);\n" - - "return out;\n" - "}\n" - - "fragment float4 fragFunc(VertexOutput input [[stage_in]],\n" - "texture2d colorTexture [[ texture(0) ]])\n" - "{\n" - "constexpr sampler textureSampler(mag_filter::nearest, min_filter::nearest);\n" + //--------------------- + fragment float4 + fragFunc(VertexOutput input [[stage_in]], texture2d colorTexture [[ texture(0) ]]) { + constexpr sampler textureSampler(mag_filter::nearest, min_filter::nearest); // Sample the texture to obtain a color - "const half4 colorSample = colorTexture.sample(textureSampler, input.texcoord);\n" + const half4 colorSample = colorTexture.sample(textureSampler, input.texcoord); // We return the color of the texture - "return float4(colorSample);\n" - //"return float4(input.texcoord.x, input.texcoord.y, 0.0, 1.0);\n" - "}\n"; + return float4(colorSample); + }; +); #endif @@ -89,47 +78,39 @@ NSString* g_shadersSrc = @ #if defined(USE_METAL_API) static bool create_shaders(SWindowData_OSX *window_data_osx) { - // Error - NSError* nsError = 0x0; - NSError** nsErrorPtr = &nsError; + NSError *error = 0x0; - id library = [g_metal_device newLibraryWithSource:g_shadersSrc - options:[[MTLCompileOptions alloc] init] - error:nsErrorPtr]; - - // Error update - if (nsError || !library) { - NSLog(@"Unable to create shaders %@", nsError); + id g_library = [g_metal_device newLibraryWithSource:g_shader_src + options:[[MTLCompileOptions alloc] init] + error:&error + ]; + if (error || !g_library) { + NSLog(@"Unable to create shaders %@", error); return false; - } + } - g_library = library; - NSLog(@"Names %@", [g_library functionNames]); - - id vertex_shader_func = [g_library newFunctionWithName:@"vertFunc2"]; + id vertex_shader_func = [g_library newFunctionWithName:@"vertFunc"]; id fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"]; if (!vertex_shader_func) { - printf("Unable to get vertFunc!\n"); + NSLog(@"Unable to get vertFunc!\n"); return false; } if (!fragment_shader_func) { - printf("Unable to get fragFunc!\n"); + NSLog(@"Unable to get fragFunc!\n"); return false; } // Create a reusable pipeline state MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; - pipelineStateDescriptor.label = @"MyPipeline"; + pipelineStateDescriptor.label = @"MiniFB_pipeline"; pipelineStateDescriptor.vertexFunction = vertex_shader_func; pipelineStateDescriptor.fragmentFunction = fragment_shader_func; pipelineStateDescriptor.colorAttachments[0].pixelFormat = 80; //bgra8Unorm; - NSError *error = 0x0; window_data_osx->metal.pipeline_state = [g_metal_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error]; - if (!window_data_osx->metal.pipeline_state) - { + if (!window_data_osx->metal.pipeline_state) { NSLog(@"Failed to created pipeline state, error %@", error); } @@ -140,16 +121,14 @@ create_shaders(SWindowData_OSX *window_data_osx) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct mfb_window * -mfb_open(const char *title, unsigned width, unsigned height) -{ +mfb_open(const char *title, unsigned width, unsigned height) { return mfb_open_ex(title, width, height, 0); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct mfb_window * -mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) -{ +mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; init_keycodes(); @@ -176,9 +155,8 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) #if defined(USE_METAL_API) g_metal_device = MTLCreateSystemDefaultDevice(); - if (!g_metal_device) { - printf("Your device/OS doesn't support Metal."); + NSLog(@"Metal is not supported on this device"); return 0x0; } @@ -212,27 +190,21 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) WindowViewController* viewController = [WindowViewController new]; - MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init]; - // Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is // an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0) - textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm; - - // Set the pixel dimensions of the texture - textureDescriptor.width = width; - textureDescriptor.height = height; + MTLTextureDescriptor *td; + td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm + width:width + height:height + mipmapped:false]; // Create the texture from the device by using the descriptor - - for (int i = 0; i < MaxBuffersInFlight; ++i) { - viewController->m_texture_buffers[i] = [g_metal_device newTextureWithDescriptor:textureDescriptor]; + for (size_t i = 0; i < MaxBuffersInFlight; ++i) { + viewController->texture_buffers[i] = [g_metal_device newTextureWithDescriptor:td]; } // Used for syncing the CPU and GPU - viewController->m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight); - viewController->m_draw_buffer = window_data->draw_buffer; - viewController->m_width = width; - viewController->m_height = height; + viewController->semaphore = dispatch_semaphore_create(MaxBuffersInFlight); MTKView* view = [[MTKView alloc] initWithFrame:rectangle]; view.device = g_metal_device; @@ -240,10 +212,6 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; [window_data_osx->window.contentView addSubview:view]; - //window_data->buffer_width = width; - //window_data->buffer_height = height; - //window_data->buffer_stride = width * 4; - //[window_data->window updateSize]; #endif @@ -277,8 +245,7 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void -destroy_window_data(SWindowData *window_data) -{ +destroy_window_data(SWindowData *window_data) { if(window_data == 0x0) return; @@ -304,8 +271,7 @@ destroy_window_data(SWindowData *window_data) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void -update_events(SWindowData *window_data) -{ +update_events(SWindowData *window_data) { NSEvent* event; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -322,8 +288,7 @@ update_events(SWindowData *window_data) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// mfb_update_state -mfb_update(struct mfb_window *window, void *buffer) -{ +mfb_update(struct mfb_window *window, void *buffer) { if(window == 0x0) { return STATE_INVALID_WINDOW; } @@ -356,8 +321,7 @@ mfb_update(struct mfb_window *window, void *buffer) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// mfb_update_state -mfb_update_events(struct mfb_window *window) -{ +mfb_update_events(struct mfb_window *window) { if(window == 0x0) { return STATE_INVALID_WINDOW; } @@ -432,8 +396,7 @@ mfb_wait_sync(struct mfb_window *window) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool -mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) -{ +mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) { SWindowData *window_data = (SWindowData *) window; if(offset_x + width > window_data->window_width) { @@ -454,17 +417,17 @@ mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y float y1 = ((float) offset_y / window_data->window_height) * 2.0f - 1.0f; float y2 = (((float) offset_y + height) / window_data->window_height) * 2.0f - 1.0f; - gVertices[0].x = x1; - gVertices[0].y = y1; + g_vertices[0].x = x1; + g_vertices[0].y = y1; - gVertices[1].x = x1; - gVertices[1].y = y2; + g_vertices[1].x = x1; + g_vertices[1].y = y2; - gVertices[2].x = x2; - gVertices[2].y = y1; + g_vertices[2].x = x2; + g_vertices[2].y = y1; - gVertices[3].x = x2; - gVertices[3].y = y2; + g_vertices[3].x = x2; + g_vertices[3].y = y2; #endif return true; @@ -475,8 +438,7 @@ mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y extern short int g_keycodes[512]; void -init_keycodes() -{ +init_keycodes() { // Clear keys for (unsigned int i = 0; i < sizeof(g_keycodes) / sizeof(g_keycodes[0]); ++i) g_keycodes[i] = 0; diff --git a/src/macosx/OSXWindow.h b/src/macosx/OSXWindow.h index 4dd0ba7..4f77ac7 100644 --- a/src/macosx/OSXWindow.h +++ b/src/macosx/OSXWindow.h @@ -1,6 +1,5 @@ #import #include -// @class OSXWindowFrameView; @interface OSXWindow : NSWindow { diff --git a/src/macosx/OSXWindowFrameView.h b/src/macosx/OSXWindowFrameView.h index d887b17..ad3b308 100644 --- a/src/macosx/OSXWindowFrameView.h +++ b/src/macosx/OSXWindowFrameView.h @@ -16,13 +16,9 @@ enum { MaxBuffersInFlight = 3 }; @interface WindowViewController : NSViewController { - @public id m_texture_buffers[MaxBuffersInFlight]; - @public int m_current_buffer; - @public void* m_draw_buffer; - @public int m_width; - @public int m_height; - // Used for syncing with CPU/GPU - @public dispatch_semaphore_t m_semaphore; + @public id texture_buffers[MaxBuffersInFlight]; + @public int current_buffer; + @public dispatch_semaphore_t semaphore; // Used for syncing with CPU/GPU } @end @@ -32,9 +28,9 @@ enum { MaxBuffersInFlight = 3 }; @interface OSXWindowFrameView : NSView { - @public SWindowData *window_data; + @public SWindowData *window_data; #if defined(USE_METAL_API) - @private NSTrackingArea* trackingArea; + @private NSTrackingArea *tracking_area; #endif } diff --git a/src/macosx/OSXWindowFrameView.m b/src/macosx/OSXWindowFrameView.m index 3c56d0d..8ad0020 100644 --- a/src/macosx/OSXWindowFrameView.m +++ b/src/macosx/OSXWindowFrameView.m @@ -9,38 +9,35 @@ extern id g_metal_device; extern id g_library; -extern Vertex gVertices[4]; +extern Vertex g_vertices[4]; @implementation WindowViewController -- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size -{ +- (void) mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { (void)view; (void)size; // resize } -- (void)drawInMTKView:(nonnull MTKView *)view -{ - OSXWindow *window = (OSXWindow *) view.window; - if(window->window_data == 0x0) { +- (void) drawInMTKView:(nonnull MTKView *)view { + OSXWindow *window = (OSXWindow *) view.window; + SWindowData *window_data = window->window_data; + if(window_data == 0x0) { return; } // Wait to ensure only MaxBuffersInFlight number of frames are getting proccessed // by any stage in the Metal pipeline (App, Metal, Drivers, GPU, etc) - dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER); + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // Iterate through our Metal buffers, and cycle back to the first when we've written to MaxBuffersInFlight - m_current_buffer = (m_current_buffer + 1) % MaxBuffersInFlight; + current_buffer = (current_buffer + 1) % MaxBuffersInFlight; // Calculate the number of bytes per row of our image. - NSUInteger bytesPerRow = 4 * m_width; - MTLRegion region = { { 0, 0, 0 }, { m_width, m_height, 1 } }; + MTLRegion region = { { 0, 0, 0 }, { window_data->buffer_width, window_data->buffer_height, 1 } }; // Copy the bytes from our data object into the texture - [m_texture_buffers[m_current_buffer] replaceRegion:region - mipmapLevel:0 withBytes:m_draw_buffer bytesPerRow:bytesPerRow]; + [texture_buffers[current_buffer] replaceRegion:region mipmapLevel:0 withBytes:window_data->draw_buffer bytesPerRow:window_data->buffer_stride]; // Create a new command buffer for each render pass to the current drawable SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific; @@ -52,7 +49,7 @@ extern Vertex gVertices[4]; // dynamic buffers filled with our vertices, that we're writing to this frame, will no longer // be needed by Metal and the GPU, meaning we can overwrite the buffer contents without // corrupting the rendering. - __block dispatch_semaphore_t block_sema = m_semaphore; + __block dispatch_semaphore_t block_sema = semaphore; [commandBuffer addCompletedHandler:^(id buffer) { (void)buffer; @@ -60,34 +57,24 @@ extern Vertex gVertices[4]; }]; MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor; - - if (renderPassDescriptor != nil) - { + if (renderPassDescriptor != nil) { renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0); // Create a render command encoder so we can render into something - id renderEncoder = - [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; renderEncoder.label = @"minifb_command_encoder"; // Set render command encoder state - OSXWindow *window = (OSXWindow *) view.window; + OSXWindow *window = (OSXWindow *) view.window; SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific; [renderEncoder setRenderPipelineState:window_data_osx->metal.pipeline_state]; - [renderEncoder setVertexBytes:gVertices - length:sizeof(gVertices) - atIndex:0]; + [renderEncoder setVertexBytes:g_vertices length:sizeof(g_vertices) atIndex:0]; - [renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0]; + [renderEncoder setFragmentTexture:texture_buffers[current_buffer] atIndex:0]; // Draw the vertices of our quads - // [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle - // vertexStart:0 - // vertexCount:3]; - [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip - vertexStart:0 - vertexCount:4]; + [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; // We're done encoding commands [renderEncoder endEncoding]; @@ -107,20 +94,22 @@ extern Vertex gVertices[4]; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #if defined(USE_METAL_API) + - (void)updateTrackingAreas { - if(trackingArea != nil) { - [self removeTrackingArea:trackingArea]; - [trackingArea release]; + if(tracking_area != nil) { + [self removeTrackingArea:tracking_area]; + [tracking_area release]; } int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways); - trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds] - options:opts - owner:self - userInfo:nil]; - [self addTrackingArea:trackingArea]; + tracking_area = [[NSTrackingArea alloc] initWithRect:[self bounds] + options:opts + owner:self + userInfo:nil]; + [self addTrackingArea:tracking_area]; } + #else /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -135,7 +124,8 @@ extern Vertex gVertices[4]; NSMaxX(contentViewRect) + contentViewPadding, NSMinY(contentViewRect) - resizeBoxSize - contentViewPadding, resizeBoxSize, - resizeBoxSize); + resizeBoxSize + ); return resizeRect; } diff --git a/src/macosx/WindowData_OSX.h b/src/macosx/WindowData_OSX.h index efd0dfb..ec8bd5f 100644 --- a/src/macosx/WindowData_OSX.h +++ b/src/macosx/WindowData_OSX.h @@ -4,7 +4,7 @@ #include #if defined(USE_METAL_API) -#include + #include #endif @class OSXWindow; @@ -14,9 +14,9 @@ typedef struct { struct mfb_timer *timer; #if defined(USE_METAL_API) - struct { - id command_queue; - id pipeline_state; - } metal; + struct { + id command_queue; + id pipeline_state; + } metal; #endif } SWindowData_OSX; diff --git a/src/wayland/WaylandMiniFB.c b/src/wayland/WaylandMiniFB.c index 71991f1..ade49b3 100644 --- a/src/wayland/WaylandMiniFB.c +++ b/src/wayland/WaylandMiniFB.c @@ -59,9 +59,9 @@ destroy(SWindowData *window_data) KILL(shell); KILL(surface); //KILL(buffer); - if(window_data_way->draw_buffer) { - wl_buffer_destroy(window_data_way->draw_buffer); - window_data_way->draw_buffer = 0x0; + if(window_data->draw_buffer) { + wl_buffer_destroy(window_data->draw_buffer); + window_data->draw_buffer = 0x0; } KILL(shm_pool); KILL(shm); diff --git a/src/wayland/WindowData_Way.h b/src/wayland/WindowData_Way.h index 81c337c..8b80342 100644 --- a/src/wayland/WindowData_Way.h +++ b/src/wayland/WindowData_Way.h @@ -40,19 +40,5 @@ typedef struct uint32_t shm_format; uint32_t *shm_ptr; - uint32_t window_width; - uint32_t window_height; - uint32_t dst_offset_x; - uint32_t dst_offset_y; - uint32_t dst_width; - uint32_t dst_height; - - struct wl_buffer *draw_buffer; - uint32_t buffer_width; - uint32_t buffer_height; - uint32_t buffer_stride; - - uint32_t mod_keys; struct mfb_timer *timer; - bool close; } SWindowData_Way; diff --git a/src/x11/WindowData_X11.h b/src/x11/WindowData_X11.h index 6826020..7e7d926 100644 --- a/src/x11/WindowData_X11.h +++ b/src/x11/WindowData_X11.h @@ -17,5 +17,6 @@ typedef struct { XImage *image_scaler; uint32_t image_scaler_width; uint32_t image_scaler_height; + struct mfb_timer *timer; } SWindowData_X11; diff --git a/tests/noise.c b/tests/noise.c index ff7d3fb..6556fdc 100644 --- a/tests/noise.c +++ b/tests/noise.c @@ -11,16 +11,14 @@ static unsigned int g_buffer[WIDTH * HEIGHT]; int main() { - int noise, carry, seed = 0xbeef; + int i, noise, carry, seed = 0xbeef; struct mfb_window *window = mfb_open_ex("Noise Test", WIDTH, HEIGHT, WF_RESIZABLE); if (!window) return 0; + mfb_update_state state; do { - int i; - mfb_update_state state; - for (i = 0; i < WIDTH * HEIGHT; ++i) { noise = seed; noise >>= 3;