Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/leadedge/Spout2
Browse files Browse the repository at this point in the history
  • Loading branch information
leadedge committed Jul 27, 2021
2 parents 09790be + f859d1a commit 98263bf
Show file tree
Hide file tree
Showing 65 changed files with 844 additions and 266 deletions.
Binary file modified BUILD/Binaries/Win32/Spout.dll
Binary file not shown.
Binary file modified BUILD/Binaries/Win32/Spout.lib
Binary file not shown.
Binary file modified BUILD/Binaries/Win32/SpoutDX.dll
Binary file not shown.
Binary file modified BUILD/Binaries/Win32/SpoutDX.lib
Binary file not shown.
Binary file modified BUILD/Binaries/Win32/SpoutLibrary.dll
Binary file not shown.
Binary file modified BUILD/Binaries/Win32/SpoutLibrary.lib
Binary file not shown.
Binary file modified BUILD/Binaries/Win32/Spout_static.lib
Binary file not shown.
Binary file modified BUILD/Binaries/x64/Spout.dll
Binary file not shown.
Binary file modified BUILD/Binaries/x64/Spout.lib
Binary file not shown.
Binary file modified BUILD/Binaries/x64/SpoutDX.dll
Binary file not shown.
Binary file modified BUILD/Binaries/x64/SpoutDX.lib
Binary file not shown.
Binary file modified BUILD/Binaries/x64/SpoutLibrary.dll
Binary file not shown.
Binary file modified BUILD/Binaries/x64/SpoutLibrary.lib
Binary file not shown.
Binary file modified BUILD/Binaries/x64/Spout_static.lib
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,21 @@ void ofApp::draw() {
// Send fbo
// The fbo must be bound for read.
// The invert option is false because the fbo is already flipped in y.
// The fbo size can be different to the application window for a fixed sender size.
// Disable the code in WindowResized() if you want this.
sender.SendFbo(myFbo.getId(), senderwidth, senderheight, false);

myFbo.end();
// - - - - - - - - - - - - - - - -

// Send texture (fastest method)
// Show the result sized to the application window
myFbo.draw(0, 0, ofGetWidth(), ofGetHeight());

// Send the application window (default framebuffer).
// The window width and height must be used if myFbo size is different.
// sender.SendFbo(0, ofGetWidth(), ofGetHeight(), false);

// Send texture
// sender.SendTexture(myFbo.getTexture().getTextureData().textureID,
// myFbo.getTexture().getTextureData().textureTarget,
// senderwidth, senderheight, false);
Expand All @@ -204,9 +213,6 @@ void ofApp::draw() {
// myFbo.readToPixels(myPixels); // readToPixels is slow - but this is just an example
// sender.SendImage(myPixels.getData(),senderwidth, senderheight, GL_RGBA, false);

// Show the result sized to the application window
myFbo.draw(0, 0, ofGetWidth(), ofGetHeight());

// Show what it is sending
ofSetColor(255);
std::string str = "Sending as : ";
Expand Down
14 changes: 10 additions & 4 deletions SPOUTSDK/Examples/ofSpoutExample/src/ofApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,21 @@ void ofApp::draw() {
// Send fbo
// The fbo must be bound for read.
// The invert option is false because the fbo is already flipped in y.
// The fbo size can be different to the application window for a fixed sender size.
// Disable the code in WindowResized() if you want this.
sender.SendFbo(myFbo.getId(), senderwidth, senderheight, false);

myFbo.end();
// - - - - - - - - - - - - - - - -

// Send texture (fastest method)
// Show the result sized to the application window
myFbo.draw(0, 0, ofGetWidth(), ofGetHeight());

// Send the application window (default framebuffer).
// The window width and height must be used if myFbo size is different.
// sender.SendFbo(0, ofGetWidth(), ofGetHeight(), false);

// Send texture
// sender.SendTexture(myFbo.getTexture().getTextureData().textureID,
// myFbo.getTexture().getTextureData().textureTarget,
// senderwidth, senderheight, false);
Expand All @@ -204,9 +213,6 @@ void ofApp::draw() {
// myFbo.readToPixels(myPixels); // readToPixels is slow - but this is just an example
// sender.SendImage(myPixels.getData(),senderwidth, senderheight, GL_RGBA, false);

// Show the result sized to the application window
myFbo.draw(0, 0, ofGetWidth(), ofGetHeight());

// Show what it is sending
ofSetColor(255);
std::string str = "Sending as : ";
Expand Down
Binary file not shown.
Binary file modified SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial07.exe
Binary file not shown.
120 changes: 74 additions & 46 deletions SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@
// 29.04.21 - Change IsFrameNew() to return frame class global.
// 10.06.21 - Remove Memoryshare struct and replace with SpoutSharedMemory object
// Update data functions
// 01.07.21 - ReadPixelData - add swap r/b argument
// 04.07.21 - GetSenderCount, GetSender pass through to sendernames class.
// - Destructor : do not release receiver connected sender name.
// 20.07.21 - Correct GetSender to include max size
// Add SendBackBuffer
//
// ====================================================================================
/*
Expand Down Expand Up @@ -170,10 +175,20 @@ spoutDX::spoutDX()

spoutDX::~spoutDX()
{
ReleaseSender();
ReleaseReceiver();
if (m_bConnected) {
// Receiver object
// Do not release the connected sender name
ReleaseReceiver();
}
else {
// Sender object (or receiver not connected. i.e. not initialized)
// Release the sender name if initialized
ReleaseSender();
}

CloseDirectX11();
memorybuffer.Close();

}

//---------------------------------------------------------
Expand Down Expand Up @@ -366,6 +381,31 @@ void spoutDX::ReleaseSender()

}

//---------------------------------------------------------
// Function: SendBackbuffer
// Get the swap chain's back buffer to a texture for sending.
// Assumes a single render target view.
// Refer to SendTexture for compatible formats.
//
bool spoutDX::SendBackBuffer()
{
if (m_pImmediateContext) {
ID3D11RenderTargetView *rendertarget = nullptr;
m_pImmediateContext->OMGetRenderTargets(1, &rendertarget, nullptr);
if (rendertarget) {
ID3D11Resource* pBackBufferResource = nullptr;
rendertarget->GetResource(&pBackBufferResource);
if (pBackBufferResource) {
// SendTexture checks for DirectX initialization
// and handles sender creation and re-sizing.
SendTexture(reinterpret_cast<ID3D11Texture2D*>(pBackBufferResource));
return true;
}
}
}
return false;
}

//---------------------------------------------------------
// Function: SendTexture
// Send DirectX11 texture
Expand Down Expand Up @@ -693,7 +733,7 @@ bool spoutDX::ReceiveImage(unsigned char * pixels,
// Copy from the sender's shared texture to the first staging texture
m_pImmediateContext->CopyResource(m_pStaging[m_Index], m_pSharedTexture);
// Map and read from the second while the first is occupied
ReadPixelData(m_pStaging[m_NextIndex], pixels, width, height, bRGB, bInvert);
ReadPixelData(m_pStaging[m_NextIndex], pixels, width, height, bRGB, bInvert, false);
}
// Allow access to the shared texture
frame.AllowTextureAccess(m_pSharedTexture);
Expand Down Expand Up @@ -888,41 +928,15 @@ bool spoutDX::WaitFrameSync(const char *SenderName, DWORD dwTimeout)
// Number of senders
int spoutDX::GetSenderCount()
{
std::set<std::string> SenderNameSet;
if (sendernames.GetSenderNames(&SenderNameSet)) {
return((int)SenderNameSet.size());
}
return 0;
return sendernames.GetSenderCount();
}

//---------------------------------------------------------
// Function: GetSender
// Sender item name in the sender names set
bool spoutDX::GetSender(int index, char* sendername, int sendernameMaxSize)
{
std::set<std::string> SenderNameSet;
std::set<std::string>::iterator iter;
std::string namestring;
char name[256];
int i;

if (sendernames.GetSenderNames(&SenderNameSet)) {
if (SenderNameSet.size() < (unsigned int)index) {
return false;
}
i = 0;
for (iter = SenderNameSet.begin(); iter != SenderNameSet.end(); iter++) {
namestring = *iter; // the name string
strcpy_s(name, 256, namestring.c_str()); // the 256 byte name char array
if (i == index) {
strcpy_s(sendername, sendernameMaxSize, name); // the passed name char array
break;
}
i++;
}
return true;
}
return false;
return sendernames.GetSender(index, sendername, sendernameMaxSize);
}

//---------------------------------------------------------
Expand Down Expand Up @@ -1798,53 +1812,67 @@ void spoutDX::CreateReceiver(const char * SenderName, unsigned int width, unsign
//
// A class device and context must have been created using OpenDirectX11()
//
bool spoutDX::ReadPixelData(ID3D11Texture2D* pStagingTexture, unsigned char* pixels,
unsigned int width, unsigned int height, bool bRGB, bool bInvert)
// bRGB - pixel data is RGB instead of RGBA
// bInvert - flip the image
// bSwap - swap red/blue (BGRA/RGBA). Not available for re-sample
//
bool spoutDX::ReadPixelData(ID3D11Texture2D* pStagingSource, unsigned char* destpixels,
unsigned int width, unsigned int height, bool bRGB, bool bInvert, bool bSwap)
{
if (!m_pImmediateContext || !pStagingTexture || !pixels)
if (!m_pImmediateContext || !pStagingSource || !destpixels)
return false;

// Map the resource so we can access the pixels
// Map the staging texture resource so we can access the pixels
D3D11_MAPPED_SUBRESOURCE mappedSubResource;
// Make sure all commands are done before mapping the staging texture
m_pImmediateContext->Flush();
// Map waits for GPU access
HRESULT hr = m_pImmediateContext->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mappedSubResource);
HRESULT hr = m_pImmediateContext->Map(pStagingSource, 0, D3D11_MAP_READ, 0, &mappedSubResource);
if (SUCCEEDED(hr)) {

// Copy the staging texture pixels to the user buffer
if (!bRGB) {
// RGBA buffer
// RGBA pixel buffer
// TODO : test rgba-rgba resample
// TODO : rgba2bgraResample
if (width != m_Width || height != m_Height) {
spoutcopy.rgba2rgbaResample(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert);
spoutcopy.rgba2rgbaResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert);
}
else {
spoutcopy.rgba2rgba(mappedSubResource.pData, pixels, width, height, mappedSubResource.RowPitch, bInvert);
if(bSwap)
spoutcopy.rgba2bgra(mappedSubResource.pData, destpixels, width, height, mappedSubResource.RowPitch, bInvert);
else
spoutcopy.rgba2rgba(mappedSubResource.pData, destpixels, width, height, mappedSubResource.RowPitch, bInvert);
}
}
else if (m_dwFormat == 28) {
// RGB buffer
else if (m_dwFormat == 28) { // DXGI_FORMAT_R8G8B8A8_UNORM
// RGBA texture - RGB/BGR pixel buffer
// If the texture format is RGBA it has to be converted to BGR by the staging texture copy
if (width != m_Width || height != m_Height) {
spoutcopy.rgba2bgrResample(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert);
if(bSwap)
spoutcopy.rgba2rgbResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert);
else
spoutcopy.rgba2bgrResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert);
}
else {
spoutcopy.rgba2bgr(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert);
if (bSwap)
spoutcopy.rgba2rgb(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert);
else
spoutcopy.rgba2bgr(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert);
}
}
else {
// Used for SpoutCam to receive RGB images
if (width != m_Width || height != m_Height) {
spoutcopy.rgba2rgbResample(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert, m_bMirror, m_bSwapRB);
spoutcopy.rgba2rgbResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert, m_bMirror, m_bSwapRB);
}
else {
// Approx 5 msec at 1920x1080
spoutcopy.rgba2rgb(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert, m_bMirror, m_bSwapRB);
spoutcopy.rgba2rgb(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert, m_bMirror, m_bSwapRB);
}
}

m_pImmediateContext->Unmap(pStagingTexture, 0);
m_pImmediateContext->Unmap(pStagingSource, 0);

return true;
} // endif DX11 map OK
Expand Down
11 changes: 8 additions & 3 deletions SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class SPOUT_DLLEXP spoutDX {
void SetSenderFormat(DXGI_FORMAT format);
// Close sender and free resources
void ReleaseSender();
// Send the back buffer
bool SendBackBuffer();
// Send a texture
bool SendTexture(ID3D11Texture2D* pTexture);
// Send an image
Expand Down Expand Up @@ -199,7 +201,7 @@ class SPOUT_DLLEXP spoutDX {
bool CreateDX11texture(ID3D11Device* pd3dDevice,
unsigned int width, unsigned int height,
DXGI_FORMAT format, ID3D11Texture2D** ppTexture);

//
// Data sharing
//
Expand Down Expand Up @@ -268,8 +270,11 @@ protected :
bool ReceiveSenderData();
void CreateReceiver(const char * sendername, unsigned int width, unsigned int height, DWORD dwFormat);

// Read pixels via staging texture
bool ReadPixelData(ID3D11Texture2D* pStagingTexture, unsigned char* pixels, unsigned int width, unsigned int height, bool bRGB, bool bInvert);
// Read pixels from a staging texture
bool ReadPixelData(ID3D11Texture2D* pStagingSource, unsigned char* destpixels,
unsigned int width, unsigned int height, bool bRGB, bool bInvert, bool bSwap);

// Create staging textures
bool CheckStagingTextures(unsigned int width, unsigned int height, DWORD dwFormat = DXGI_FORMAT_B8G8R8A8_UNORM);
bool CreateDX11StagingTexture(unsigned int width, unsigned int height, DXGI_FORMAT format, ID3D11Texture2D** pStagingTexture);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,16 +333,10 @@ void D3D12HelloTriangle::OnRender()
sender.SendDX11Resource(m_wrappedBackBuffers[m_frameIndex].Get());

// Present the frame.
ThrowIfFailed(m_swapChain->Present(1, 0));
ThrowIfFailed(m_swapChain->Present(1, 0));

WaitForPreviousFrame();

//
// SPOUT - fps control
//
// "sender.HoldFps(60);" can be used to hold a target frame rate - e.g. 60 or 30fps.
// Here it's not required because "Present(1, 0)" synchronizes to vertical blank.


}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,6 @@ VOID Render()
// Present the backbuffer contents to the display
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);

//
// SPOUT - fps control
//
// Hold a target frame rate - e.g. 60 or 30fps
// This is not necessary if the application already has fps control.
// If frame count is enabled, receivers will detect the sender fps
// sender.HoldFps(30);

}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,6 @@ VOID Render()
// Present the backbuffer contents to the display
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);

//
// SPOUT - fps control
//
// Hold a target frame rate - e.g. 60 or 30fps
// This is not necessary if the application already has fps control.
// If frame count is enabled, receivers will detect the sender fps
// sender.HoldFps(30);

}


Expand Down
Loading

0 comments on commit 98263bf

Please sign in to comment.