mirror of
https://github.com/libretro/RetroArch
synced 2025-01-18 04:12:07 +00:00
a0900ec433
Menu TODOs: * understand why ribbon does not look the same as GL * add clear support to `MenuDisplay` for glui
214 lines
5.9 KiB
Objective-C
214 lines
5.9 KiB
Objective-C
//
|
|
// Created by Stuart Carnie on 6/24/18.
|
|
//
|
|
|
|
#import "Context.h"
|
|
#import "MenuDisplay.h"
|
|
#import "ShaderTypes.h"
|
|
#import "menu_driver.h"
|
|
#import <Metal/Metal.h>
|
|
// TODO(sgc): this dependency is incorrect
|
|
#import "../metal_common.h"
|
|
|
|
@implementation MenuDisplay
|
|
{
|
|
__weak MetalDriver *_driver;
|
|
Context *_context;
|
|
MTLClearColor _clearColor;
|
|
bool _clearNextRender;
|
|
Uniforms _uniforms;
|
|
}
|
|
|
|
- (instancetype)initWithDriver:(MetalDriver *)driver
|
|
{
|
|
if (self = [super init])
|
|
{
|
|
_driver = driver;
|
|
_context = driver.context;
|
|
_clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
|
|
_uniforms.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
|
|
}
|
|
return self;
|
|
}
|
|
|
|
+ (const float *)defaultVertices
|
|
{
|
|
static float dummy[] = {
|
|
0.0f, 1.0f,
|
|
1.0f, 1.0f,
|
|
0.0f, 0.0f,
|
|
1.0f, 0.0f,
|
|
};
|
|
return &dummy[0];
|
|
}
|
|
|
|
+ (const float *)defaultTexCoords
|
|
{
|
|
static float dummy[] = {
|
|
0.0f, 0.0f,
|
|
1.0f, 0.0f,
|
|
0.0f, 1.0f,
|
|
1.0f, 1.0f,
|
|
};
|
|
return &dummy[0];
|
|
}
|
|
|
|
+ (const float *)defaultColor
|
|
{
|
|
static float dummy[] = {
|
|
1.0f, 0.0f, 1.0f, 1.0f,
|
|
1.0f, 0.0f, 1.0f, 1.0f,
|
|
1.0f, 0.0f, 1.0f, 1.0f,
|
|
1.0f, 0.0f, 1.0f, 1.0f,
|
|
};
|
|
return &dummy[0];
|
|
}
|
|
|
|
- (void)setClearColor:(MTLClearColor)clearColor
|
|
{
|
|
_clearColor = clearColor;
|
|
_clearNextRender = YES;
|
|
}
|
|
|
|
- (MTLClearColor)clearColor
|
|
{
|
|
return _clearColor;
|
|
}
|
|
|
|
- (MTLPrimitiveType)_toPrimitiveType:(enum menu_display_prim_type)prim
|
|
{
|
|
switch (prim)
|
|
{
|
|
case MENU_DISPLAY_PRIM_TRIANGLESTRIP:
|
|
return MTLPrimitiveTypeTriangleStrip;
|
|
case MENU_DISPLAY_PRIM_TRIANGLES:
|
|
return MTLPrimitiveTypeTriangle;
|
|
default:
|
|
RARCH_LOG("unexpected primitive type %d\n", prim);
|
|
return MTLPrimitiveTypeTriangle;
|
|
}
|
|
}
|
|
|
|
- (void)drawPipeline:(menu_display_ctx_draw_t *)draw video:(video_frame_info_t *)video
|
|
{
|
|
static struct video_coords blank_coords;
|
|
|
|
draw->x = 0;
|
|
draw->y = 0;
|
|
draw->matrix_data = NULL;
|
|
|
|
_uniforms.outputSize = simd_make_float2(_driver.viewport->full_width, _driver.viewport->full_height);
|
|
|
|
draw->pipeline.backend_data = &_uniforms;
|
|
draw->pipeline.backend_data_size = sizeof(_uniforms);
|
|
|
|
switch (draw->pipeline.id)
|
|
{
|
|
// ribbon
|
|
default:
|
|
case VIDEO_SHADER_MENU:
|
|
case VIDEO_SHADER_MENU_2:
|
|
{
|
|
video_coord_array_t *ca = menu_display_get_coords_array();
|
|
draw->coords = (struct video_coords *)&ca->coords;
|
|
break;
|
|
}
|
|
|
|
case VIDEO_SHADER_MENU_3:
|
|
case VIDEO_SHADER_MENU_4:
|
|
case VIDEO_SHADER_MENU_5:
|
|
case VIDEO_SHADER_MENU_6:
|
|
{
|
|
draw->coords = &blank_coords;
|
|
blank_coords.vertices = 4;
|
|
draw->prim_type = MENU_DISPLAY_PRIM_TRIANGLESTRIP;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_uniforms.time += 0.01;
|
|
}
|
|
|
|
- (void)draw:(menu_display_ctx_draw_t *)draw video:(video_frame_info_t *)video
|
|
{
|
|
Texture *tex = (__bridge Texture *)(void *)draw->texture;
|
|
const float *vertex = draw->coords->vertex ?: MenuDisplay.defaultVertices;
|
|
const float *tex_coord = draw->coords->tex_coord ?: MenuDisplay.defaultTexCoords;
|
|
const float *color = draw->coords->color ?: MenuDisplay.defaultColor;
|
|
|
|
NSUInteger needed = draw->coords->vertices * sizeof(SpriteVertex);
|
|
BufferRange range;
|
|
if (![_context allocRange:&range length:needed])
|
|
{
|
|
RARCH_ERR("[Metal]: MenuDisplay unable to allocate buffer of %d bytes", needed);
|
|
return;
|
|
}
|
|
|
|
NSUInteger vertexCount = draw->coords->vertices;
|
|
SpriteVertex *pv = (SpriteVertex *)range.data;
|
|
for (unsigned i = 0; i < draw->coords->vertices; i++, pv++)
|
|
{
|
|
pv->position = simd_make_float2(vertex[0], 1.0 - vertex[1]);
|
|
vertex += 2;
|
|
|
|
pv->texCoord = simd_make_float2(tex_coord[0], tex_coord[1]);
|
|
tex_coord += 2;
|
|
|
|
pv->color = simd_make_float4(color[0], color[1], color[2], color[3]);
|
|
color += 4;
|
|
}
|
|
|
|
id<MTLRenderCommandEncoder> rce = _context.rce;
|
|
MTLViewport vp = {
|
|
.originX = draw->x,
|
|
.originY = _driver.viewport->full_height - draw->y - draw->height,
|
|
.width = draw->width,
|
|
.height = draw->height,
|
|
.znear = 0,
|
|
.zfar = 1,
|
|
};
|
|
[rce setViewport:vp];
|
|
|
|
switch (draw->pipeline.id)
|
|
{
|
|
#if HAVE_SHADERPIPELINE
|
|
case VIDEO_SHADER_MENU:
|
|
case VIDEO_SHADER_MENU_2:
|
|
case VIDEO_SHADER_MENU_3:
|
|
case VIDEO_SHADER_MENU_4:
|
|
case VIDEO_SHADER_MENU_5:
|
|
case VIDEO_SHADER_MENU_6:
|
|
{
|
|
[rce setRenderPipelineState:[_driver getStockShader:draw->pipeline.id blend:_blend]];
|
|
[rce setVertexBytes:draw->pipeline.backend_data length:draw->pipeline.backend_data_size atIndex:BufferIndexUniforms];
|
|
[rce setVertexBuffer:range.buffer offset:range.offset atIndex:BufferIndexPositions];
|
|
[rce setFragmentBytes:draw->pipeline.backend_data length:draw->pipeline.backend_data_size atIndex:BufferIndexUniforms];
|
|
[rce drawPrimitives:[self _toPrimitiveType:draw->prim_type] vertexStart:0 vertexCount:vertexCount];
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
{
|
|
if (_clearNextRender)
|
|
{
|
|
// TODO(sgc): draw quad to clear
|
|
_clearNextRender = NO;
|
|
}
|
|
|
|
[rce setRenderPipelineState:[_driver getStockShader:VIDEO_SHADER_STOCK_BLEND blend:_blend]];
|
|
Uniforms uniforms = {
|
|
.projectionMatrix = draw->matrix_data ? *(matrix_float4x4 *)draw->matrix_data
|
|
: _uniforms.projectionMatrix
|
|
};
|
|
[rce setVertexBytes:&uniforms length:sizeof(uniforms) atIndex:BufferIndexUniforms];
|
|
[rce setVertexBuffer:range.buffer offset:range.offset atIndex:BufferIndexPositions];
|
|
[rce setFragmentTexture:tex.texture atIndex:TextureIndexColor];
|
|
[rce setFragmentSamplerState:tex.sampler atIndex:SamplerIndexDraw];
|
|
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:vertexCount];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
@end
|