test 1
This commit is contained in:
parent
4bd40299eb
commit
8e1a981085
@ -5,6 +5,12 @@ project(${PROJECT_NAME})
|
||||
|
||||
message("Processing " ${PROJECT_NAME})
|
||||
|
||||
if(NOT DEFINED IOS)
|
||||
if(TOLOWER CMAKE_SYSTEM_NAME STREQUAL "ios")
|
||||
set(IOS true)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SrcLib
|
||||
include/MiniFB.h
|
||||
include/MiniFB_cpp.h
|
||||
@ -32,6 +38,16 @@ set(SrcMacOSX
|
||||
src/macosx/WindowData_OSX.h
|
||||
)
|
||||
|
||||
set(SrcIOS
|
||||
src/ios/WindowData_IOS.h
|
||||
src/ios/iOSMiniFB.m
|
||||
src/ios/iOSViewController.h
|
||||
src/ios/iOSViewController.m
|
||||
src/ios/iOSViewDelegate.h
|
||||
src/ios/iOSViewDelegate.m
|
||||
include/MiniFB_ios.h
|
||||
)
|
||||
|
||||
set(SrcWayland
|
||||
src/wayland/WaylandMiniFB.c
|
||||
src/wayland/WindowData_Way.h
|
||||
@ -93,7 +109,7 @@ endif()
|
||||
|
||||
# Set default cmake flags
|
||||
#--------------------------------------
|
||||
if (APPLE)
|
||||
if (APPLE AND NOT IOS)
|
||||
OPTION(USE_METAL_API "Build the project using metal API code" ON)
|
||||
elseif (UNIX)
|
||||
OPTION(USE_WAYLAND_API "Build the project using wayland API code" OFF)
|
||||
@ -110,6 +126,8 @@ elseif (MINGW)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
|
||||
list(APPEND SrcLib ${SrcWindows})
|
||||
elseif (IOS)
|
||||
list(APPEND SrcLib ${SrcIOS})
|
||||
elseif (APPLE)
|
||||
if(USE_METAL_API)
|
||||
add_definitions(-DUSE_METAL_API)
|
||||
@ -142,10 +160,13 @@ add_library(minifb STATIC
|
||||
|
||||
#--------------------------------------
|
||||
if (APPLE)
|
||||
if(IOS)
|
||||
else()
|
||||
target_link_libraries(minifb "-framework Cocoa")
|
||||
target_link_libraries(minifb "-framework QuartzCore")
|
||||
target_link_libraries(minifb "-framework Metal")
|
||||
target_link_libraries(minifb "-framework MetalKit")
|
||||
endif()
|
||||
elseif (UNIX)
|
||||
if(USE_WAYLAND_API)
|
||||
target_link_libraries(minifb "-lwayland-client")
|
||||
@ -164,6 +185,7 @@ link_libraries(minifb)
|
||||
|
||||
# Examples
|
||||
#--------------------------------------
|
||||
if(NOT IOS)
|
||||
add_executable(noise
|
||||
tests/noise.c
|
||||
)
|
||||
@ -179,5 +201,23 @@ add_executable(input_events_cpp
|
||||
add_executable(multiple_windows
|
||||
tests/multiple_windows.c
|
||||
)
|
||||
else()
|
||||
add_executable(noise
|
||||
tests/ios/main.m
|
||||
tests/ios/AppDelegate.h
|
||||
tests/ios/AppDelegate.m
|
||||
)
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Set CMake deployment target" ${FORCE_CACHE})
|
||||
|
||||
target_include_directories(minifb PRIVATE src)
|
||||
|
||||
add_definitions(-DTVOS_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||
|
||||
target_include_directories(noise PRIVATE src/ios)
|
||||
|
||||
target_link_libraries(noise "-framework UIKit")
|
||||
target_link_libraries(noise "-framework Metal")
|
||||
endif()
|
||||
|
||||
message("Done " ${PROJECT_NAME})
|
||||
|
7
include/MiniFB_ios.h
Normal file
7
include/MiniFB_ios.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <MiniFB_enums.h>
|
||||
|
||||
void user_implemented_init(struct mfb_window *window);
|
||||
|
||||
void user_implemented_update(struct mfb_window *window);
|
15
src/ios/WindowData_IOS.h
Normal file
15
src/ios/WindowData_IOS.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <MiniFB_enums.h>
|
||||
#include <WindowData.h>
|
||||
|
||||
#include <MetalKit/MetalKit.h>
|
||||
|
||||
typedef struct Vertex {
|
||||
float x, y, z, w;
|
||||
} Vertex;
|
||||
|
||||
typedef struct {
|
||||
id<MTLCommandQueue> command_queue;
|
||||
id<MTLRenderPipelineState> pipeline_state;
|
||||
} SWindowData_IOS;
|
170
src/ios/iOSMiniFB.m
Normal file
170
src/ios/iOSMiniFB.m
Normal file
@ -0,0 +1,170 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <MiniFB.h>
|
||||
#include "MiniFB_internal.h"
|
||||
#include "WindowData.h"
|
||||
#include "WindowData_IOS.h"
|
||||
|
||||
//-------------------------------------
|
||||
struct mfb_window *
|
||||
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) {
|
||||
kUnused(title);
|
||||
kUnused(flags);
|
||||
SWindowData *window_data;
|
||||
|
||||
window_data = malloc(sizeof(SWindowData));
|
||||
memset(window_data, 0, sizeof(SWindowData));
|
||||
|
||||
SWindowData_IOS *window_data_ios = malloc(sizeof(SWindowData_IOS));
|
||||
memset((void *) window_data_ios, 0, sizeof(SWindowData_IOS));
|
||||
window_data->specific = window_data_ios;
|
||||
|
||||
window_data->window_width = width;
|
||||
window_data->window_height = height;
|
||||
|
||||
window_data->dst_width = width;
|
||||
window_data->dst_height = height;
|
||||
|
||||
window_data->buffer_width = width;
|
||||
window_data->buffer_height = height;
|
||||
window_data->buffer_stride = width * 4;
|
||||
|
||||
window_data->draw_buffer = malloc(width * height * 4);
|
||||
if (!window_data->draw_buffer) {
|
||||
NSLog(@"Unable to create draw buffer");
|
||||
}
|
||||
|
||||
return (struct mfb_window *) window_data;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
static void
|
||||
destroy_window_data(SWindowData *window_data) {
|
||||
if(window_data == 0x0)
|
||||
return;
|
||||
|
||||
@autoreleasepool {
|
||||
SWindowData_IOS *window_data_ios = (SWindowData_IOS *) window_data->specific;
|
||||
if(window_data_ios != 0x0) {
|
||||
memset((void *) window_data_ios, 0, sizeof(SWindowData_IOS));
|
||||
free(window_data_ios);
|
||||
}
|
||||
memset(window_data, 0, sizeof(SWindowData));
|
||||
free(window_data);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
mfb_update_state
|
||||
mfb_update(struct mfb_window *window, void *buffer) {
|
||||
if(window == 0x0) {
|
||||
return STATE_INVALID_WINDOW;
|
||||
}
|
||||
|
||||
SWindowData *window_data = (SWindowData *) window;
|
||||
if(window_data->close) {
|
||||
destroy_window_data(window_data);
|
||||
return STATE_EXIT;
|
||||
}
|
||||
|
||||
if(buffer == 0x0) {
|
||||
return STATE_INVALID_BUFFER;
|
||||
}
|
||||
|
||||
memcpy(window_data->draw_buffer, buffer, window_data->buffer_width * window_data->buffer_height * 4);
|
||||
|
||||
return STATE_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
mfb_update_state
|
||||
mfb_update_events(struct mfb_window *window) {
|
||||
return STATE_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
extern double g_time_for_frame;
|
||||
|
||||
bool
|
||||
mfb_wait_sync(struct mfb_window *window) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extern Vertex g_vertices[4];
|
||||
|
||||
//-------------------------------------
|
||||
bool
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
if(offset_y + height > window_data->window_height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
window_data->dst_offset_x = offset_x;
|
||||
window_data->dst_offset_y = offset_y;
|
||||
window_data->dst_width = width;
|
||||
window_data->dst_height = height;
|
||||
|
||||
float x1 = ((float) offset_x / window_data->window_width) * 2.0f - 1.0f;
|
||||
float x2 = (((float) offset_x + width) / window_data->window_width) * 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;
|
||||
|
||||
g_vertices[0].x = x1;
|
||||
g_vertices[0].y = y1;
|
||||
|
||||
g_vertices[1].x = x1;
|
||||
g_vertices[1].y = y2;
|
||||
|
||||
g_vertices[2].x = x2;
|
||||
g_vertices[2].y = y1;
|
||||
|
||||
g_vertices[3].x = x2;
|
||||
g_vertices[3].y = y2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
extern double g_timer_frequency;
|
||||
extern double g_timer_resolution;
|
||||
|
||||
uint64_t
|
||||
mfb_timer_tick() {
|
||||
static mach_timebase_info_data_t timebase = { 0 };
|
||||
|
||||
if (timebase.denom == 0) {
|
||||
(void) mach_timebase_info(&timebase);
|
||||
}
|
||||
|
||||
uint64_t time = mach_absolute_time();
|
||||
|
||||
//return (time * s_timebase_info.numer) / s_timebase_info.denom;
|
||||
|
||||
// Perform the arithmetic at 128-bit precision to avoid the overflow!
|
||||
uint64_t high = (time >> 32) * timebase.numer;
|
||||
uint64_t highRem = ((high % timebase.denom) << 32) / timebase.denom;
|
||||
uint64_t low = (time & 0xFFFFFFFFull) * timebase.numer / timebase.denom;
|
||||
high /= timebase.denom;
|
||||
|
||||
return (high << 32) + highRem + low;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void
|
||||
mfb_timer_init() {
|
||||
g_timer_frequency = 1e+9;
|
||||
g_timer_resolution = 1.0 / g_timer_frequency;
|
||||
}
|
||||
|
14
src/ios/iOSViewController.h
Normal file
14
src/ios/iOSViewController.h
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// iOSViewController.h
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#include "iOSViewDelegate.h"
|
||||
|
||||
@interface iOSViewController : UIViewController
|
||||
|
||||
@end
|
49
src/ios/iOSViewController.m
Normal file
49
src/ios/iOSViewController.m
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// iOSViewController.m
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import "iOSViewController.h"
|
||||
#import <Metal/Metal.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#import "iOSViewDelegate.h"
|
||||
|
||||
//-------------------------------------
|
||||
@implementation iOSViewController
|
||||
{
|
||||
MTKView *_view;
|
||||
iOSViewDelegate *_renderer;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
- (void) loadView {
|
||||
UIView *view = [[MTKView alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
[self setView:view];
|
||||
[view release];
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
- (void) viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
_view = (MTKView *)self.view;
|
||||
_view.device = MTLCreateSystemDefaultDevice();
|
||||
_view.backgroundColor = UIColor.blackColor;
|
||||
|
||||
if(!_view.device) {
|
||||
NSLog(@"Metal is not supported on this device");
|
||||
self.view = [[UIView alloc] initWithFrame:self.view.frame];
|
||||
return;
|
||||
}
|
||||
|
||||
_renderer = [[iOSViewDelegate alloc] initWithMetalKitView:_view];
|
||||
[_renderer mtkView:_view drawableSizeWillChange:_view.bounds.size];
|
||||
|
||||
_view.delegate = _renderer;
|
||||
}
|
||||
|
||||
@end
|
23
src/ios/iOSViewDelegate.h
Normal file
23
src/ios/iOSViewDelegate.h
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Renderer.h
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#include "WindowData.h"
|
||||
|
||||
// Our platform independent renderer class.
|
||||
// Implements the MTKViewDelegate protocol which allows it to accept per-frame
|
||||
// update and drawable resize callbacks.
|
||||
@interface iOSViewDelegate : NSObject <MTKViewDelegate>
|
||||
{
|
||||
@public SWindowData *m_window_data;
|
||||
}
|
||||
|
||||
-(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view;
|
||||
|
||||
@end
|
||||
|
222
src/ios/iOSViewDelegate.m
Normal file
222
src/ios/iOSViewDelegate.m
Normal file
@ -0,0 +1,222 @@
|
||||
//
|
||||
// Renderer.m
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import <simd/simd.h>
|
||||
#import <ModelIO/ModelIO.h>
|
||||
|
||||
#import "iOSViewDelegate.h"
|
||||
#include "WindowData_IOS.h"
|
||||
#include <MiniFB.h>
|
||||
#include <MiniFB_ios.h>
|
||||
|
||||
//-------------------------------------
|
||||
#define kShader(inc, src) @inc#src
|
||||
|
||||
//-------------------------------------
|
||||
enum { MaxBuffersInFlight = 3 }; // Number of textures in flight (tripple buffered)
|
||||
|
||||
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},
|
||||
};
|
||||
|
||||
//--
|
||||
NSString *g_shader_src = kShader(
|
||||
"#include <metal_stdlib>\n",
|
||||
using namespace metal;
|
||||
|
||||
//---------------------
|
||||
struct VertexOutput {
|
||||
float4 pos [[position]];
|
||||
float2 texcoord;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
float4 position [[position]];
|
||||
};
|
||||
|
||||
//---------------------
|
||||
vertex VertexOutput
|
||||
vertFunc(unsigned int vID[[vertex_id]], const device Vertex *pos [[ buffer(0) ]]) {
|
||||
VertexOutput out;
|
||||
|
||||
out.pos = pos[vID].position;
|
||||
|
||||
out.texcoord.x = (float) (vID / 2);
|
||||
out.texcoord.y = 1.0 - (float) (vID % 2);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//---------------------
|
||||
fragment float4
|
||||
fragFunc(VertexOutput input [[stage_in]], texture2d<half> 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);
|
||||
|
||||
// We return the color of the texture
|
||||
return float4(colorSample);
|
||||
};
|
||||
);
|
||||
|
||||
//-------------------------------------
|
||||
@implementation iOSViewDelegate {
|
||||
dispatch_semaphore_t m_semaphore;
|
||||
id <MTLCommandQueue> m_command_queue;
|
||||
|
||||
id <MTLRenderPipelineState> m_pipeline_state;
|
||||
id <MTLTexture> m_texture_buffer;
|
||||
|
||||
uint8_t m_current_buffer;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
-(nonnull instancetype) initWithMetalKitView:(nonnull MTKView *) view {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
g_metal_device = view.device;
|
||||
|
||||
view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
view.sampleCount = 1;
|
||||
|
||||
uint32_t width = view.bounds.size.width;
|
||||
uint32_t height = view.bounds.size.height;
|
||||
|
||||
m_window_data = (SWindowData *) mfb_open_ex("", width, height, 0);
|
||||
|
||||
m_semaphore = dispatch_semaphore_create(MaxBuffersInFlight);
|
||||
m_command_queue = [g_metal_device newCommandQueue];
|
||||
|
||||
[self _createShaders];
|
||||
[self _createAssets];
|
||||
|
||||
user_implemented_init((struct mfb_window *) m_window_data);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
- (bool) _createShaders {
|
||||
NSError *error = nil;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
id<MTLFunction> vertex_shader_func = [g_library newFunctionWithName:@"vertFunc"];
|
||||
id<MTLFunction> fragment_shader_func = [g_library newFunctionWithName:@"fragFunc"];
|
||||
|
||||
if (!vertex_shader_func) {
|
||||
NSLog(@"Unable to get vertFunc!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fragment_shader_func) {
|
||||
NSLog(@"Unable to get fragFunc!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
pipelineStateDescriptor.label = @"MiniFB_pipeline";
|
||||
pipelineStateDescriptor.vertexFunction = vertex_shader_func;
|
||||
pipelineStateDescriptor.fragmentFunction = fragment_shader_func;
|
||||
pipelineStateDescriptor.colorAttachments[0].pixelFormat = 80; //bgra8Unorm;
|
||||
|
||||
m_pipeline_state = [g_metal_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error];
|
||||
if (!m_pipeline_state) {
|
||||
NSLog(@"Failed to created pipeline state, error %@", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
- (void) _createAssets {
|
||||
MTLTextureDescriptor *td;
|
||||
td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||
width:m_window_data->window_width
|
||||
height:m_window_data->window_height
|
||||
mipmapped:false];
|
||||
|
||||
m_texture_buffer = [g_metal_device newTextureWithDescriptor:td];
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
- (void) drawInMTKView:(nonnull MTKView *) view
|
||||
{
|
||||
// Per frame updates here
|
||||
user_implemented_update((struct mfb_window *) m_window_data);
|
||||
|
||||
dispatch_semaphore_wait(m_semaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
m_current_buffer = (m_current_buffer + 1) % MaxBuffersInFlight;
|
||||
|
||||
id <MTLCommandBuffer> commandBuffer = [m_command_queue commandBuffer];
|
||||
commandBuffer.label = @"minifb_command_buffer";
|
||||
|
||||
__block dispatch_semaphore_t block_sema = m_semaphore;
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
|
||||
dispatch_semaphore_signal(block_sema);
|
||||
}];
|
||||
|
||||
// Copy the bytes from our data object into the texture
|
||||
MTLRegion region = { { 0, 0, 0 }, { m_window_data->window_width, m_window_data->window_height, 1 } };
|
||||
[m_texture_buffer replaceRegion:region mipmapLevel:0 withBytes:m_window_data->draw_buffer bytesPerRow:m_window_data->buffer_stride];
|
||||
|
||||
// Delay getting the currentRenderPassDescriptor until absolutely needed. This avoids
|
||||
// holding onto the drawable and blocking the display pipeline any longer than necessary
|
||||
MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;
|
||||
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<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
renderEncoder.label = @"minifb_command_encoder";
|
||||
|
||||
// Set render command encoder state
|
||||
[renderEncoder setRenderPipelineState:m_pipeline_state];
|
||||
[renderEncoder setVertexBytes:g_vertices length:sizeof(g_vertices) atIndex:0];
|
||||
|
||||
//[renderEncoder setFragmentTexture:m_texture_buffers[m_current_buffer] atIndex:0];
|
||||
[renderEncoder setFragmentTexture:m_texture_buffer atIndex:0];
|
||||
|
||||
// Draw the vertices of our quads
|
||||
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
|
||||
// We're done encoding commands
|
||||
[renderEncoder endEncoding];
|
||||
|
||||
// Schedule a present once the framebuffer is complete using the current drawable
|
||||
[commandBuffer presentDrawable:view.currentDrawable];
|
||||
}
|
||||
|
||||
// Finalize rendering here & push the command buffer to the GPU
|
||||
[commandBuffer commit];
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
- (void) mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
|
||||
// Respond to drawable size or orientation changes here
|
||||
}
|
||||
|
||||
@end
|
20
tests/ios/AppDelegate.h
Normal file
20
tests/ios/AppDelegate.h
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
{
|
||||
CADisplayLink *mDisplayLink;
|
||||
}
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
- (void) on_update;
|
||||
|
||||
@end
|
||||
|
128
tests/ios/AppDelegate.m
Normal file
128
tests/ios/AppDelegate.m
Normal file
@ -0,0 +1,128 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#include <MiniFB.h>
|
||||
#include <iOSViewController.h>
|
||||
|
||||
static uint32_t *g_buffer = 0x0;
|
||||
static uint32_t g_width = 0;
|
||||
static uint32_t g_height = 0;
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
void
|
||||
user_implemented_init(struct mfb_window *window) {
|
||||
g_width = mfb_get_window_width(window);
|
||||
g_height = mfb_get_window_height(window);
|
||||
g_buffer = malloc(g_width * g_height * 4);
|
||||
|
||||
// mfb_set_viewport(window, 50, 50, 200, 200);
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
void
|
||||
user_implemented_update(struct mfb_window *window) {
|
||||
static int seed = 0xbeef;
|
||||
int noise, carry;
|
||||
|
||||
if(g_buffer != 0x0) {
|
||||
for (uint32_t i = 0; i < g_width * g_height; ++i) {
|
||||
noise = seed;
|
||||
noise >>= 3;
|
||||
noise ^= seed;
|
||||
carry = noise & 1;
|
||||
noise >>= 1;
|
||||
seed >>= 1;
|
||||
seed |= (carry << 30);
|
||||
noise &= 0xFF;
|
||||
g_buffer[i] = MFB_RGB(noise, noise, noise);
|
||||
}
|
||||
}
|
||||
|
||||
mfb_update_state state = mfb_update(window, g_buffer);
|
||||
if (state != STATE_OK) {
|
||||
free(g_buffer);
|
||||
g_buffer = 0x0;
|
||||
g_width = 0;
|
||||
g_height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) on_update {
|
||||
NSLog(@"si");
|
||||
}
|
||||
|
||||
- (void) applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
UIWindow *window;
|
||||
NSArray *pWindows;
|
||||
size_t numWindows;
|
||||
|
||||
pWindows = [[UIApplication sharedApplication] windows];
|
||||
|
||||
numWindows = [pWindows count];
|
||||
//iOSViewController *controller = [[iOSViewController alloc] initWithFrame: [UIScreen mainScreen].bounds];
|
||||
iOSViewController *controller = [[iOSViewController alloc] init];
|
||||
if(numWindows > 0)
|
||||
{
|
||||
window = [pWindows objectAtIndex:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Notice that you need to set "Launch Screen File" in:
|
||||
// project > executable > general to get the real size
|
||||
window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
NSLog(@"UIApplication has no window. We create one (%f, %f).", [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
|
||||
}
|
||||
[window setRootViewController:controller];
|
||||
[controller release];
|
||||
controller = (iOSViewController *) window.rootViewController;
|
||||
[window makeKeyAndVisible];
|
||||
|
||||
mDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(on_update)];
|
||||
[mDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
[mDisplayLink invalidate];
|
||||
}
|
||||
|
||||
|
||||
@end
|
16
tests/ios/main.m
Normal file
16
tests/ios/main.m
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// main.m
|
||||
// MiniFB
|
||||
//
|
||||
// Created by Carlos Aragones on 22/04/2020.
|
||||
// Copyright © 2020 Carlos Aragones. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user