re-working graphics surfaces
This commit is contained in:
parent
db5b4966e9
commit
9bf62d2218
|
@ -3,9 +3,10 @@
|
||||||
BINDIR=../../bin
|
BINDIR=../../bin
|
||||||
RESDIR=../../resources
|
RESDIR=../../resources
|
||||||
SRCDIR=../../src
|
SRCDIR=../../src
|
||||||
|
EXTDIR=../../ext
|
||||||
|
|
||||||
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||||
|
|
||||||
clang -g $FLAGS $LIBS $INCLUDES -o test main.c
|
clang -g $FLAGS -Wl,-dead_strip $LIBS $INCLUDES -o test main.c
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BINDIR=../../bin
|
||||||
|
RESDIR=../../resources
|
||||||
|
SRCDIR=../../src
|
||||||
|
|
||||||
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
|
LIBS="-L$BINDIR -lmilepost -framework Carbon -framework Cocoa -framework Metal -framework QuartzCore"
|
||||||
|
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG -Wl,-dead_strip"
|
||||||
|
|
||||||
|
xcrun -sdk macosx metal -c -o shader.air shader.metal
|
||||||
|
xcrun -sdk macosx metallib -o shader.metallib shader.air
|
||||||
|
|
||||||
|
clang -g $FLAGS $LIBS $INCLUDES -o test main.m
|
|
@ -0,0 +1,189 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: main.cpp
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 30/07/2022
|
||||||
|
* @revision:
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
|
||||||
|
#include<math.h>
|
||||||
|
|
||||||
|
#include"milepost.h"
|
||||||
|
#include"metal_surface.h"
|
||||||
|
|
||||||
|
#define LOG_SUBSYSTEM "Main"
|
||||||
|
|
||||||
|
#import<Metal/Metal.h>
|
||||||
|
#import<QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
|
#include"vertex.h"
|
||||||
|
|
||||||
|
static const my_vertex triangle[3] = {{{250, -250},{1, 0, 0, 1}},
|
||||||
|
{{-250, -250},{0, 1, 0, 1}},
|
||||||
|
{{0, 250},{0, 0, 1, 1}}};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
LogLevel(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
mp_init();
|
||||||
|
|
||||||
|
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600};
|
||||||
|
mp_window window = mp_window_create(rect, "test", 0);
|
||||||
|
|
||||||
|
//NOTE: create surface
|
||||||
|
mg_init();
|
||||||
|
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_METAL);
|
||||||
|
|
||||||
|
//NOTE(martin): load the library
|
||||||
|
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
|
||||||
|
|
||||||
|
const char* shaderPath = "shader.metallib";
|
||||||
|
NSString* metalFileName = [[NSString alloc] initWithCString: shaderPath encoding: NSUTF8StringEncoding];
|
||||||
|
NSError* err = 0;
|
||||||
|
id<MTLLibrary> library = [device newLibraryWithFile: metalFileName error:&err];
|
||||||
|
if(err != nil)
|
||||||
|
{
|
||||||
|
const char* errStr = [[err localizedDescription] UTF8String];
|
||||||
|
printf("error : %s\n", errStr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
id<MTLFunction> vertexFunction = [library newFunctionWithName:@"VertexShader"];
|
||||||
|
id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"FragmentShader"];
|
||||||
|
|
||||||
|
//NOTE(martin): create a render pipeline
|
||||||
|
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
|
pipelineStateDescriptor.label = @"My simple pipeline";
|
||||||
|
pipelineStateDescriptor.vertexFunction = vertexFunction;
|
||||||
|
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
|
||||||
|
|
||||||
|
CAMetalLayer* layer = mg_metal_surface_layer(surface);
|
||||||
|
pipelineStateDescriptor.colorAttachments[0].pixelFormat = layer.pixelFormat;
|
||||||
|
|
||||||
|
id<MTLRenderPipelineState> pipelineState = [device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err];
|
||||||
|
if(err != nil)
|
||||||
|
{
|
||||||
|
const char* errStr = [[err localizedDescription] UTF8String];
|
||||||
|
printf("error : %s\n", errStr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start app
|
||||||
|
|
||||||
|
mp_window_bring_to_front(window);
|
||||||
|
mp_window_focus(window);
|
||||||
|
|
||||||
|
while(!mp_should_quit())
|
||||||
|
{
|
||||||
|
mp_pump_events(0);
|
||||||
|
mp_event event = {0};
|
||||||
|
while(mp_next_event(&event))
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case MP_EVENT_WINDOW_CLOSE:
|
||||||
|
{
|
||||||
|
mp_request_quit();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_WINDOW_RESIZE:
|
||||||
|
{
|
||||||
|
printf("resized, rect = {%f, %f, %f, %f}\n",
|
||||||
|
event.frame.rect.x,
|
||||||
|
event.frame.rect.y,
|
||||||
|
event.frame.rect.w,
|
||||||
|
event.frame.rect.h);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_WINDOW_MOVE:
|
||||||
|
{
|
||||||
|
printf("moved, rect = {%f, %f, %f, %f}\n",
|
||||||
|
event.frame.rect.x,
|
||||||
|
event.frame.rect.y,
|
||||||
|
event.frame.rect.w,
|
||||||
|
event.frame.rect.h);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_MOUSE_MOVE:
|
||||||
|
{
|
||||||
|
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n",
|
||||||
|
event.move.x,
|
||||||
|
event.move.y,
|
||||||
|
event.move.deltaX,
|
||||||
|
event.move.deltaY);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_MOUSE_WHEEL:
|
||||||
|
{
|
||||||
|
printf("mouse wheel, delta = {%f, %f}\n",
|
||||||
|
event.move.deltaX,
|
||||||
|
event.move.deltaY);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_MOUSE_ENTER:
|
||||||
|
{
|
||||||
|
printf("mouse enter\n");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_MOUSE_LEAVE:
|
||||||
|
{
|
||||||
|
printf("mouse leave\n");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_MOUSE_BUTTON:
|
||||||
|
{
|
||||||
|
printf("mouse button %i: %i\n",
|
||||||
|
event.key.code,
|
||||||
|
event.key.action == MP_KEY_PRESS ? 1 : 0);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_KEYBOARD_KEY:
|
||||||
|
{
|
||||||
|
printf("key %i: %s\n",
|
||||||
|
event.key.code,
|
||||||
|
event.key.action == MP_KEY_PRESS ? "press" : (event.key.action == MP_KEY_RELEASE ? "release" : "repeat"));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MP_EVENT_KEYBOARD_CHAR:
|
||||||
|
{
|
||||||
|
printf("entered char %s\n", event.character.sequence);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_uint2 viewportSize;
|
||||||
|
viewportSize.x = 800;
|
||||||
|
viewportSize.y = 600;
|
||||||
|
|
||||||
|
mg_surface_prepare(surface);
|
||||||
|
id<CAMetalDrawable> drawable = mg_metal_surface_drawable(surface);
|
||||||
|
id<MTLCommandBuffer> commandBuffer = mg_metal_surface_command_buffer(surface);
|
||||||
|
|
||||||
|
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
|
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
|
||||||
|
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||||
|
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||||
|
|
||||||
|
//Set the pipeline state
|
||||||
|
[encoder setRenderPipelineState:pipelineState];
|
||||||
|
|
||||||
|
//Send data to the shader and add draw call
|
||||||
|
[encoder setVertexBytes: triangle length:sizeof(triangle) atIndex: vertexInputIndexVertices];
|
||||||
|
[encoder setVertexBytes: &viewportSize length:sizeof(viewportSize) atIndex: vertexInputIndexViewportSize];
|
||||||
|
[encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart: 0 vertexCount: 3];
|
||||||
|
[encoder endEncoding];
|
||||||
|
|
||||||
|
mg_surface_present(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_terminate();
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
#include<metal_stdlib>
|
||||||
|
#include<simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
#import "vertex.h"
|
||||||
|
|
||||||
|
typedef unsigned int uint;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float4 clipSpacePos [[position]];
|
||||||
|
float4 color;
|
||||||
|
|
||||||
|
} rasterizer_data;
|
||||||
|
|
||||||
|
vertex rasterizer_data VertexShader(uint vertexID [[vertex_id]],
|
||||||
|
constant my_vertex* vertices [[buffer(vertexInputIndexVertices)]],
|
||||||
|
constant vector_uint2* viewportSizePointer [[buffer(vertexInputIndexViewportSize)]])
|
||||||
|
{
|
||||||
|
float2 pixelPos = vertices[vertexID].pos.xy;
|
||||||
|
float2 viewportSize = vector_float2(*viewportSizePointer);
|
||||||
|
|
||||||
|
rasterizer_data out;
|
||||||
|
out.clipSpacePos = vector_float4(0, 0, 0, 1);
|
||||||
|
out.clipSpacePos.xy = pixelPos/(viewportSize/2);
|
||||||
|
out.color = vertices[vertexID].col;
|
||||||
|
|
||||||
|
return(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment float4 FragmentShader(rasterizer_data in [[stage_in]])
|
||||||
|
{
|
||||||
|
return(in.color);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
#ifndef __VERTEX_H__
|
||||||
|
#define __VERTEX_H__
|
||||||
|
|
||||||
|
#include<simd/simd.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
vector_float2 pos;
|
||||||
|
vector_float4 col;
|
||||||
|
} my_vertex;
|
||||||
|
|
||||||
|
typedef enum { vertexInputIndexVertices = 0,
|
||||||
|
vertexInputIndexViewportSize = 1 } vertexInputIndex;
|
||||||
|
|
||||||
|
|
||||||
|
#endif //__VERTEX_H__
|
|
@ -537,15 +537,13 @@ mg_image_data* mg_image_ptr_from_handle(mg_canvas_data* context, mg_image handle
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
#ifdef MG_IMPLEMENTS_BACKEND_METAL
|
#ifdef MG_IMPLEMENTS_BACKEND_METAL
|
||||||
//NOTE: function is defined in metal_backend.mm
|
#include"metal_surface.h"
|
||||||
mg_surface mg_metal_surface_create_for_window(mp_window window);
|
#endif
|
||||||
mg_surface mg_metal_surface_create_for_view(mp_view view);
|
|
||||||
#endif //MG_IMPLEMENTS_BACKEND_METAL
|
|
||||||
|
|
||||||
#ifdef MG_IMPLEMENTS_BACKEND_GLES
|
#ifdef MG_IMPLEMENTS_BACKEND_GLES
|
||||||
mg_surface mg_gles_surface_create_offscreen(u32 width, u32 height);
|
mg_surface mg_gles_surface_create_offscreen(u32 width, u32 height);
|
||||||
mg_surface_server mg_gles_surface_create_server(mg_surface_info* surface);
|
mg_surface_server mg_gles_surface_create_server(mg_surface_info* surface);
|
||||||
#endif //MG_IMPLEMENTS_BACKEND_GLES
|
#endif
|
||||||
|
|
||||||
#ifdef MG_IMPLEMENTS_BACKEND_GL
|
#ifdef MG_IMPLEMENTS_BACKEND_GL
|
||||||
mg_surface mg_gl_surface_create_for_window(mp_window window);
|
mg_surface mg_gl_surface_create_for_window(mp_window window);
|
||||||
|
@ -582,29 +580,6 @@ mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend)
|
||||||
return(surface);
|
return(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_surface mg_surface_create_for_view(mp_view view, mg_backend_id backend)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(__mgInfo.init);
|
|
||||||
|
|
||||||
mg_surface surface = mg_surface_nil();
|
|
||||||
|
|
||||||
switch(backend)
|
|
||||||
{
|
|
||||||
#ifdef MG_IMPLEMENTS_BACKEND_METAL
|
|
||||||
case MG_BACKEND_METAL:
|
|
||||||
surface = mg_metal_surface_create_for_view(view);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//...
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_surface mg_surface_create_offscreen(mg_backend_id backend, u32 width, u32 height)
|
mg_surface mg_surface_create_offscreen(mg_backend_id backend, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(__mgInfo.init);
|
DEBUG_ASSERT(__mgInfo.init);
|
||||||
|
@ -795,17 +770,6 @@ void mg_surface_client_destroy(mg_surface_client handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_surface_client_attach_to_view(mg_surface_client client, mp_view view)
|
|
||||||
{
|
|
||||||
mg_surface_client_info* clientInfo = mg_surface_client_ptr_from_handle(client);
|
|
||||||
|
|
||||||
if(clientInfo)
|
|
||||||
{
|
|
||||||
clientInfo->attachment = view;
|
|
||||||
clientInfo->attach(clientInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mg_surface_client_detach(mg_surface_client client)
|
void mg_surface_client_detach(mg_surface_client client)
|
||||||
{
|
{
|
||||||
mg_surface_client_info* clientInfo = mg_surface_client_ptr_from_handle(client);
|
mg_surface_client_info* clientInfo = mg_surface_client_ptr_from_handle(client);
|
||||||
|
|
|
@ -33,7 +33,6 @@ void mg_init();
|
||||||
mg_surface mg_surface_nil();
|
mg_surface mg_surface_nil();
|
||||||
bool mg_surface_is_nil(mg_surface surface);
|
bool mg_surface_is_nil(mg_surface surface);
|
||||||
mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend);
|
mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend);
|
||||||
mg_surface mg_surface_create_for_view(mp_view view, mg_backend_id backend);
|
|
||||||
mg_surface mg_surface_create_offscreen(mg_backend_id backend, u32 width, u32 height);
|
mg_surface mg_surface_create_offscreen(mg_backend_id backend, u32 width, u32 height);
|
||||||
|
|
||||||
void mg_surface_destroy(mg_surface surface);
|
void mg_surface_destroy(mg_surface surface);
|
||||||
|
@ -41,10 +40,13 @@ void* mg_surface_get_os_resource(mg_surface surface);
|
||||||
|
|
||||||
void mg_surface_prepare(mg_surface surface);
|
void mg_surface_prepare(mg_surface surface);
|
||||||
void mg_surface_present(mg_surface surface);
|
void mg_surface_present(mg_surface surface);
|
||||||
|
|
||||||
void mg_surface_resize(mg_surface surface, int width, int height);
|
void mg_surface_resize(mg_surface surface, int width, int height);
|
||||||
|
void mg_surface_set_frame(mg_surface surface, mp_rect frame);
|
||||||
void mg_surface_set_hidden(mg_surface surface, bool hidden);
|
void mg_surface_set_hidden(mg_surface surface, bool hidden);
|
||||||
|
|
||||||
vec2 mg_surface_size(mg_surface surface);
|
vec2 mg_surface_size(mg_surface surface);
|
||||||
|
mp_rect mg_surface_frame(mg_surface surface);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics surface sharing
|
//NOTE(martin): graphics surface sharing
|
||||||
|
@ -61,8 +63,6 @@ mg_surface_server_id mg_surface_server_get_id(mg_surface_server server);
|
||||||
|
|
||||||
mg_surface_client mg_surface_client_create(mg_surface_server_id id);
|
mg_surface_client mg_surface_client_create(mg_surface_server_id id);
|
||||||
void mg_surface_client_destroy(mg_surface_client client);
|
void mg_surface_client_destroy(mg_surface_client client);
|
||||||
void mg_surface_client_attach_to_view(mg_surface_client client, mp_view view);
|
|
||||||
void mg_surface_client_detach(mg_surface_client client);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): canvas drawing structs
|
//NOTE(martin): canvas drawing structs
|
||||||
|
|
|
@ -75,8 +75,6 @@ typedef struct mg_surface_client_info
|
||||||
mg_surface_client_attach_proc attach;
|
mg_surface_client_attach_proc attach;
|
||||||
mg_surface_client_detach_proc detach;
|
mg_surface_client_detach_proc detach;
|
||||||
|
|
||||||
mp_view attachment;
|
|
||||||
|
|
||||||
} mg_surface_client_info;
|
} mg_surface_client_info;
|
||||||
|
|
||||||
mg_surface_client mg_surface_client_alloc_handle(mg_surface_client_info* client);
|
mg_surface_client mg_surface_client_alloc_handle(mg_surface_client_info* client);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: metal_surface.h
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 25/12/2022
|
||||||
|
* @revision:
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
#ifndef __METAL_SURFACE_H_
|
||||||
|
#define __METAL_SURFACE_H_
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
#import<Metal/Metal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mg_surface mg_metal_surface_create_for_window(mp_window window);
|
||||||
|
void* mg_metal_surface_render_encoder(mg_surface surface);
|
||||||
|
void* mg_metal_surface_compute_encoder(mg_surface surface);
|
||||||
|
|
||||||
|
void* mg_metal_surface_layer(mg_surface surface);
|
||||||
|
void* mg_metal_surface_drawable(mg_surface surface);
|
||||||
|
void* mg_metal_surface_command_buffer(mg_surface surface);
|
||||||
|
|
||||||
|
#endif //__METAL_SURFACE_H_
|
|
@ -154,7 +154,6 @@ void mg_metal_surface_set_hidden(mg_surface_info* interface, bool hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vec2 mg_metal_surface_get_size(mg_surface_info* interface)
|
vec2 mg_metal_surface_get_size(mg_surface_info* interface)
|
||||||
{
|
{
|
||||||
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
mg_metal_surface* surface = (mg_metal_surface*)interface;
|
||||||
|
@ -175,10 +174,10 @@ void* mg_metal_surface_get_os_resource(mg_surface_info* interface)
|
||||||
|
|
||||||
static const f32 MG_METAL_SURFACE_CONTENTS_SCALING = 2;
|
static const f32 MG_METAL_SURFACE_CONTENTS_SCALING = 2;
|
||||||
|
|
||||||
mg_surface mg_metal_surface_create_for_view(mp_view view)
|
mg_surface mg_metal_surface_create_for_window(mp_window window)
|
||||||
{
|
{
|
||||||
mp_view_data* viewData = mp_view_ptr_from_handle(view);
|
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
||||||
if(!viewData)
|
if(!windowData)
|
||||||
{
|
{
|
||||||
return(mg_surface_nil());
|
return(mg_surface_nil());
|
||||||
}
|
}
|
||||||
|
@ -198,6 +197,12 @@ mg_surface mg_metal_surface_create_for_view(mp_view view)
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
|
||||||
|
surface->view = [[NSView alloc] initWithFrame: frame];
|
||||||
|
[surface->view setWantsLayer:YES];
|
||||||
|
|
||||||
|
[[windowData->osx.nsWindow contentView] addSubview: surface->view];
|
||||||
|
|
||||||
surface->drawableSemaphore = dispatch_semaphore_create(MP_METAL_MAX_DRAWABLES_IN_FLIGHT);
|
surface->drawableSemaphore = dispatch_semaphore_create(MP_METAL_MAX_DRAWABLES_IN_FLIGHT);
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
@ -211,8 +216,6 @@ mg_surface mg_metal_surface_create_for_view(mp_view view)
|
||||||
|
|
||||||
surface->metalLayer.device = surface->device;
|
surface->metalLayer.device = surface->device;
|
||||||
|
|
||||||
surface->view = viewData->nsView;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
//NOTE(martin): set the size and scaling
|
//NOTE(martin): set the size and scaling
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
@ -244,23 +247,51 @@ mg_surface mg_metal_surface_create_for_view(mp_view view)
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_surface handle = mg_surface_alloc_handle((mg_surface_info*)surface);
|
mg_surface handle = mg_surface_alloc_handle((mg_surface_info*)surface);
|
||||||
viewData->surface = handle;
|
|
||||||
|
|
||||||
return(handle);
|
return(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_surface mg_metal_surface_create_for_window(mp_window window)
|
void* mg_metal_surface_layer(mg_surface surface)
|
||||||
{
|
{
|
||||||
mp_window_data* windowData = mp_window_ptr_from_handle(window);
|
mg_surface_info* surfaceData = mg_surface_ptr_from_handle(surface);
|
||||||
if(!windowData)
|
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||||
{
|
{
|
||||||
return(mg_surface_nil());
|
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||||
|
return(metalSurface->metalLayer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return(mg_metal_surface_create_for_view(windowData->osx.mainView));
|
return(nil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mg_metal_surface_drawable(mg_surface surface)
|
||||||
|
{
|
||||||
|
mg_surface_info* surfaceData = mg_surface_ptr_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||||
|
{
|
||||||
|
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||||
|
return(metalSurface->drawable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(nil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mg_metal_surface_command_buffer(mg_surface surface)
|
||||||
|
{
|
||||||
|
mg_surface_info* surfaceData = mg_surface_ptr_from_handle(surface);
|
||||||
|
if(surfaceData && surfaceData->backend == MG_BACKEND_METAL)
|
||||||
|
{
|
||||||
|
mg_metal_surface* metalSurface = (mg_metal_surface*)surfaceData;
|
||||||
|
return(metalSurface->commandBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(nil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#undef LOG_SUBSYSTEM
|
#undef LOG_SUBSYSTEM
|
||||||
|
|
|
@ -16,4 +16,4 @@
|
||||||
#include"osx_gles_surface.m"
|
#include"osx_gles_surface.m"
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
#include"osx_surface_client.m"
|
//#include"osx_surface_client.m"
|
||||||
|
|
11
src/mp_app.h
11
src/mp_app.h
|
@ -22,7 +22,6 @@ extern "C" {
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct mp_window { u64 h; } mp_window;
|
typedef struct mp_window { u64 h; } mp_window;
|
||||||
typedef struct mp_view { u64 h; } mp_view;
|
|
||||||
|
|
||||||
typedef enum { MP_MOUSE_CURSOR_ARROW,
|
typedef enum { MP_MOUSE_CURSOR_ARROW,
|
||||||
MP_MOUSE_CURSOR_RESIZE_0,
|
MP_MOUSE_CURSOR_RESIZE_0,
|
||||||
|
@ -320,16 +319,6 @@ void mp_window_center(mp_window window);
|
||||||
mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
|
mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
|
||||||
mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
|
mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
// View management
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
|
|
||||||
mp_view mp_view_nil();
|
|
||||||
bool mp_view_is_nil(mp_view view);
|
|
||||||
mp_view mp_view_create(mp_window window, mp_rect frame);
|
|
||||||
void mp_view_destroy(mp_view view);
|
|
||||||
void mp_view_set_frame(mp_view view, mp_rect frame);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Input state polling
|
// Input state polling
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
|
@ -30,22 +30,10 @@ typedef struct osx_window_data
|
||||||
NSView* nsView;
|
NSView* nsView;
|
||||||
NSObject* nsWindowDelegate;
|
NSObject* nsWindowDelegate;
|
||||||
|
|
||||||
mp_view mainView;
|
|
||||||
|
|
||||||
} osx_window_data;
|
} osx_window_data;
|
||||||
|
|
||||||
#define MP_PLATFORM_WINDOW_DATA osx_window_data osx;
|
#define MP_PLATFORM_WINDOW_DATA osx_window_data osx;
|
||||||
|
|
||||||
typedef struct mp_view_data
|
|
||||||
{
|
|
||||||
list_elt freeListElt;
|
|
||||||
u32 generation;
|
|
||||||
|
|
||||||
mp_window window;
|
|
||||||
NSView* nsView;
|
|
||||||
mg_surface surface;
|
|
||||||
} mp_view_data;
|
|
||||||
|
|
||||||
const u32 MP_APP_MAX_VIEWS = 128;
|
const u32 MP_APP_MAX_VIEWS = 128;
|
||||||
|
|
||||||
typedef struct osx_app_data
|
typedef struct osx_app_data
|
||||||
|
@ -57,9 +45,6 @@ typedef struct osx_app_data
|
||||||
void* kbLayoutUnicodeData;
|
void* kbLayoutUnicodeData;
|
||||||
id kbLayoutListener;
|
id kbLayoutListener;
|
||||||
|
|
||||||
list_info viewFreeList;
|
|
||||||
mp_view_data viewPool[MP_APP_MAX_VIEWS];
|
|
||||||
|
|
||||||
} osx_app_data;
|
} osx_app_data;
|
||||||
|
|
||||||
#define MP_PLATFORM_APP_DATA osx_app_data osx;
|
#define MP_PLATFORM_APP_DATA osx_app_data osx;
|
||||||
|
|
|
@ -90,64 +90,6 @@ static u32 mp_osx_get_window_style_mask(mp_window_style style)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// App struct and utility functions
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void mp_init_view_handles()
|
|
||||||
{
|
|
||||||
ListInit(&__mpApp.osx.viewFreeList);
|
|
||||||
for(int i=0; i<MP_APP_MAX_VIEWS; i++)
|
|
||||||
{
|
|
||||||
__mpApp.osx.viewPool[i].generation = 1;
|
|
||||||
ListAppend(&__mpApp.osx.viewFreeList, &__mpApp.osx.viewPool[i].freeListElt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mp_view_data* mp_view_alloc()
|
|
||||||
{
|
|
||||||
return(ListPopEntry(&__mpApp.osx.viewFreeList, mp_view_data, freeListElt));
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_view_data* mp_view_ptr_from_handle(mp_view handle)
|
|
||||||
{
|
|
||||||
u32 index = handle.h>>32;
|
|
||||||
u32 generation = handle.h & 0xffffffff;
|
|
||||||
if(index >= MP_APP_MAX_VIEWS)
|
|
||||||
{
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
mp_view_data* view = &__mpApp.osx.viewPool[index];
|
|
||||||
if(view->generation != generation)
|
|
||||||
{
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return(view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_view mp_view_handle_from_ptr(mp_view_data* view)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT( (view - __mpApp.osx.viewPool) >= 0
|
|
||||||
&& (view - __mpApp.osx.viewPool) < MP_APP_MAX_VIEWS);
|
|
||||||
|
|
||||||
u64 h = ((u64)(view - __mpApp.osx.viewPool))<<32
|
|
||||||
| ((u64)view->generation);
|
|
||||||
|
|
||||||
return((mp_view){h});
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp_view_recycle_ptr(mp_view_data* view)
|
|
||||||
{
|
|
||||||
view->generation++;
|
|
||||||
ListPush(&__mpApp.osx.viewFreeList, &view->freeListElt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
static void mp_init_osx_keys()
|
static void mp_init_osx_keys()
|
||||||
{
|
{
|
||||||
|
@ -719,10 +661,6 @@ static void mp_update_key_mods(mp_key_mods mods)
|
||||||
event.frame.rect.w = contentRect.size.width;
|
event.frame.rect.w = contentRect.size.width;
|
||||||
event.frame.rect.h = contentRect.size.height;
|
event.frame.rect.h = contentRect.size.height;
|
||||||
|
|
||||||
mp_rect viewFrame = {0, 0, contentRect.size.width, contentRect.size.height};
|
|
||||||
mp_view_set_frame(mpWindow->osx.mainView, viewFrame);
|
|
||||||
|
|
||||||
|
|
||||||
if(__mpApp.liveResizeCallback)
|
if(__mpApp.liveResizeCallback)
|
||||||
{
|
{
|
||||||
__mpApp.liveResizeCallback(event, __mpApp.liveResizeData);
|
__mpApp.liveResizeCallback(event, __mpApp.liveResizeData);
|
||||||
|
@ -1269,7 +1207,6 @@ void mp_init()
|
||||||
|
|
||||||
LOG_MESSAGE("init handles\n");
|
LOG_MESSAGE("init handles\n");
|
||||||
mp_init_window_handles();
|
mp_init_window_handles();
|
||||||
mp_init_view_handles();
|
|
||||||
|
|
||||||
LOG_MESSAGE("init event queue\n");
|
LOG_MESSAGE("init event queue\n");
|
||||||
ringbuffer_init(&__mpApp.eventQueue, 16);
|
ringbuffer_init(&__mpApp.eventQueue, 16);
|
||||||
|
@ -1508,9 +1445,6 @@ mp_window mp_window_create(mp_rect contentRect, const char* title, mp_window_sty
|
||||||
|
|
||||||
mp_window windowHandle = mp_window_handle_from_ptr(window);
|
mp_window windowHandle = mp_window_handle_from_ptr(window);
|
||||||
|
|
||||||
mp_rect mainViewFrame = {0, 0, contentRect.w, contentRect.h};
|
|
||||||
window->osx.mainView = mp_view_create(windowHandle, mainViewFrame);
|
|
||||||
|
|
||||||
return(windowHandle);
|
return(windowHandle);
|
||||||
}//autoreleasepool
|
}//autoreleasepool
|
||||||
}
|
}
|
||||||
|
@ -1780,17 +1714,7 @@ void mp_window_set_content_size(mp_window window, int width, int height)
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// view management
|
// view management
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
/*
|
||||||
mp_view mp_view_nil()
|
|
||||||
{
|
|
||||||
return((mp_view){0});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mp_view_is_nil(mp_view view)
|
|
||||||
{
|
|
||||||
return(!view.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_view mp_view_create(mp_window windowHandle, mp_rect frame)
|
mp_view mp_view_create(mp_window windowHandle, mp_rect frame)
|
||||||
{@autoreleasepool{
|
{@autoreleasepool{
|
||||||
mp_window_data* window = mp_window_ptr_from_handle(windowHandle);
|
mp_window_data* window = mp_window_ptr_from_handle(windowHandle);
|
||||||
|
@ -1853,7 +1777,7 @@ void mp_view_set_frame(mp_view viewHandle, mp_rect frame)
|
||||||
mg_surface_resize(view->surface, frame.w, frame.h);
|
mg_surface_resize(view->surface, frame.w, frame.h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Main loop throttle
|
// Main loop throttle
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
53
todo.txt
53
todo.txt
|
@ -19,23 +19,62 @@ Windows port
|
||||||
(mp_app.c can 'see' platform specific stuff, so ObjectiveC defs pose a problem, but we can define id as void*
|
(mp_app.c can 'see' platform specific stuff, so ObjectiveC defs pose a problem, but we can define id as void*
|
||||||
when not in ObjC...)
|
when not in ObjC...)
|
||||||
|
|
||||||
[ ] Check changes in macos version
|
[.] Check changes in macos version
|
||||||
[x] Restructure macos version to use mp_app_internal.h/mp_app.c
|
[x] Restructure macos version to use mp_app_internal.h/mp_app.c
|
||||||
[x] test new run loop structure on macos
|
[x] test new run loop structure on macos
|
||||||
[x] Fix resize crash when there's no surface
|
[x] Fix resize crash when there's no surface
|
||||||
[ ] separate data for key and mouse event?
|
[>] separate data for key and mouse event?
|
||||||
[ ] Clarify how we want to do view handling across platforms
|
[>] Simplify event structs
|
||||||
[ ] Views (using docked windows?) -- or see if we can use surfaces and restrict their location?
|
|
||||||
[ ] pull views in common stuff
|
|
||||||
[ ] use isARepeat in macos keyDown event and simplify update key state
|
[ ] use isARepeat in macos keyDown event and simplify update key state
|
||||||
|
|
||||||
[ ] Simplify event structs
|
[>] Clarify how we want to do view handling across platforms
|
||||||
|
[.] use surfaces to define restricted drawing locations
|
||||||
|
[x] Implement with NSView subviews on osx
|
||||||
|
[/] Maybe switch to just using CALayers?
|
||||||
|
[ ] Clarify metal-specific surface API
|
||||||
|
> right now mg_surface doesn't really give access to directly drawing in metal
|
||||||
|
we only need render encoder from the surface? -> if we just want to issue draw calls.
|
||||||
|
We'll likely need the command buffer if we want other passes? or also have get_compute_encoder().
|
||||||
|
We only need the command buffer/command queue if we want to manually create encoders, eg with different clear color
|
||||||
|
|
||||||
|
-> get pixel format / command buffer / texture
|
||||||
|
(don't get drawable as it is specific to the kind of target (window or image))
|
||||||
|
-> as helper, get simple encoders in the command buffer
|
||||||
|
|
||||||
|
maybe even _just_ get a CAMetalDrawable and pixel format, and let user code create commandQueue, buffers, encoders...
|
||||||
|
-> but we need to present the drawable to a specific commandbuffer
|
||||||
|
-> so, maybe the view should also maintain a command buffer
|
||||||
|
-> pixel format, drawable, command buffer, + helpers for encoders(passes)
|
||||||
|
|
||||||
|
--> but then, mg_surface doesn't really abstract anything (usage code needs to know which kind of surface it is to be able to draw inside it)
|
||||||
|
(well, it abstracts the creation of the context and the presentation...)
|
||||||
|
|
||||||
|
maybe we should actually abstract over that, a la sokol_gfx... And then the 2D vector graphics uses this abstract API?
|
||||||
|
-> but this is a bigger endeavour
|
||||||
|
|
||||||
|
Maybe keep surface simple, write an opengl version, then try to port painter to opengl version,
|
||||||
|
and then we will have more info to decide if we want to abstract over the different APIs.
|
||||||
|
|
||||||
|
Do surfaces for different graphics API even need to be abstracted? don't we always know which surface we're using?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
->> how much do we abstract graphics API vs how much we give access to native calls...
|
||||||
|
|
||||||
|
ie we could abstract shaders, buffers, textures, pipeline, encoders, etc... but also provide access to native data structures
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ ] Cleanup graphics backend compile-time/runtime selection
|
||||||
|
[ ] Implement surfaces with child windows on win32
|
||||||
|
[/] Maybe implement compositing directly in d3d and opengl compat extension...
|
||||||
|
|
||||||
[.] Implement input polling
|
[.] Implement input polling
|
||||||
[ ] Simplify input polling API names
|
[ ] Simplify input polling API names
|
||||||
[/] Try to simplify input state and polling once we have UI usage code
|
[/] Try to simplify input state and polling once we have UI usage code
|
||||||
|
|
||||||
[ ] Finish window properties query/setting
|
[ ] Finish win32 window create flags and properties query/setting
|
||||||
|
|
||||||
[ ] Implement clipboard
|
[ ] Implement clipboard
|
||||||
[ ] Implement file dialogs
|
[ ] Implement file dialogs
|
||||||
|
|
Loading…
Reference in New Issue