Cocoa Port: Copying the contents of the display window via Edit > Copy now copies the actual contents of the display window instead of directly copying the NDS screens with a generic vertical layout.
This commit is contained in:
parent
70c69a46d3
commit
d37ef1ff95
|
@ -1017,7 +1017,12 @@ void ClientDisplayView::FlushView()
|
|||
this->_viewNeedsFlush = false;
|
||||
}
|
||||
|
||||
void ClientDisplayView::FinishFrameAtIndex(const u8 bufferIndex)
|
||||
void ClientDisplayView::CopyFrameToBuffer(uint32_t *dstBuffer)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
}
|
||||
|
||||
void ClientDisplayView::FinishFrameAtIndex(const uint8_t bufferIndex)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
}
|
||||
|
|
|
@ -320,7 +320,9 @@ public:
|
|||
virtual void ProcessDisplays();
|
||||
virtual void UpdateView();
|
||||
virtual void FlushView();
|
||||
virtual void FinishFrameAtIndex(const u8 bufferIndex);
|
||||
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
|
||||
|
||||
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
|
||||
|
||||
// Emulator interface
|
||||
const NDSDisplayInfo& GetEmuDisplayInfo() const;
|
||||
|
|
|
@ -34,6 +34,7 @@ static const char *HUDOutputVertShader_100 = {"\
|
|||
uniform vec2 viewSize; \n\
|
||||
uniform float scalar; \n\
|
||||
uniform float angleDegrees; \n\
|
||||
uniform bool renderFlipped; \n\
|
||||
\n\
|
||||
VARYING vec4 vtxColor; \n\
|
||||
VARYING vec2 texCoord[1]; \n\
|
||||
|
@ -54,6 +55,11 @@ static const char *HUDOutputVertShader_100 = {"\
|
|||
vtxColor = inColor; \n\
|
||||
texCoord[0] = inTexCoord0; \n\
|
||||
gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\
|
||||
\n\
|
||||
if (renderFlipped)\n\
|
||||
{\n\
|
||||
gl_Position.y *= -1.0;\n\
|
||||
}\n\
|
||||
} \n\
|
||||
"};
|
||||
|
||||
|
@ -77,6 +83,7 @@ static const char *Sample1x1OutputVertShader_100 = {"\
|
|||
uniform vec2 viewSize; \n\
|
||||
uniform float scalar; \n\
|
||||
uniform float angleDegrees; \n\
|
||||
uniform bool renderFlipped; \n\
|
||||
\n\
|
||||
VARYING vec2 texCoord[1]; \n\
|
||||
\n\
|
||||
|
@ -95,6 +102,11 @@ static const char *Sample1x1OutputVertShader_100 = {"\
|
|||
\n\
|
||||
texCoord[0] = inTexCoord0; \n\
|
||||
gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\
|
||||
\n\
|
||||
if (renderFlipped)\n\
|
||||
{\n\
|
||||
gl_Position.y *= -1.0;\n\
|
||||
}\n\
|
||||
} \n\
|
||||
"};
|
||||
|
||||
|
@ -111,6 +123,7 @@ static const char *BicubicSample4x4Output_VertShader_110 = {"\
|
|||
uniform vec2 viewSize; \n\
|
||||
uniform float scalar; \n\
|
||||
uniform float angleDegrees; \n\
|
||||
uniform bool renderFlipped; \n\
|
||||
\n\
|
||||
VARYING vec2 texCoord[16];\n\
|
||||
\n\
|
||||
|
@ -150,6 +163,11 @@ static const char *BicubicSample4x4Output_VertShader_110 = {"\
|
|||
texCoord[12] = xystart + vec2( 2.0, 2.0);\n\
|
||||
\n\
|
||||
gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\
|
||||
\n\
|
||||
if (renderFlipped)\n\
|
||||
{\n\
|
||||
gl_Position.y *= -1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
|
@ -167,6 +185,7 @@ static const char *BicubicSample5x5Output_VertShader_110 = {"\
|
|||
uniform vec2 viewSize; \n\
|
||||
uniform float scalar; \n\
|
||||
uniform float angleDegrees; \n\
|
||||
uniform bool renderFlipped; \n\
|
||||
\n\
|
||||
VARYING vec2 texCoord[25];\n\
|
||||
\n\
|
||||
|
@ -216,6 +235,11 @@ static const char *BicubicSample5x5Output_VertShader_110 = {"\
|
|||
texCoord[12] = xystart + vec2( 2.0, 2.0);\n\
|
||||
\n\
|
||||
gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\
|
||||
\n\
|
||||
if (renderFlipped)\n\
|
||||
{\n\
|
||||
gl_Position.y *= -1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
|
@ -234,6 +258,7 @@ static const char *BicubicSample6x6Output_VertShader_110 = {"\
|
|||
uniform vec2 viewSize; \n\
|
||||
uniform float scalar; \n\
|
||||
uniform float angleDegrees; \n\
|
||||
uniform bool renderFlipped; \n\
|
||||
\n\
|
||||
VARYING vec2 texCoord[36];\n\
|
||||
\n\
|
||||
|
@ -295,6 +320,11 @@ static const char *BicubicSample6x6Output_VertShader_110 = {"\
|
|||
texCoord[30] = xystart + vec2( 3.0, 3.0);\n\
|
||||
\n\
|
||||
gl_Position = vec4(projection * rotation * scale * inPosition, 0.0, 1.0);\n\
|
||||
\n\
|
||||
if (renderFlipped)\n\
|
||||
{\n\
|
||||
gl_Position.y *= -1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
|
@ -4996,6 +5026,8 @@ OGLVideoOutput::OGLVideoOutput()
|
|||
|
||||
_texCPUFilterDstID[NDSDisplayID_Main] = 0;
|
||||
_texCPUFilterDstID[NDSDisplayID_Touch] = 0;
|
||||
|
||||
_fboFrameCopyID = 0;
|
||||
}
|
||||
|
||||
OGLVideoOutput::~OGLVideoOutput()
|
||||
|
@ -5011,6 +5043,7 @@ OGLVideoOutput::~OGLVideoOutput()
|
|||
this->_layerList = NULL;
|
||||
}
|
||||
|
||||
glDeleteFramebuffersEXT(1, &this->_fboFrameCopyID);
|
||||
glDeleteTextures(2, this->_texCPUFilterDstID);
|
||||
}
|
||||
|
||||
|
@ -5118,7 +5151,7 @@ void OGLVideoOutput::Init()
|
|||
glDisable(GL_DITHER);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
|
||||
// Set up fixed-function pipeline render states.
|
||||
if (!this->_contextInfo->IsShaderSupported())
|
||||
|
@ -5133,10 +5166,9 @@ void OGLVideoOutput::Init()
|
|||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Set up textures
|
||||
glGenTextures(2, this->_texCPUFilterDstID);
|
||||
|
||||
glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_ARB, this->_vfMasterDstBufferSize, this->_vfMasterDstBuffer);
|
||||
|
||||
glGenTextures(2, this->_texCPUFilterDstID);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texCPUFilterDstID[NDSDisplayID_Main]);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
@ -5154,6 +5186,8 @@ void OGLVideoOutput::Init()
|
|||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_vf[NDSDisplayID_Touch]->GetDstWidth(), this->_vf[NDSDisplayID_Touch]->GetDstHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_vf[NDSDisplayID_Touch]->GetDstBufferPtr());
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
glGenFramebuffersEXT(1, &this->_fboFrameCopyID);
|
||||
}
|
||||
|
||||
void OGLVideoOutput::SetOutputFilter(const OutputFilterTypeID filterID)
|
||||
|
@ -5222,7 +5256,7 @@ void OGLVideoOutput::ProcessDisplays()
|
|||
}
|
||||
}
|
||||
|
||||
void OGLVideoOutput::FinishFrameAtIndex(const u8 bufferIndex)
|
||||
void OGLVideoOutput::FinishFrameAtIndex(const uint8_t bufferIndex)
|
||||
{
|
||||
for (size_t i = 0; i < _layerList->size(); i++)
|
||||
{
|
||||
|
@ -5235,7 +5269,42 @@ void OGLVideoOutput::FinishFrameAtIndex(const u8 bufferIndex)
|
|||
}
|
||||
}
|
||||
|
||||
void OGLVideoOutput::RenderViewOGL()
|
||||
void OGLVideoOutput::CopyFrameToBuffer(uint32_t *dstBuffer)
|
||||
{
|
||||
for (size_t i = 0; i < _layerList->size(); i++)
|
||||
{
|
||||
OGLVideoLayer *theLayer = (*_layerList)[i];
|
||||
theLayer->SetNeedsUpdateViewport();
|
||||
}
|
||||
|
||||
GLuint texFrameCopyID = 0;
|
||||
|
||||
glGenTextures(1, &texFrameCopyID);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texFrameCopyID);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_viewportWidth, this->_viewportHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, dstBuffer);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->_fboFrameCopyID);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texFrameCopyID, 0);
|
||||
|
||||
this->RenderFrameOGL(true);
|
||||
glReadPixels(0, 0, this->_renderProperty.clientWidth, this->_renderProperty.clientHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, dstBuffer);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
glDeleteTextures(1, &texFrameCopyID);
|
||||
|
||||
for (size_t i = 0; i < _layerList->size(); i++)
|
||||
{
|
||||
OGLVideoLayer *theLayer = (*_layerList)[i];
|
||||
theLayer->SetNeedsUpdateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
void OGLVideoOutput::RenderFrameOGL(bool isRenderingFlipped)
|
||||
{
|
||||
if (this->_needUpdateViewport)
|
||||
{
|
||||
|
@ -5251,7 +5320,7 @@ void OGLVideoOutput::RenderViewOGL()
|
|||
|
||||
if (theLayer->IsVisible())
|
||||
{
|
||||
theLayer->RenderOGL();
|
||||
theLayer->RenderOGL(isRenderingFlipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5632,6 +5701,7 @@ OGLImage::OGLImage(OGLContextInfo *contextInfo, GLsizei imageWidth, GLsizei imag
|
|||
_uniformAngleDegrees = glGetUniformLocation(finalOutputProgramID, "angleDegrees");
|
||||
_uniformScalar = glGetUniformLocation(finalOutputProgramID, "scalar");
|
||||
_uniformViewSize = glGetUniformLocation(finalOutputProgramID, "viewSize");
|
||||
_uniformRenderFlipped = glGetUniformLocation(finalOutputProgramID, "renderFlipped");
|
||||
glUseProgram(0);
|
||||
}
|
||||
else
|
||||
|
@ -5771,6 +5841,7 @@ void OGLImage::UploadTransformationOGL()
|
|||
glUniform2f(this->_uniformViewSize, w, h);
|
||||
glUniform1f(this->_uniformAngleDegrees, 0.0f);
|
||||
glUniform1f(this->_uniformScalar, s);
|
||||
glUniform1i(this->_uniformRenderFlipped, GL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6228,6 +6299,7 @@ OGLHUDLayer::OGLHUDLayer(OGLVideoOutput *oglVO)
|
|||
_uniformAngleDegrees = glGetUniformLocation(_program->GetProgramID(), "angleDegrees");
|
||||
_uniformScalar = glGetUniformLocation(_program->GetProgramID(), "scalar");
|
||||
_uniformViewSize = glGetUniformLocation(_program->GetProgramID(), "viewSize");
|
||||
_uniformRenderFlipped = glGetUniformLocation(_program->GetProgramID(), "renderFlipped");
|
||||
glUseProgram(0);
|
||||
}
|
||||
else
|
||||
|
@ -6438,7 +6510,7 @@ void OGLHUDLayer::_UpdateVerticesOGL()
|
|||
this->_output->ClearHUDNeedsUpdate();
|
||||
}
|
||||
|
||||
void OGLHUDLayer::RenderOGL()
|
||||
void OGLHUDLayer::RenderOGL(bool isRenderingFlipped)
|
||||
{
|
||||
size_t hudLength = this->_output->GetHUDString().length();
|
||||
size_t hudTouchLineLength = 0;
|
||||
|
@ -6489,6 +6561,7 @@ void OGLHUDLayer::RenderOGL()
|
|||
if (this->_needUpdateViewport)
|
||||
{
|
||||
glUniform2f(this->_uniformViewSize, this->_output->GetViewProperties().clientWidth, this->_output->GetViewProperties().clientHeight);
|
||||
glUniform1i(this->_uniformRenderFlipped, (isRenderingFlipped) ? GL_TRUE : GL_FALSE);
|
||||
this->_needUpdateViewport = false;
|
||||
}
|
||||
}
|
||||
|
@ -6645,6 +6718,7 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO)
|
|||
_uniformAngleDegrees = glGetUniformLocation(finalOutputProgramID, "angleDegrees");
|
||||
_uniformScalar = glGetUniformLocation(finalOutputProgramID, "scalar");
|
||||
_uniformViewSize = glGetUniformLocation(finalOutputProgramID, "viewSize");
|
||||
_uniformRenderFlipped = glGetUniformLocation(finalOutputProgramID, "renderFlipped");
|
||||
glUseProgram(0);
|
||||
}
|
||||
else
|
||||
|
@ -7134,7 +7208,7 @@ void OGLDisplayLayer::ProcessOGL()
|
|||
glViewport(0, 0, this->_output->GetViewportWidth(), this->_output->GetViewportHeight());
|
||||
}
|
||||
|
||||
void OGLDisplayLayer::RenderOGL()
|
||||
void OGLDisplayLayer::RenderOGL(bool isRenderingFlipped)
|
||||
{
|
||||
const NDSDisplayInfo &emuDisplayInfo = this->_output->GetEmuDisplayInfo();
|
||||
|
||||
|
@ -7145,6 +7219,7 @@ void OGLDisplayLayer::RenderOGL()
|
|||
if (this->_needUpdateViewport)
|
||||
{
|
||||
glUniform2f(this->_uniformViewSize, this->_output->GetViewportWidth(), this->_output->GetViewportHeight());
|
||||
glUniform1i(this->_uniformRenderFlipped, (isRenderingFlipped) ? GL_TRUE : GL_FALSE);
|
||||
this->_needUpdateViewport = false;
|
||||
}
|
||||
}
|
||||
|
@ -7156,7 +7231,15 @@ void OGLDisplayLayer::RenderOGL()
|
|||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
if (isRenderingFlipped)
|
||||
{
|
||||
glOrtho(-w/2.0, -w/2.0 + w, -h/2.0 + h, -h/2.0, -1.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glOrtho(-w/2.0, -w/2.0 + w, -h/2.0, -h/2.0 + h, -1.0, 1.0);
|
||||
}
|
||||
|
||||
this->_needUpdateViewport = false;
|
||||
}
|
||||
|
|
|
@ -212,6 +212,7 @@ protected:
|
|||
GLint _uniformAngleDegrees;
|
||||
GLint _uniformScalar;
|
||||
GLint _uniformViewSize;
|
||||
GLint _uniformRenderFlipped;
|
||||
|
||||
void UploadVerticesOGL();
|
||||
void UploadTexCoordsOGL();
|
||||
|
@ -257,6 +258,7 @@ protected:
|
|||
GLint _uniformAngleDegrees;
|
||||
GLint _uniformScalar;
|
||||
GLint _uniformViewSize;
|
||||
GLint _uniformRenderFlipped;
|
||||
|
||||
public:
|
||||
virtual ~OGLVideoLayer() {};
|
||||
|
@ -268,7 +270,7 @@ public:
|
|||
virtual bool IsVisible();
|
||||
virtual void SetVisibility(const bool visibleState);
|
||||
|
||||
virtual void RenderOGL() = 0;
|
||||
virtual void RenderOGL(bool isRenderingFlipped) = 0;
|
||||
virtual void FinishOGL(const u8 bufferIndex) {};
|
||||
};
|
||||
|
||||
|
@ -292,7 +294,7 @@ public:
|
|||
|
||||
void CopyHUDFont(const FT_Face &fontFace, const size_t glyphSize, const size_t glyphTileSize, GlyphInfo *glyphInfo);
|
||||
|
||||
virtual void RenderOGL();
|
||||
virtual void RenderOGL(bool isRenderingFlipped);
|
||||
};
|
||||
|
||||
class OGLDisplayLayer : public OGLVideoLayer
|
||||
|
@ -324,7 +326,7 @@ public:
|
|||
|
||||
void LoadNativeDisplayByID_OGL(const NDSDisplayID displayID);
|
||||
void ProcessOGL();
|
||||
virtual void RenderOGL();
|
||||
virtual void RenderOGL(bool isRenderingFlipped);
|
||||
virtual void FinishOGL(const u8 bufferIndex);
|
||||
};
|
||||
|
||||
|
@ -381,6 +383,7 @@ protected:
|
|||
bool _hasOGLPixelScaler;
|
||||
std::vector<OGLVideoLayer *> *_layerList;
|
||||
GLuint _texCPUFilterDstID[2];
|
||||
GLuint _fboFrameCopyID;
|
||||
|
||||
void _UpdateViewport();
|
||||
|
||||
|
@ -419,8 +422,9 @@ public:
|
|||
|
||||
// Client view interface
|
||||
virtual void ProcessDisplays();
|
||||
virtual void FinishFrameAtIndex(const u8 bufferIndex);
|
||||
virtual void RenderViewOGL();
|
||||
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
|
||||
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);;
|
||||
virtual void RenderFrameOGL(bool isRenderingFlipped);
|
||||
virtual void LockDisplayTextures();
|
||||
virtual void UnlockDisplayTextures();
|
||||
};
|
||||
|
|
|
@ -170,6 +170,7 @@
|
|||
|
||||
- (void) setScaleFactor:(float)theScaleFactor;
|
||||
- (void) hudUpdate;
|
||||
- (NSImage *) copyImageFromView;
|
||||
- (NSImage *) image;
|
||||
- (NSBitmapImageRep *) bitmapImageRep;
|
||||
|
||||
|
|
|
@ -1140,7 +1140,7 @@
|
|||
|
||||
- (void) handleCopyToPasteboard
|
||||
{
|
||||
NSImage *screenshot = [self image];
|
||||
NSImage *screenshot = [self copyImageFromView];
|
||||
if (screenshot == nil)
|
||||
{
|
||||
return;
|
||||
|
@ -1188,6 +1188,44 @@
|
|||
OSSpinLockUnlock(&spinlockNDSFrameInfo);
|
||||
}
|
||||
|
||||
- (NSImage *) copyImageFromView
|
||||
{
|
||||
NSSize viewSize = NSMakeSize(_cdv->GetViewProperties().clientWidth, _cdv->GetViewProperties().clientHeight);
|
||||
NSUInteger w = viewSize.width;
|
||||
NSUInteger h = viewSize.height;
|
||||
|
||||
NSImage *newImage = [[NSImage alloc] initWithSize:viewSize];
|
||||
if (newImage == nil)
|
||||
{
|
||||
return newImage;
|
||||
}
|
||||
|
||||
// Render the frame in an NSBitmapImageRep
|
||||
NSBitmapImageRep *newImageRep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||
pixelsWide:w
|
||||
pixelsHigh:h
|
||||
bitsPerSample:8
|
||||
samplesPerPixel:4
|
||||
hasAlpha:YES
|
||||
isPlanar:NO
|
||||
colorSpaceName:NSCalibratedRGBColorSpace
|
||||
bytesPerRow:w * 4
|
||||
bitsPerPixel:32] autorelease];
|
||||
if (newImageRep == nil)
|
||||
{
|
||||
[newImage release];
|
||||
newImage = nil;
|
||||
return newImage;
|
||||
}
|
||||
|
||||
_cdv->CopyFrameToBuffer((uint32_t *)[newImageRep bitmapData]);
|
||||
|
||||
// Attach the rendered frame to the NSImageRep
|
||||
[newImage addRepresentation:newImageRep];
|
||||
|
||||
return [newImage autorelease];
|
||||
}
|
||||
|
||||
- (NSImage *) image
|
||||
{
|
||||
pthread_rwlock_rdlock(self.rwlockProducer);
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
id<MTLComputePipelineState> _fetch888Pipeline;
|
||||
id<MTLComputePipelineState> deposterizePipeline;
|
||||
id<MTLRenderPipelineState> hudPipeline;
|
||||
id<MTLRenderPipelineState> hudRGBAPipeline;
|
||||
|
||||
id<MTLBlitCommandEncoder> _fetchEncoder;
|
||||
|
||||
|
@ -109,6 +110,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
|
||||
@property (readonly, nonatomic) id<MTLComputePipelineState> deposterizePipeline;
|
||||
@property (readonly, nonatomic) id<MTLRenderPipelineState> hudPipeline;
|
||||
@property (readonly, nonatomic) id<MTLRenderPipelineState> hudRGBAPipeline;
|
||||
@property (readonly, nonatomic) id<MTLSamplerState> samplerHUDBox;
|
||||
@property (readonly, nonatomic) id<MTLSamplerState> samplerHUDText;
|
||||
|
||||
|
@ -162,6 +164,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
MTLRenderPassColorAttachmentDescriptor *colorAttachment0Desc;
|
||||
id<MTLComputePipelineState> pixelScalePipeline;
|
||||
id<MTLRenderPipelineState> displayOutputPipeline;
|
||||
id<MTLRenderPipelineState> displayRGBAOutputPipeline;
|
||||
|
||||
id<MTLBuffer> _cdvPropertiesBuffer;
|
||||
id<MTLBuffer> _displayVtxPositionBuffer;
|
||||
|
@ -203,6 +206,7 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
@property (readonly, nonatomic) MTLRenderPassColorAttachmentDescriptor *colorAttachment0Desc;
|
||||
@property (retain) id<MTLComputePipelineState> pixelScalePipeline;
|
||||
@property (retain) id<MTLRenderPipelineState> displayOutputPipeline;
|
||||
@property (retain) id<MTLRenderPipelineState> displayRGBAOutputPipeline;
|
||||
@property (retain) id<MTLBuffer> bufCPUFilterSrcMain;
|
||||
@property (retain) id<MTLBuffer> bufCPUFilterSrcTouch;
|
||||
@property (retain) id<MTLBuffer> bufCPUFilterDstMain;
|
||||
|
@ -223,6 +227,10 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
|
|||
- (void) copyHUDFontUsingFace:(const FT_Face &)fontFace size:(const size_t)glyphSize tileSize:(const size_t)glyphTileSize info:(GlyphInfo *)glyphInfo;
|
||||
- (void) processDisplays;
|
||||
- (void) updateRenderBuffers;
|
||||
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||
displayPipelineState:(id<MTLRenderPipelineState>)displayPipelineState
|
||||
hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState;
|
||||
- (void) renderAndDownloadToBuffer:(uint32_t *)dstBuffer;
|
||||
- (void) renderAndFlushDrawable;
|
||||
|
||||
@end
|
||||
|
@ -287,6 +295,8 @@ public:
|
|||
virtual void ProcessDisplays();
|
||||
virtual void UpdateView();
|
||||
virtual void FlushView();
|
||||
|
||||
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
@synthesize deposterizePipeline;
|
||||
@synthesize hudPipeline;
|
||||
@synthesize hudRGBAPipeline;
|
||||
@synthesize samplerHUDBox;
|
||||
@synthesize samplerHUDText;
|
||||
|
||||
|
@ -109,20 +110,24 @@
|
|||
deposterizeThreadGroupsPerGrid = fetchThreadGroupsPerGridNative;
|
||||
|
||||
MTLRenderPipelineDescriptor *hudPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatBGRA8Unorm];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setBlendingEnabled:YES];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setRgbBlendOperation:MTLBlendOperationAdd];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setAlphaBlendOperation:MTLBlendOperationAdd];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setSourceRGBBlendFactor:MTLBlendFactorSourceAlpha];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setSourceAlphaBlendFactor:MTLBlendFactorSourceAlpha];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setSourceAlphaBlendFactor:MTLBlendFactorZero];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setDestinationRGBBlendFactor:MTLBlendFactorOneMinusSourceAlpha];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setDestinationAlphaBlendFactor:MTLBlendFactorOneMinusSourceAlpha];
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setDestinationAlphaBlendFactor:MTLBlendFactorOne];
|
||||
|
||||
id<MTLFunction> hudFragmentFunction = [defaultLibrary newFunctionWithName:@"hud_fragment"];
|
||||
[hudPipelineDesc setVertexFunction:[defaultLibrary newFunctionWithName:@"hud_vertex"]];
|
||||
[hudPipelineDesc setFragmentFunction:hudFragmentFunction];
|
||||
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatBGRA8Unorm];
|
||||
hudPipeline = [[device newRenderPipelineStateWithDescriptor:hudPipelineDesc error:nil] retain];
|
||||
|
||||
[[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatRGBA8Unorm];
|
||||
hudRGBAPipeline = [[device newRenderPipelineStateWithDescriptor:hudPipelineDesc error:nil] retain];
|
||||
|
||||
[hudPipelineDesc release];
|
||||
|
||||
hudIndexBuffer = [[device newBufferWithLength:(sizeof(uint16_t) * HUD_TOTAL_ELEMENTS * 6) options:MTLResourceStorageModeManaged] retain];
|
||||
|
@ -274,6 +279,7 @@
|
|||
[_fetch888Pipeline release];
|
||||
[deposterizePipeline release];
|
||||
[hudPipeline release];
|
||||
[hudRGBAPipeline release];
|
||||
[hudIndexBuffer release];
|
||||
|
||||
[_bufMasterBrightMode[NDSDisplayID_Main] release];
|
||||
|
@ -728,6 +734,7 @@
|
|||
@synthesize colorAttachment0Desc;
|
||||
@synthesize pixelScalePipeline;
|
||||
@synthesize displayOutputPipeline;
|
||||
@synthesize displayRGBAOutputPipeline;
|
||||
@synthesize bufCPUFilterSrcMain;
|
||||
@synthesize bufCPUFilterSrcTouch;
|
||||
@synthesize bufCPUFilterDstMain;
|
||||
|
@ -764,6 +771,7 @@
|
|||
|
||||
pixelScalePipeline = nil;
|
||||
displayOutputPipeline = nil;
|
||||
displayRGBAOutputPipeline = nil;
|
||||
|
||||
_cdvPropertiesBuffer = nil;
|
||||
_displayVtxPositionBuffer = nil;
|
||||
|
@ -828,6 +836,7 @@
|
|||
[[self colorAttachment0Desc] setTexture:nil];
|
||||
[self setPixelScalePipeline:nil];
|
||||
[self setDisplayOutputPipeline:nil];
|
||||
[self setDisplayRGBAOutputPipeline:nil];
|
||||
[self setTexHUDCharMap:nil];
|
||||
|
||||
[self setSharedData:nil];
|
||||
|
@ -996,7 +1005,6 @@
|
|||
- (void) setOutputFilter:(OutputFilterTypeID)filterID
|
||||
{
|
||||
MTLRenderPipelineDescriptor *outputPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
[[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:[self pixelFormat]];
|
||||
[outputPipelineDesc setAlphaToOneEnabled:YES];
|
||||
|
||||
switch (filterID)
|
||||
|
@ -1033,7 +1041,12 @@
|
|||
break;
|
||||
}
|
||||
|
||||
[[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:[self pixelFormat]];
|
||||
[self setDisplayOutputPipeline:[[self device] newRenderPipelineStateWithDescriptor:outputPipelineDesc error:nil]];
|
||||
|
||||
[[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatRGBA8Unorm];
|
||||
[self setDisplayRGBAOutputPipeline:[[self device] newRenderPipelineStateWithDescriptor:outputPipelineDesc error:nil]];
|
||||
|
||||
[outputPipelineDesc release];
|
||||
}
|
||||
|
||||
|
@ -1047,12 +1060,16 @@
|
|||
[self setDevice:[sharedData device]];
|
||||
|
||||
MTLRenderPipelineDescriptor *outputPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
[[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:[self pixelFormat]];
|
||||
[outputPipelineDesc setAlphaToOneEnabled:YES];
|
||||
[outputPipelineDesc setVertexFunction:[[sharedData defaultLibrary] newFunctionWithName:@"display_output_vertex"]];
|
||||
[outputPipelineDesc setFragmentFunction:[[sharedData defaultLibrary] newFunctionWithName:@"output_filter_bilinear"]];
|
||||
|
||||
[[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:[self pixelFormat]];
|
||||
displayOutputPipeline = [[[self device] newRenderPipelineStateWithDescriptor:outputPipelineDesc error:nil] retain];
|
||||
|
||||
[[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatRGBA8Unorm];
|
||||
displayRGBAOutputPipeline = [[[self device] newRenderPipelineStateWithDescriptor:outputPipelineDesc error:nil] retain];
|
||||
|
||||
[outputPipelineDesc release];
|
||||
|
||||
_cdvPropertiesBuffer = [[[self device] newBufferWithLength:sizeof(DisplayViewShaderProperties) options:MTLResourceStorageModeManaged] retain];
|
||||
|
@ -1581,31 +1598,24 @@
|
|||
pthread_mutex_unlock(&_mutexBufferUpdate);
|
||||
}
|
||||
|
||||
- (void) renderAndFlushDrawable
|
||||
- (void) renderForCommandBuffer:(id<MTLCommandBuffer>)cb
|
||||
displayPipelineState:(id<MTLRenderPipelineState>)displayPipelineState
|
||||
hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
pthread_mutex_lock(&_mutexDisplayTextureUpdate);
|
||||
pthread_mutex_lock(&_mutexBufferUpdate);
|
||||
|
||||
// Now that everything is set up, go ahead and draw everything.
|
||||
id<CAMetalDrawable> layerDrawable = [self nextDrawable];
|
||||
[colorAttachment0Desc setTexture:[layerDrawable texture]];
|
||||
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
||||
id<MTLRenderCommandEncoder> ce = [cb renderCommandEncoderWithDescriptor:_outputRenderPassDesc];
|
||||
id<MTLRenderCommandEncoder> rce = [cb renderCommandEncoderWithDescriptor:_outputRenderPassDesc];
|
||||
|
||||
if (_needEncodeViewport)
|
||||
{
|
||||
[ce setViewport:_newViewport];
|
||||
[rce setViewport:_newViewport];
|
||||
}
|
||||
|
||||
// Draw the NDS displays.
|
||||
if (_willDrawDisplays)
|
||||
{
|
||||
[ce setRenderPipelineState:[self displayOutputPipeline]];
|
||||
[ce setVertexBuffer:_displayVtxPositionBuffer offset:0 atIndex:0];
|
||||
[ce setVertexBuffer:_displayTexCoordBuffer offset:0 atIndex:1];
|
||||
[ce setVertexBuffer:_cdvPropertiesBuffer offset:0 atIndex:2];
|
||||
[rce setRenderPipelineState:displayPipelineState];
|
||||
[rce setVertexBuffer:_displayVtxPositionBuffer offset:0 atIndex:0];
|
||||
[rce setVertexBuffer:_displayTexCoordBuffer offset:0 atIndex:1];
|
||||
[rce setVertexBuffer:_cdvPropertiesBuffer offset:0 atIndex:2];
|
||||
|
||||
switch (_cdv->GetViewProperties().mode)
|
||||
{
|
||||
|
@ -1613,8 +1623,8 @@
|
|||
{
|
||||
if (_cdv->IsSelectedDisplayEnabled(NDSDisplayID_Main))
|
||||
{
|
||||
[ce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Main] atIndex:0];
|
||||
[ce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
[rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Main] atIndex:0];
|
||||
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1623,8 +1633,8 @@
|
|||
{
|
||||
if (_cdv->IsSelectedDisplayEnabled(NDSDisplayID_Touch))
|
||||
{
|
||||
[ce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Touch] atIndex:0];
|
||||
[ce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:4 vertexCount:4];
|
||||
[rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Touch] atIndex:0];
|
||||
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:4 vertexCount:4];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1642,8 +1652,8 @@
|
|||
{
|
||||
if (_cdv->IsSelectedDisplayEnabled(majorDisplayID))
|
||||
{
|
||||
[ce setFragmentTexture:_texDisplayOutput[majorDisplayID] atIndex:0];
|
||||
[ce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:majorDisplayVtx vertexCount:4];
|
||||
[rce setFragmentTexture:_texDisplayOutput[majorDisplayID] atIndex:0];
|
||||
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:majorDisplayVtx vertexCount:4];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1654,14 +1664,14 @@
|
|||
|
||||
if (_cdv->IsSelectedDisplayEnabled(NDSDisplayID_Main))
|
||||
{
|
||||
[ce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Main] atIndex:0];
|
||||
[ce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
[rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Main] atIndex:0];
|
||||
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
}
|
||||
|
||||
if (_cdv->IsSelectedDisplayEnabled(NDSDisplayID_Touch))
|
||||
{
|
||||
[ce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Touch] atIndex:0];
|
||||
[ce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:4 vertexCount:4];
|
||||
[rce setFragmentTexture:_texDisplayOutput[NDSDisplayID_Touch] atIndex:0];
|
||||
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:4 vertexCount:4];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1675,29 +1685,29 @@
|
|||
{
|
||||
uint8_t isScreenOverlay = 0;
|
||||
|
||||
[ce setRenderPipelineState:[sharedData hudPipeline]];
|
||||
[ce setVertexBuffer:_hudVtxPositionBuffer offset:0 atIndex:0];
|
||||
[ce setVertexBuffer:_hudVtxColorBuffer offset:0 atIndex:1];
|
||||
[ce setVertexBuffer:_hudTexCoordBuffer offset:0 atIndex:2];
|
||||
[ce setVertexBuffer:_cdvPropertiesBuffer offset:0 atIndex:3];
|
||||
[ce setFragmentTexture:[self texHUDCharMap] atIndex:0];
|
||||
[rce setRenderPipelineState:hudPipelineState];
|
||||
[rce setVertexBuffer:_hudVtxPositionBuffer offset:0 atIndex:0];
|
||||
[rce setVertexBuffer:_hudVtxColorBuffer offset:0 atIndex:1];
|
||||
[rce setVertexBuffer:_hudTexCoordBuffer offset:0 atIndex:2];
|
||||
[rce setVertexBuffer:_cdvPropertiesBuffer offset:0 atIndex:3];
|
||||
[rce setFragmentTexture:[self texHUDCharMap] atIndex:0];
|
||||
|
||||
// First, draw the inputs.
|
||||
if (_willDrawHUDInput)
|
||||
{
|
||||
isScreenOverlay = 1;
|
||||
[ce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4];
|
||||
[ce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0];
|
||||
[ce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
[rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4];
|
||||
[rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0];
|
||||
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:_hudTouchLineLength * 6
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:[sharedData hudIndexBuffer]
|
||||
indexBufferOffset:(_hudStringLength + HUD_INPUT_ELEMENT_LENGTH) * 6 * sizeof(uint16_t)];
|
||||
|
||||
isScreenOverlay = 0;
|
||||
[ce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4];
|
||||
[ce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0];
|
||||
[ce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
[rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4];
|
||||
[rce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0];
|
||||
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:HUD_INPUT_ELEMENT_LENGTH * 6
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:[sharedData hudIndexBuffer]
|
||||
|
@ -1705,24 +1715,96 @@
|
|||
}
|
||||
|
||||
// Next, draw the backing text box.
|
||||
[ce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4];
|
||||
[ce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0];
|
||||
[ce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
[rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4];
|
||||
[rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0];
|
||||
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:6
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:[sharedData hudIndexBuffer]
|
||||
indexBufferOffset:0];
|
||||
|
||||
// Finally, draw each character inside the box.
|
||||
[ce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0];
|
||||
[ce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
[rce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0];
|
||||
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:(_hudStringLength - 1) * 6
|
||||
indexType:MTLIndexTypeUInt16
|
||||
indexBuffer:[sharedData hudIndexBuffer]
|
||||
indexBufferOffset:6 * sizeof(uint16_t)];
|
||||
}
|
||||
|
||||
[ce endEncoding];
|
||||
[rce endEncoding];
|
||||
}
|
||||
|
||||
- (void) renderAndDownloadToBuffer:(uint32_t *)dstBuffer
|
||||
{
|
||||
const size_t clientWidth = _cdv->GetViewProperties().clientWidth;
|
||||
const size_t clientHeight = _cdv->GetViewProperties().clientHeight;
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
MTLTextureDescriptor *texRenderDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||
width:clientWidth
|
||||
height:clientHeight
|
||||
mipmapped:NO];
|
||||
[texRenderDesc setResourceOptions:MTLResourceStorageModePrivate];
|
||||
[texRenderDesc setStorageMode:MTLStorageModePrivate];
|
||||
[texRenderDesc setUsage:MTLTextureUsageRenderTarget];
|
||||
|
||||
id<MTLTexture> texRender = [[[self device] newTextureWithDescriptor:texRenderDesc] retain];
|
||||
id<MTLBuffer> dstMTLBuffer = [[[self device] newBufferWithLength:clientWidth * clientHeight * sizeof(uint32_t) options:MTLResourceStorageModeManaged] retain];
|
||||
|
||||
pthread_mutex_lock(&_mutexDisplayTextureUpdate);
|
||||
pthread_mutex_lock(&_mutexBufferUpdate);
|
||||
|
||||
// Now that everything is set up, go ahead and draw everything.
|
||||
[colorAttachment0Desc setTexture:texRender];
|
||||
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
||||
|
||||
[self renderForCommandBuffer:cb displayPipelineState:[self displayRGBAOutputPipeline] hudPipelineState:[sharedData hudRGBAPipeline]];
|
||||
|
||||
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
|
||||
|
||||
[bce copyFromTexture:texRender
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(0, 0, 0)
|
||||
sourceSize:MTLSizeMake(clientWidth, clientHeight, 1)
|
||||
toBuffer:dstMTLBuffer
|
||||
destinationOffset:0
|
||||
destinationBytesPerRow:clientWidth * sizeof(uint32_t)
|
||||
destinationBytesPerImage:clientWidth * clientHeight * sizeof(uint32_t)];
|
||||
|
||||
[bce synchronizeResource:dstMTLBuffer];
|
||||
[bce endEncoding];
|
||||
|
||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
pthread_mutex_unlock(&_mutexBufferUpdate);
|
||||
pthread_mutex_unlock(&_mutexDisplayTextureUpdate);
|
||||
|
||||
memcpy(dstBuffer, [dstMTLBuffer contents], clientWidth * clientHeight * sizeof(uint32_t));
|
||||
|
||||
[texRender release];
|
||||
[dstMTLBuffer release];
|
||||
}];
|
||||
|
||||
[cb commit];
|
||||
[cb waitUntilCompleted];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) renderAndFlushDrawable
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
pthread_mutex_lock(&_mutexDisplayTextureUpdate);
|
||||
pthread_mutex_lock(&_mutexBufferUpdate);
|
||||
|
||||
// Now that everything is set up, go ahead and draw everything.
|
||||
id<CAMetalDrawable> layerDrawable = [self nextDrawable];
|
||||
[colorAttachment0Desc setTexture:[layerDrawable texture]];
|
||||
id<MTLCommandBuffer> cb = [self newCommandBuffer];
|
||||
|
||||
[self renderForCommandBuffer:cb displayPipelineState:[self displayOutputPipeline] hudPipelineState:[sharedData hudPipeline]];
|
||||
|
||||
[cb presentDrawable:layerDrawable];
|
||||
[cb addCompletedHandler:^(id<MTLCommandBuffer> block) {
|
||||
|
@ -1999,6 +2081,11 @@ void MacMetalDisplayView::FlushView()
|
|||
[(DisplayViewMetalLayer *)this->GetFrontendLayer() renderAndFlushDrawable];
|
||||
}
|
||||
|
||||
void MacMetalDisplayView::CopyFrameToBuffer(uint32_t *dstBuffer)
|
||||
{
|
||||
[(DisplayViewMetalLayer *)this->GetFrontendLayer() renderAndDownloadToBuffer:dstBuffer];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
void SetupHQnxLUTs_Metal(id<MTLDevice> &device, id<MTLTexture> &texLQ2xLUT, id<MTLTexture> &texHQ2xLUT, id<MTLTexture> &texHQ3xLUT, id<MTLTexture> &texHQ4xLUT)
|
||||
{
|
||||
|
|
|
@ -100,7 +100,8 @@ public:
|
|||
virtual void ProcessDisplays();
|
||||
virtual void UpdateView();
|
||||
virtual void FlushView();
|
||||
virtual void FinishFrameAtIndex(const u8 bufferIndex);
|
||||
virtual void CopyFrameToBuffer(uint32_t *dstBuffer);
|
||||
virtual void FinishFrameAtIndex(const uint8_t bufferIndex);
|
||||
virtual void LockDisplayTextures();
|
||||
virtual void UnlockDisplayTextures();
|
||||
};
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
{
|
||||
CGLSetCurrentContext(glContext);
|
||||
CGLLockContext(glContext);
|
||||
_cdv->RenderViewOGL();
|
||||
_cdv->RenderFrameOGL(false);
|
||||
[super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
|
||||
CGLUnlockContext(glContext);
|
||||
}
|
||||
|
@ -447,12 +447,20 @@ void MacOGLDisplayView::FlushView()
|
|||
|
||||
CGLLockContext(this->_context);
|
||||
CGLSetCurrentContext(this->_context);
|
||||
this->RenderViewOGL();
|
||||
this->RenderFrameOGL(false);
|
||||
CGLFlushDrawable(this->_context);
|
||||
CGLUnlockContext(this->_context);
|
||||
}
|
||||
|
||||
void MacOGLDisplayView::FinishFrameAtIndex(const u8 bufferIndex)
|
||||
void MacOGLDisplayView::CopyFrameToBuffer(uint32_t *dstBuffer)
|
||||
{
|
||||
CGLLockContext(this->_context);
|
||||
CGLSetCurrentContext(this->_context);
|
||||
this->OGLVideoOutput::CopyFrameToBuffer(dstBuffer);
|
||||
CGLUnlockContext(this->_context);
|
||||
}
|
||||
|
||||
void MacOGLDisplayView::FinishFrameAtIndex(const uint8_t bufferIndex)
|
||||
{
|
||||
CGLLockContext(this->_context);
|
||||
CGLSetCurrentContext(this->_context);
|
||||
|
|
Loading…
Reference in New Issue