190 lines
6.5 KiB
C++

//===============================================================================
// Copyright (c) 2014-2016 Advanced Micro Devices, Inc. All rights reserved.
//===============================================================================
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef _COMPCLIENT_H_INCLUDED_
#define _COMPCLIENT_H_INCLUDED_
#include <atlstr.h>
#include <strsafe.h>
#define BUFFER_SIZE 512 // bytes MAX buffer size
#define COMPRESS_DATA_HEADER_SIZE 4 // bytes offset until first data location in COMPRESS_DATA structure
#define REMOTE_AMD_COMPRESSOR "\\\\.\\pipe\\AMD_COMPRESS" // Shared Pipe name of remote connection
struct COMPRESS_DATA {
WORD cmd; // 2 Bytes
WORD data_size; // 2 Bytes
// Above bytes should add up to COMPRESS_DATA_HEADER_SIZE
union {
unsigned char data [BUFFER_SIZE];
float fdata[BUFFER_SIZE / sizeof(float)];
};
};
struct COMPRESS_ACK_DATA {
unsigned short cmd; // 2 Bytes
unsigned short data_size = 0; // 2 Bytes
};
class CompViewerClient {
public:
CompViewerClient() {
snprintf(m_strPipeName,128,REMOTE_AMD_COMPRESSOR);
m_hPipe = INVALID_HANDLE_VALUE;
memset(&m_data,0,sizeof(m_data));
}
~CompViewerClient() {
disconnect();
}
void disconnect() {
if (m_hPipe != INVALID_HANDLE_VALUE) {
// Close the pipe if opened.
CloseHandle(m_hPipe);
m_hPipe = INVALID_HANDLE_VALUE;
}
}
bool connect() {
if (m_hPipe != INVALID_HANDLE_VALUE) return true; // Already connected
bool connected = false;
while (TRUE) {
m_hPipe = CreateFileA(
m_strPipeName, // Pipe name
GENERIC_READ | // Read and write access
GENERIC_WRITE,
0, // No sharing
NULL, // Default security attributes
OPEN_EXISTING, // Opens existing pipe
0, // Default attributes
NULL); // No template file
// Break if the pipe handle is valid.
if (m_hPipe != INVALID_HANDLE_VALUE)
break;
if (// Exit if an error other than ERROR_PIPE_BUSY occurs
GetLastError() != ERROR_PIPE_BUSY
||
// All pipe instances are busy, so wait for 5 seconds
!WaitNamedPipeA(m_strPipeName, 5000)) {
m_error = GetLastError();
m_hPipe = INVALID_HANDLE_VALUE;
return false;
}
}
if (GetResponse()) {
connected = true;
} else {
disconnect();
}
return connected;
}
bool Connected() {
return (m_hPipe != INVALID_HANDLE_VALUE);
}
bool SendData(WORD Cmd, WORD DataSize, byte *Data, bool Respond = true) {
if (m_hPipe == INVALID_HANDLE_VALUE) return false; // not connected
if (DataSize > (BUFFER_SIZE - COMPRESS_DATA_HEADER_SIZE)) return false; // data size too big to handle!
m_data.cmd = Cmd; // Darw Source pixels
m_data.data_size = DataSize;
memcpy(m_data.data,Data,DataSize);
m_bResult = WriteFile( // Write to the pipe.
m_hPipe, // Handle of the pipe
&m_data, // Message to be written
m_data.data_size + COMPRESS_DATA_HEADER_SIZE, // Number of bytes to write
&m_cbBytesWritten, // Number of bytes written
NULL); // Not overlapped
if (!m_bResult/*Failed*/ || (m_data.data_size + (DWORD)COMPRESS_DATA_HEADER_SIZE) != m_cbBytesWritten/*Failed*/) {
m_error = GetLastError();
return false;
}
// reset data size as data has been sent
m_data.data_size = 0;
if (Respond)
GetResponse();
return true;
}
private:
bool GetResponse() {
if (m_hPipe == INVALID_HANDLE_VALUE) return false; // not connected
m_cbBytesRead = 0;
// Receive the response from the server.
m_cbReplyBytes = sizeof(COMPRESS_ACK_DATA);
do {
m_bResult = ReadFile( // Read from the pipe.
m_hPipe, // Handle of the pipe
&m_chReply, // Buffer to receive the reply
m_cbReplyBytes, // Size of buffer
&m_cbBytesRead, // Number of bytes read
NULL); // Not overlapped
if (!m_bResult && GetLastError() != ERROR_MORE_DATA) {
m_error = GetLastError();
break;
}
} while (!m_bResult); // Repeat loop if ERROR_MORE_DATA
return true;
}
protected:
// Prepare the pipe name
char m_strPipeName[128];
HANDLE m_hPipe;
DWORD m_error;
DWORD m_cbBytesWritten;
DWORD m_cbBytesRead, m_cbReplyBytes;
BOOL m_bResult;
public:
COMPRESS_ACK_DATA m_chReply;
COMPRESS_DATA m_data;
};
#endif