This commit is contained in:
Carlos Aragones 2020-04-25 23:16:35 +02:00
parent 894e7cca5e
commit 4bd40299eb
8 changed files with 102 additions and 162 deletions

View File

@ -28,15 +28,16 @@ typedef struct {
uint32_t buffer_width; uint32_t buffer_width;
uint32_t buffer_height; uint32_t buffer_height;
uint32_t buffer_stride; uint32_t buffer_stride;
uint32_t mod_keys;
bool close;
bool is_active;
int32_t mouse_pos_x; int32_t mouse_pos_x;
int32_t mouse_pos_y; int32_t mouse_pos_y;
float mouse_wheel_x; float mouse_wheel_x;
float mouse_wheel_y; float mouse_wheel_y;
uint8_t mouse_button_status[8]; uint8_t mouse_button_status[8];
uint8_t key_status[512]; uint8_t key_status[512];
uint32_t mod_keys;
bool is_active;
bool close;
} SWindowData; } SWindowData;

View File

@ -15,72 +15,61 @@
void init_keycodes(); void init_keycodes();
//-------------------------------------
#if defined(USE_METAL_API) #if defined(USE_METAL_API)
id<MTLDevice> g_metal_device;
id<MTLLibrary> g_library;
Vertex gVertices[4] = { id<MTLDevice> g_metal_device = nil;
id<MTLLibrary> 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},
{ 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 = @ NSString *g_shader_src = kShader(
" #include <metal_stdlib>\n" "#include <metal_stdlib>\n",
"using namespace metal;\n" using namespace metal;
"struct VertexOutput {\n" //---------------------
"float4 pos [[position]];\n" struct VertexOutput {
"float2 texcoord;\n" float4 pos [[position]];
"};\n" float2 texcoord;
};
"vertex VertexOutput vertFunc(unsigned int vID[[vertex_id]])\n" struct Vertex {
"{\n" float4 position [[position]];
"VertexOutput out;\n" };
"out.pos.x = (float)(vID / 2) * 4.0 - 1.0;\n" //---------------------
"out.pos.y = (float)(vID % 2) * 4.0 - 1.0;\n" vertex VertexOutput
"out.pos.z = 0.0;\n" vertFunc(unsigned int vID[[vertex_id]], const device Vertex *pos [[ buffer(0) ]]) {
"out.pos.w = 1.0;\n" VertexOutput out;
"out.texcoord.x = (float)(vID / 2) * 2.0;\n" out.pos = pos[vID].position;
"out.texcoord.y = 1.0 - (float)(vID % 2) * 2.0;\n"
"return out;\n" out.texcoord.x = (float) (vID / 2);
"}\n" out.texcoord.y = 1.0 - (float) (vID % 2);
"struct Vertex\n" return out;
"{\n" }
"float4 position [[position]];\n"
"};\n"
"vertex VertexOutput vertFunc2(unsigned int vID[[vertex_id]], const device Vertex *pos [[buffer(0)]])\n" //---------------------
"{\n" fragment float4
"VertexOutput out;\n" fragFunc(VertexOutput input [[stage_in]], texture2d<half> colorTexture [[ texture(0) ]]) {
constexpr sampler textureSampler(mag_filter::nearest, min_filter::nearest);
"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<half> colorTexture [[ texture(0) ]])\n"
"{\n"
"constexpr sampler textureSampler(mag_filter::nearest, min_filter::nearest);\n"
// Sample the texture to obtain a color // 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 // We return the color of the texture
"return float4(colorSample);\n" return float4(colorSample);
//"return float4(input.texcoord.x, input.texcoord.y, 0.0, 1.0);\n" };
"}\n"; );
#endif #endif
@ -89,47 +78,39 @@ NSString* g_shadersSrc = @
#if defined(USE_METAL_API) #if defined(USE_METAL_API)
static bool static bool
create_shaders(SWindowData_OSX *window_data_osx) { create_shaders(SWindowData_OSX *window_data_osx) {
// Error NSError *error = 0x0;
NSError* nsError = 0x0;
NSError** nsErrorPtr = &nsError;
id<MTLLibrary> library = [g_metal_device newLibraryWithSource:g_shadersSrc id<MTLLibrary> g_library = [g_metal_device newLibraryWithSource:g_shader_src
options:[[MTLCompileOptions alloc] init] options:[[MTLCompileOptions alloc] init]
error:nsErrorPtr]; error:&error
];
// Error update if (error || !g_library) {
if (nsError || !library) { NSLog(@"Unable to create shaders %@", error);
NSLog(@"Unable to create shaders %@", nsError);
return false; return false;
} }
g_library = library; id<MTLFunction> vertex_shader_func = [g_library newFunctionWithName:@"vertFunc"];
NSLog(@"Names %@", [g_library functionNames]);
id<MTLFunction> vertex_shader_func = [g_library newFunctionWithName:@"vertFunc2"];
id<MTLFunction> fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"]; id<MTLFunction> fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"];
if (!vertex_shader_func) { if (!vertex_shader_func) {
printf("Unable to get vertFunc!\n"); NSLog(@"Unable to get vertFunc!\n");
return false; return false;
} }
if (!fragment_shader_func) { if (!fragment_shader_func) {
printf("Unable to get fragFunc!\n"); NSLog(@"Unable to get fragFunc!\n");
return false; return false;
} }
// Create a reusable pipeline state // Create a reusable pipeline state
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineStateDescriptor.label = @"MyPipeline"; pipelineStateDescriptor.label = @"MiniFB_pipeline";
pipelineStateDescriptor.vertexFunction = vertex_shader_func; pipelineStateDescriptor.vertexFunction = vertex_shader_func;
pipelineStateDescriptor.fragmentFunction = fragment_shader_func; pipelineStateDescriptor.fragmentFunction = fragment_shader_func;
pipelineStateDescriptor.colorAttachments[0].pixelFormat = 80; //bgra8Unorm; pipelineStateDescriptor.colorAttachments[0].pixelFormat = 80; //bgra8Unorm;
NSError *error = 0x0;
window_data_osx->metal.pipeline_state = [g_metal_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error]; 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); NSLog(@"Failed to created pipeline state, error %@", error);
} }
@ -140,16 +121,14 @@ create_shaders(SWindowData_OSX *window_data_osx) {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct mfb_window * 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); return mfb_open_ex(title, width, height, 0);
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct mfb_window * 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]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
init_keycodes(); init_keycodes();
@ -176,9 +155,8 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
#if defined(USE_METAL_API) #if defined(USE_METAL_API)
g_metal_device = MTLCreateSystemDefaultDevice(); g_metal_device = MTLCreateSystemDefaultDevice();
if (!g_metal_device) { if (!g_metal_device) {
printf("Your device/OS doesn't support Metal."); NSLog(@"Metal is not supported on this device");
return 0x0; return 0x0;
} }
@ -212,20 +190,17 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
WindowViewController* viewController = [WindowViewController new]; 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 // 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) // an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0)
textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm; MTLTextureDescriptor *td;
td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
// Set the pixel dimensions of the texture width:width
textureDescriptor.width = width; height:height
textureDescriptor.height = height; mipmapped:false];
// Create the texture from the device by using the descriptor // Create the texture from the device by using the descriptor
for (size_t i = 0; i < MaxBuffersInFlight; ++i) {
for (int i = 0; i < MaxBuffersInFlight; ++i) { viewController->m_texture_buffers[i] = [g_metal_device newTextureWithDescriptor:td];
viewController->m_texture_buffers[i] = [g_metal_device newTextureWithDescriptor:textureDescriptor];
} }
// Used for syncing the CPU and GPU // Used for syncing the CPU and GPU
@ -240,10 +215,6 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[window_data_osx->window.contentView addSubview:view]; [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]; //[window_data->window updateSize];
#endif #endif
@ -277,8 +248,7 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void static void
destroy_window_data(SWindowData *window_data) destroy_window_data(SWindowData *window_data) {
{
if(window_data == 0x0) if(window_data == 0x0)
return; return;
@ -304,8 +274,7 @@ destroy_window_data(SWindowData *window_data)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void static void
update_events(SWindowData *window_data) update_events(SWindowData *window_data) {
{
NSEvent* event; NSEvent* event;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@ -322,8 +291,7 @@ update_events(SWindowData *window_data)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
mfb_update_state mfb_update_state
mfb_update(struct mfb_window *window, void *buffer) mfb_update(struct mfb_window *window, void *buffer) {
{
if(window == 0x0) { if(window == 0x0) {
return STATE_INVALID_WINDOW; return STATE_INVALID_WINDOW;
} }
@ -356,8 +324,7 @@ mfb_update(struct mfb_window *window, void *buffer)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
mfb_update_state mfb_update_state
mfb_update_events(struct mfb_window *window) mfb_update_events(struct mfb_window *window) {
{
if(window == 0x0) { if(window == 0x0) {
return STATE_INVALID_WINDOW; return STATE_INVALID_WINDOW;
} }
@ -432,8 +399,7 @@ mfb_wait_sync(struct mfb_window *window) {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool 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; SWindowData *window_data = (SWindowData *) window;
if(offset_x + width > window_data->window_width) { if(offset_x + width > window_data->window_width) {
@ -454,17 +420,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 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; float y2 = (((float) offset_y + height) / window_data->window_height) * 2.0f - 1.0f;
gVertices[0].x = x1; g_vertices[0].x = x1;
gVertices[0].y = y1; g_vertices[0].y = y1;
gVertices[1].x = x1; g_vertices[1].x = x1;
gVertices[1].y = y2; g_vertices[1].y = y2;
gVertices[2].x = x2; g_vertices[2].x = x2;
gVertices[2].y = y1; g_vertices[2].y = y1;
gVertices[3].x = x2; g_vertices[3].x = x2;
gVertices[3].y = y2; g_vertices[3].y = y2;
#endif #endif
return true; return true;
@ -475,8 +441,7 @@ mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y
extern short int g_keycodes[512]; extern short int g_keycodes[512];
void void
init_keycodes() init_keycodes() {
{
// Clear keys // Clear keys
for (unsigned int i = 0; i < sizeof(g_keycodes) / sizeof(g_keycodes[0]); ++i) for (unsigned int i = 0; i < sizeof(g_keycodes) / sizeof(g_keycodes[0]); ++i)
g_keycodes[i] = 0; g_keycodes[i] = 0;

View File

@ -21,8 +21,7 @@ enum { MaxBuffersInFlight = 3 };
@public void *m_draw_buffer; @public void *m_draw_buffer;
@public int m_width; @public int m_width;
@public int m_height; @public int m_height;
// Used for syncing with CPU/GPU @public dispatch_semaphore_t m_semaphore; // Used for syncing with CPU/GPU
@public dispatch_semaphore_t m_semaphore;
} }
@end @end

View File

@ -9,19 +9,17 @@
extern id<MTLDevice> g_metal_device; extern id<MTLDevice> g_metal_device;
extern id<MTLLibrary> g_library; extern id<MTLLibrary> g_library;
extern Vertex gVertices[4]; extern Vertex g_vertices[4];
@implementation WindowViewController @implementation WindowViewController
- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size - (void) mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
{
(void)view; (void)view;
(void)size; (void)size;
// resize // resize
} }
- (void)drawInMTKView:(nonnull MTKView *)view - (void) drawInMTKView:(nonnull MTKView *)view {
{
OSXWindow *window = (OSXWindow *) view.window; OSXWindow *window = (OSXWindow *) view.window;
if(window->window_data == 0x0) { if(window->window_data == 0x0) {
return; return;
@ -39,8 +37,7 @@ extern Vertex gVertices[4];
MTLRegion region = { { 0, 0, 0 }, { m_width, m_height, 1 } }; MTLRegion region = { { 0, 0, 0 }, { m_width, m_height, 1 } };
// Copy the bytes from our data object into the texture // Copy the bytes from our data object into the texture
[m_texture_buffers[m_current_buffer] replaceRegion:region [m_texture_buffers[m_current_buffer] replaceRegion:region mipmapLevel:0 withBytes:m_draw_buffer bytesPerRow:bytesPerRow];
mipmapLevel:0 withBytes:m_draw_buffer bytesPerRow:bytesPerRow];
// Create a new command buffer for each render pass to the current drawable // Create a new command buffer for each render pass to the current drawable
SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific; SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific;
@ -60,14 +57,11 @@ extern Vertex gVertices[4];
}]; }];
MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor; MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;
if (renderPassDescriptor != nil) {
if (renderPassDescriptor != nil)
{
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0); renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
// Create a render command encoder so we can render into something // Create a render command encoder so we can render into something
id<MTLRenderCommandEncoder> renderEncoder = id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"minifb_command_encoder"; renderEncoder.label = @"minifb_command_encoder";
// Set render command encoder state // Set render command encoder state
@ -75,19 +69,12 @@ extern Vertex gVertices[4];
SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific; SWindowData_OSX *window_data_osx = (SWindowData_OSX *) window->window_data->specific;
[renderEncoder setRenderPipelineState:window_data_osx->metal.pipeline_state]; [renderEncoder setRenderPipelineState:window_data_osx->metal.pipeline_state];
[renderEncoder setVertexBytes:gVertices [renderEncoder setVertexBytes:g_vertices length:sizeof(g_vertices) atIndex:0];
length:sizeof(gVertices)
atIndex:0];
[renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0]; [renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0];
// Draw the vertices of our quads // Draw the vertices of our quads
// [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
// vertexStart:0
// vertexCount:3];
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
vertexStart:0
vertexCount:4];
// We're done encoding commands // We're done encoding commands
[renderEncoder endEncoding]; [renderEncoder endEncoding];
@ -107,6 +94,7 @@ extern Vertex gVertices[4];
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(USE_METAL_API) #if defined(USE_METAL_API)
- (void)updateTrackingAreas - (void)updateTrackingAreas
{ {
if(trackingArea != nil) { if(trackingArea != nil) {
@ -121,6 +109,7 @@ extern Vertex gVertices[4];
userInfo:nil]; userInfo:nil];
[self addTrackingArea:trackingArea]; [self addTrackingArea:trackingArea];
} }
#else #else
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -135,7 +124,8 @@ extern Vertex gVertices[4];
NSMaxX(contentViewRect) + contentViewPadding, NSMaxX(contentViewRect) + contentViewPadding,
NSMinY(contentViewRect) - resizeBoxSize - contentViewPadding, NSMinY(contentViewRect) - resizeBoxSize - contentViewPadding,
resizeBoxSize, resizeBoxSize,
resizeBoxSize); resizeBoxSize
);
return resizeRect; return resizeRect;
} }

View File

@ -59,9 +59,9 @@ destroy(SWindowData *window_data)
KILL(shell); KILL(shell);
KILL(surface); KILL(surface);
//KILL(buffer); //KILL(buffer);
if(window_data_way->draw_buffer) { if(window_data->draw_buffer) {
wl_buffer_destroy(window_data_way->draw_buffer); wl_buffer_destroy(window_data->draw_buffer);
window_data_way->draw_buffer = 0x0; window_data->draw_buffer = 0x0;
} }
KILL(shm_pool); KILL(shm_pool);
KILL(shm); KILL(shm);

View File

@ -40,19 +40,5 @@ typedef struct
uint32_t shm_format; uint32_t shm_format;
uint32_t *shm_ptr; 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; struct mfb_timer *timer;
bool close;
} SWindowData_Way; } SWindowData_Way;

View File

@ -17,5 +17,6 @@ typedef struct {
XImage *image_scaler; XImage *image_scaler;
uint32_t image_scaler_width; uint32_t image_scaler_width;
uint32_t image_scaler_height; uint32_t image_scaler_height;
struct mfb_timer *timer; struct mfb_timer *timer;
} SWindowData_X11; } SWindowData_X11;

View File

@ -11,16 +11,14 @@ static unsigned int g_buffer[WIDTH * HEIGHT];
int int
main() 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); struct mfb_window *window = mfb_open_ex("Noise Test", WIDTH, HEIGHT, WF_RESIZABLE);
if (!window) if (!window)
return 0; return 0;
do {
int i;
mfb_update_state state; mfb_update_state state;
do {
for (i = 0; i < WIDTH * HEIGHT; ++i) { for (i = 0; i < WIDTH * HEIGHT; ++i) {
noise = seed; noise = seed;
noise >>= 3; noise >>= 3;