From bee3fd30ce150743e244750120059e1017d000c7 Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 27 Jul 2018 02:10:28 -0700 Subject: [PATCH] Cocoa Port: Update the Metal blitter to support Y-flipping of the rendered video frame, matching the same feature that already exists in the OpenGL blitter. --- .../cocoa/userinterface/MacMetalDisplayView.h | 3 ++- .../cocoa/userinterface/MacMetalDisplayView.mm | 16 +++++++++++----- .../MacMetalDisplayViewShaders.metal | 17 +++++++++++++---- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h index 865258710..c082462bf 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.h @@ -246,7 +246,8 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties; outputPipelineState:(id)outputPipelineState hudPipelineState:(id)hudPipelineState texDisplays:(MetalTexturePair)texDisplay - mrfi:(MetalRenderFrameInfo)mrfi; + mrfi:(MetalRenderFrameInfo)mrfi + doYFlip:(BOOL)willFlip; - (void) renderStartAtIndex:(uint8_t)index; - (void) renderFinishAtIndex:(uint8_t)index; - (ClientDisplayBufferState) renderBufferStateAtIndex:(uint8_t)index; diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index 51742cfb5..df844f5a9 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -1885,6 +1885,7 @@ hudPipelineState:(id)hudPipelineState texDisplays:(MetalTexturePair)texDisplay mrfi:(MetalRenderFrameInfo)mrfi + doYFlip:(BOOL)willFlip { // Generate the command encoder. id rce = [cb renderCommandEncoderWithDescriptor:_outputRenderPassDesc]; @@ -1899,6 +1900,7 @@ } // Draw the NDS displays. + const uint8_t doYFlip = (willFlip) ? 1 : 0; const NDSDisplayInfo &displayInfo = cdp->GetEmuDisplayInfo(); const float backlightIntensity[2] = { displayInfo.backlightIntensity[NDSDisplayID_Main], displayInfo.backlightIntensity[NDSDisplayID_Touch] }; @@ -1906,6 +1908,7 @@ [rce setVertexBytes:_vtxPositionBuffer length:sizeof(_vtxPositionBuffer) atIndex:0]; [rce setVertexBytes:_texCoordBuffer length:sizeof(_texCoordBuffer) atIndex:1]; [rce setVertexBytes:&_cdvPropertiesBuffer length:sizeof(_cdvPropertiesBuffer) atIndex:2]; + [rce setVertexBytes:&doYFlip length:sizeof(uint8_t) atIndex:3]; switch (cdp->GetPresenterProperties().mode) { @@ -1986,13 +1989,14 @@ [rce setVertexBuffer:_hudVtxColorBuffer[mrfi.renderIndex] offset:0 atIndex:1]; [rce setVertexBuffer:_hudTexCoordBuffer[mrfi.renderIndex] offset:0 atIndex:2]; [rce setVertexBytes:&_cdvPropertiesBuffer length:sizeof(_cdvPropertiesBuffer) atIndex:3]; + [rce setVertexBytes:&doYFlip length:sizeof(uint8_t) atIndex:4]; [rce setFragmentTexture:[self texHUDCharMap] atIndex:0]; // First, draw the inputs. if (mrfi.willDrawHUDInput) { isScreenOverlay = 1; - [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4]; + [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:5]; [rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0]; [rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:mrfi.hudTouchLineLength * 6 @@ -2001,7 +2005,7 @@ indexBufferOffset:(mrfi.hudStringLength + HUD_INPUT_ELEMENT_LENGTH) * 6 * sizeof(uint16_t)]; isScreenOverlay = 0; - [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4]; + [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:5]; [rce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0]; [rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:HUD_INPUT_ELEMENT_LENGTH * 6 @@ -2011,7 +2015,7 @@ } // Next, draw the backing text box. - [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4]; + [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:5]; [rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0]; [rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 @@ -2092,7 +2096,8 @@ outputPipelineState:[self outputRGBAPipeline] hudPipelineState:[sharedData hudRGBAPipeline] texDisplays:texProcess - mrfi:mrfi]; + mrfi:mrfi + doYFlip:YES]; id bce = [cb blitCommandEncoder]; @@ -2198,7 +2203,8 @@ outputPipelineState:[presenterObject outputDrawablePipeline] hudPipelineState:[[presenterObject sharedData] hudPipeline] texDisplays:texProcess - mrfi:mrfi]; + mrfi:mrfi + doYFlip:NO]; [cbRender addScheduledHandler:^(id block) { [presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex]; diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal index 16e050ca4..2fd630af6 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal @@ -146,7 +146,8 @@ vertex HUDVtx hud_vertex(const device float2 *inPosition [[buffer(0)]], const device uint32_t *inColor [[buffer(1)]], const device float2 *inTexCoord [[buffer(2)]], const constant DisplayViewShaderProperties &viewProps [[buffer(3)]], - const constant uint8_t &isScreenOverlay [[buffer(4)]], + const constant uint8_t &doYFlip [[buffer(4)]], + const constant uint8_t &isScreenOverlay [[buffer(5)]], const uint vid [[vertex_id]]) { const float angleRadians = viewProps.rotation * (M_PI_F/180.0f); @@ -160,8 +161,10 @@ vertex HUDVtx hud_vertex(const device float2 *inPosition [[buffer(0)]], const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f), float2( 0.0f, viewProps.viewScale)); + const float2 yFlip = (doYFlip != 0) ? float2(1.0f, -1.0f) : float2(1.0f, 1.0f); + HUDVtx outVtx; - outVtx.position = (isScreenOverlay != 0) ? float4(projection * rotation * scale * inPosition[vid], 0.0f, 1.0f) : float4(projection * inPosition[vid], 0.0f, 1.0f); + outVtx.position = (isScreenOverlay != 0) ? float4(projection * rotation * scale * inPosition[vid] * yFlip, 0.0f, 1.0f) : float4(projection * inPosition[vid] * yFlip, 0.0f, 1.0f); outVtx.color = float4( (float)((inColor[vid] >> 0) & 0xFF) / 255.0f, (float)((inColor[vid] >> 8) & 0xFF) / 255.0f, (float)((inColor[vid] >> 16) & 0xFF) / 255.0f, (float)((inColor[vid] >> 24) & 0xFF) / 255.0f ); outVtx.texCoord = inTexCoord[vid]; outVtx.lowerHUDMipMapLevel = (viewProps.lowerHUDMipMapLevel == 1); @@ -181,6 +184,7 @@ fragment float4 hud_fragment(const HUDVtx vtx [[stage_in]], vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer(0)]], const device float2 *inTexCoord [[buffer(1)]], const constant DisplayViewShaderProperties &viewProps [[buffer(2)]], + const constant uint8_t &doYFlip [[buffer(3)]], const uint vid [[vertex_id]]) { const float angleRadians = viewProps.rotation * (M_PI_F/180.0f); @@ -194,8 +198,10 @@ vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f), float2( 0.0f, viewProps.viewScale)); + const float2 yFlip = (doYFlip != 0) ? float2(1.0f, -1.0f) : float2(1.0f, 1.0f); + DisplayVtx outVtx; - outVtx.position = float4(projection * rotation * scale * inPosition[vid], 0.0f, 1.0f); + outVtx.position = float4(projection * rotation * scale * inPosition[vid] * yFlip, 0.0f, 1.0f); outVtx.texCoord = inTexCoord[vid]; return outVtx; @@ -204,6 +210,7 @@ vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer vertex DisplayVtx display_output_bicubic_vertex(const device float2 *inPosition [[buffer(0)]], const device float2 *inTexCoord [[buffer(1)]], const constant DisplayViewShaderProperties &viewProps [[buffer(2)]], + const constant uint8_t &doYFlip [[buffer(3)]], const uint vid [[vertex_id]]) { const float angleRadians = viewProps.rotation * (M_PI_F/180.0f); @@ -217,8 +224,10 @@ vertex DisplayVtx display_output_bicubic_vertex(const device float2 *inPosition const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f), float2( 0.0f, viewProps.viewScale)); + const float2 yFlip = (doYFlip != 0) ? float2(1.0f, -1.0f) : float2(1.0f, 1.0f); + DisplayVtx outVtx; - outVtx.position = float4(projection * rotation * scale * inPosition[vid], 0.0f, 1.0f); + outVtx.position = float4(projection * rotation * scale * inPosition[vid] * yFlip, 0.0f, 1.0f); outVtx.texCoord = floor(inTexCoord[vid] - 0.5f) + 0.5f; return outVtx;