commit
8c316b46b8
@ -0,0 +1,3 @@
|
||||
[submodule "librfxcodec"]
|
||||
path = librfxcodec
|
||||
url = git://github.com/neutrinolabs/librfxcodec
|
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* FIFO implementation to store pointer to data struct
|
||||
*/
|
||||
|
||||
#include "fifo.h"
|
||||
#include "os_calls.h"
|
||||
|
||||
/**
|
||||
* Create new fifo data struct
|
||||
*
|
||||
* @return pointer to new FIFO or NULL if system out of memory
|
||||
*****************************************************************************/
|
||||
|
||||
FIFO * APP_CC
|
||||
fifo_create(void)
|
||||
{
|
||||
return (FIFO *) g_malloc(sizeof(FIFO), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete specified FIFO
|
||||
*****************************************************************************/
|
||||
|
||||
void APP_CC
|
||||
fifo_delete(FIFO *self)
|
||||
{
|
||||
USER_DATA *udp;
|
||||
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
if (!self->head)
|
||||
{
|
||||
/* FIFO is empty */
|
||||
g_free(self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->head == self->tail)
|
||||
{
|
||||
/* only one item in FIFO */
|
||||
if (self->auto_free)
|
||||
g_free(self->head->item);
|
||||
|
||||
g_free(self->head);
|
||||
g_free(self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* more then one item in FIFO */
|
||||
while (self->head)
|
||||
{
|
||||
udp = self->head;
|
||||
|
||||
if (self->auto_free)
|
||||
g_free(udp->item);
|
||||
|
||||
self->head = udp->next;
|
||||
g_free(udp);
|
||||
}
|
||||
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the specified FIFO
|
||||
*
|
||||
* @param self FIFO to operate on
|
||||
* @param item item to add to specified FIFO
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*****************************************************************************/
|
||||
|
||||
int APP_CC
|
||||
fifo_add_item(FIFO *self, void *item)
|
||||
{
|
||||
USER_DATA *udp;
|
||||
|
||||
if (!self || !item)
|
||||
return -1;
|
||||
|
||||
if ((udp = (USER_DATA *) g_malloc(sizeof(USER_DATA), 0)) == 0)
|
||||
return -1;
|
||||
|
||||
udp->item = item;
|
||||
udp->next = 0;
|
||||
|
||||
/* if fifo is empty, add to head */
|
||||
if (!self->head)
|
||||
{
|
||||
self->head = udp;
|
||||
self->tail = udp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add to tail */
|
||||
self->tail->next = udp;
|
||||
self->tail = udp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an item from top of FIFO
|
||||
*
|
||||
* @param self FIFO to operate on
|
||||
*
|
||||
* @return top item from FIFO or NULL if FIFO is empty
|
||||
*****************************************************************************/
|
||||
|
||||
void * APP_CC
|
||||
fifo_remove_item(FIFO *self)
|
||||
{
|
||||
void *item;
|
||||
USER_DATA *udp;
|
||||
|
||||
if (!self || !self->head)
|
||||
return 0;
|
||||
|
||||
if (self->head == self->tail)
|
||||
{
|
||||
/* only one item in FIFO */
|
||||
item = self->head->item;
|
||||
g_free(self->head);
|
||||
self->head = 0;
|
||||
self->tail = 0;
|
||||
return item;
|
||||
}
|
||||
|
||||
/* more then one item in FIFO */
|
||||
udp = self->head;
|
||||
item = self->head->item;
|
||||
self->head = self->head->next;
|
||||
g_free(udp);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return FIFO status
|
||||
*
|
||||
* @param self FIFO to operate on
|
||||
*
|
||||
* @return true if FIFO is empty, false otherwise
|
||||
*****************************************************************************/
|
||||
|
||||
int APP_CC
|
||||
fifo_is_empty(FIFO *self)
|
||||
{
|
||||
if (!self)
|
||||
return 1;
|
||||
|
||||
return (self->head == 0);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* FIFO implementation to store pointer to data struct
|
||||
*/
|
||||
|
||||
#ifndef _FIFO_H
|
||||
#define _FIFO_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
typedef struct user_data USER_DATA;
|
||||
|
||||
struct user_data
|
||||
{
|
||||
USER_DATA *next;
|
||||
void *item;
|
||||
};
|
||||
|
||||
typedef struct fifo
|
||||
{
|
||||
USER_DATA *head;
|
||||
USER_DATA *tail;
|
||||
int auto_free;
|
||||
} FIFO;
|
||||
|
||||
FIFO * APP_CC fifo_create(void);
|
||||
void APP_CC fifo_delete(FIFO *self);
|
||||
int APP_CC fifo_add_item(FIFO *self, void *item);
|
||||
void * APP_CC fifo_remove_item(FIFO *self);
|
||||
int APP_CC fifo_is_empty(FIFO *self);
|
||||
|
||||
#endif
|
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* simple list
|
||||
*/
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "list16.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct list16 *APP_CC
|
||||
list16_create(void)
|
||||
{
|
||||
struct list16 *self;
|
||||
|
||||
self = (struct list16 *)g_malloc(sizeof(struct list16), 0);
|
||||
list16_init(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_delete(struct list16 *self)
|
||||
{
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
list16_deinit(self);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_init(struct list16* self)
|
||||
{
|
||||
g_memset(self, 0, sizeof(struct list16));
|
||||
self->max_count = 4;
|
||||
self->items = self->mitems;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_deinit(struct list16* self)
|
||||
{
|
||||
if (self->items != self->mitems)
|
||||
{
|
||||
g_free(self->items);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_add_item(struct list16 *self, tui16 item)
|
||||
{
|
||||
tui16 *p;
|
||||
int i;
|
||||
|
||||
if (self->count >= self->max_count)
|
||||
{
|
||||
i = self->max_count;
|
||||
self->max_count += 4;
|
||||
p = (tui16 *)g_malloc(sizeof(tui16) * self->max_count, 1);
|
||||
g_memcpy(p, self->items, sizeof(tui16) * i);
|
||||
if (self->items != self->mitems)
|
||||
{
|
||||
g_free(self->items);
|
||||
}
|
||||
self->items = p;
|
||||
}
|
||||
|
||||
self->items[self->count] = item;
|
||||
self->count++;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
tui16 APP_CC
|
||||
list16_get_item(struct list16 *self, int index)
|
||||
{
|
||||
if (index < 0 || index >= self->count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return self->items[index];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_clear(struct list16 *self)
|
||||
{
|
||||
if (self->items != self->mitems)
|
||||
{
|
||||
g_free(self->items);
|
||||
}
|
||||
self->count = 0;
|
||||
self->max_count = 4;
|
||||
self->items = self->mitems;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
list16_index_of(struct list16 *self, tui16 item)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < self->count; i++)
|
||||
{
|
||||
if (self->items[i] == item)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_remove_item(struct list16 *self, int index)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (index >= 0 && index < self->count)
|
||||
{
|
||||
for (i = index; i < (self->count - 1); i++)
|
||||
{
|
||||
self->items[i] = self->items[i + 1];
|
||||
}
|
||||
|
||||
self->count--;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
list16_insert_item(struct list16 *self, int index, tui16 item)
|
||||
{
|
||||
tui16 *p;
|
||||
int i;
|
||||
|
||||
if (index == self->count)
|
||||
{
|
||||
list16_add_item(self, item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (index >= 0 && index < self->count)
|
||||
{
|
||||
self->count++;
|
||||
|
||||
if (self->count > self->max_count)
|
||||
{
|
||||
i = self->max_count;
|
||||
self->max_count += 4;
|
||||
p = (tui16 *)g_malloc(sizeof(tui16) * self->max_count, 1);
|
||||
g_memcpy(p, self->items, sizeof(tui16) * i);
|
||||
if (self->items != self->mitems)
|
||||
{
|
||||
g_free(self->items);
|
||||
}
|
||||
self->items = p;
|
||||
}
|
||||
|
||||
for (i = (self->count - 2); i >= index; i--)
|
||||
{
|
||||
self->items[i + 1] = self->items[i];
|
||||
}
|
||||
|
||||
self->items[index] = item;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* simple list
|
||||
*/
|
||||
|
||||
#if !defined(LIST16_H)
|
||||
#define LIST16_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
/* list */
|
||||
struct list16
|
||||
{
|
||||
tui16* items;
|
||||
int count;
|
||||
int max_count;
|
||||
tui16 mitems[4];
|
||||
};
|
||||
|
||||
struct list16* APP_CC
|
||||
list16_create(void);
|
||||
void APP_CC
|
||||
list16_delete(struct list16* self);
|
||||
void APP_CC
|
||||
list16_init(struct list16* self);
|
||||
void APP_CC
|
||||
list16_deinit(struct list16* self);
|
||||
void APP_CC
|
||||
list16_add_item(struct list16* self, tui16 item);
|
||||
tui16 APP_CC
|
||||
list16_get_item(struct list16* self, int index);
|
||||
void APP_CC
|
||||
list16_clear(struct list16* self);
|
||||
int APP_CC
|
||||
list16_index_of(struct list16* self, tui16 item);
|
||||
void APP_CC
|
||||
list16_remove_item(struct list16* self, int index);
|
||||
void APP_CC
|
||||
list16_insert_item(struct list16* self, int index, tui16 item);
|
||||
|
||||
#endif
|
@ -0,0 +1,269 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Idan Freiberg 2013-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* transport layer security
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "os_calls.h"
|
||||
#include "trans.h"
|
||||
#include "ssl_calls.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_tls *
|
||||
APP_CC
|
||||
xrdp_tls_create(struct trans *trans, const char *key, const char *cert)
|
||||
{
|
||||
struct xrdp_tls *self;
|
||||
self = (struct xrdp_tls *) g_malloc(sizeof(struct xrdp_tls), 1);
|
||||
|
||||
if (self != NULL)
|
||||
{
|
||||
self->trans = trans;
|
||||
self->cert = (char *) cert;
|
||||
self->key = (char *) key;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_tls_print_error(char *func, SSL *connection, int value)
|
||||
{
|
||||
switch (SSL_get_error(connection, value))
|
||||
{
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
g_writeln("xrdp_tls_print_error: %s: Server closed TLS connection",
|
||||
func);
|
||||
return 1;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
g_writeln("xrdp_tls_print_error: SSL_ERROR_WANT_READ");
|
||||
return 0;
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
g_writeln("xrdp_tls_print_error: SSL_ERROR_WANT_WRITE");
|
||||
return 0;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
g_writeln("xrdp_tls_print_error: %s: I/O error", func);
|
||||
return 1;
|
||||
|
||||
case SSL_ERROR_SSL:
|
||||
g_writeln("xrdp_tls_print_error: %s: Failure in SSL library (protocol error?)",
|
||||
func);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
g_writeln("xrdp_tls_print_error: %s: Unknown error", func);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_tls_accept(struct xrdp_tls *self)
|
||||
{
|
||||
int connection_status;
|
||||
long options = 0;
|
||||
|
||||
/**
|
||||
* SSL_OP_NO_SSLv2:
|
||||
*
|
||||
* We only want SSLv3 and TLSv1, so disable SSLv2.
|
||||
* SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
|
||||
*/
|
||||
options |= SSL_OP_NO_SSLv2;
|
||||
|
||||
#if defined(SSL_OP_NO_COMPRESSION)
|
||||
/**
|
||||
* SSL_OP_NO_COMPRESSION:
|
||||
*
|
||||
* The Microsoft RDP server does not advertise support
|
||||
* for TLS compression, but alternative servers may support it.
|
||||
* This was observed between early versions of the FreeRDP server
|
||||
* and the FreeRDP client, and caused major performance issues,
|
||||
* which is why we're disabling it.
|
||||
*/
|
||||
options |= SSL_OP_NO_COMPRESSION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SSL_OP_TLS_BLOCK_PADDING_BUG:
|
||||
*
|
||||
* The Microsoft RDP server does *not* support TLS padding.
|
||||
* It absolutely needs to be disabled otherwise it won't work.
|
||||
*/
|
||||
options |= SSL_OP_TLS_BLOCK_PADDING_BUG;
|
||||
|
||||
/**
|
||||
* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
|
||||
*
|
||||
* Just like TLS padding, the Microsoft RDP server does not
|
||||
* support empty fragments. This needs to be disabled.
|
||||
*/
|
||||
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
|
||||
self->ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
/* set context options */
|
||||
SSL_CTX_set_mode(self->ctx,
|
||||
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
|
||||
SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
SSL_CTX_set_options(self->ctx, options);
|
||||
SSL_CTX_set_read_ahead(self->ctx, 1);
|
||||
|
||||
if (self->ctx == NULL)
|
||||
{
|
||||
g_writeln("xrdp_tls_accept: SSL_CTX_new failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_RSAPrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM)
|
||||
<= 0)
|
||||
{
|
||||
g_writeln("xrdp_tls_accept: SSL_CTX_use_RSAPrivateKey_file failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
self->ssl = SSL_new(self->ctx);
|
||||
|
||||
if (self->ssl == NULL)
|
||||
{
|
||||
g_writeln("xrdp_tls_accept: SSL_new failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_use_certificate_file(self->ssl, self->cert, SSL_FILETYPE_PEM) <= 0)
|
||||
{
|
||||
g_writeln("xrdp_tls_accept: SSL_use_certificate_file failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_set_fd(self->ssl, self->trans->sck) < 1)
|
||||
{
|
||||
g_writeln("xrdp_tls_accept: SSL_set_fd failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
connection_status = SSL_accept(self->ssl);
|
||||
|
||||
if (connection_status <= 0)
|
||||
{
|
||||
if (xrdp_tls_print_error("SSL_accept", self->ssl, connection_status))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
g_writeln("xrdp_tls_accept: TLS connection accepted");
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_tls_disconnect(struct xrdp_tls *self)
|
||||
{
|
||||
int status = SSL_shutdown(self->ssl);
|
||||
while (status != 1)
|
||||
{
|
||||
status = SSL_shutdown(self->ssl);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
if (xrdp_tls_print_error("SSL_shutdown", self->ssl, status))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
void APP_CC
|
||||
xrdp_tls_delete(struct xrdp_tls *self)
|
||||
{
|
||||
if (self != NULL)
|
||||
{
|
||||
if (self->ssl)
|
||||
SSL_free(self->ssl);
|
||||
|
||||
if (self->ctx)
|
||||
SSL_CTX_free(self->ctx);
|
||||
|
||||
g_free(self);
|
||||
}
|
||||
}
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_tls_read(struct xrdp_tls *tls, char *data, int length)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = SSL_read(tls->ssl, data, length);
|
||||
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
xrdp_tls_print_error("SSL_read", tls->ssl, status);
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_tls_write(struct xrdp_tls *tls, char *data, int length)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = SSL_write(tls->ssl, data, length);
|
||||
|
||||
switch (SSL_get_error(tls->ssl, status))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
xrdp_tls_print_error("SSL_write", tls->ssl, status);
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1,35 +1,42 @@
|
||||
Creating a new keymap file.
|
||||
---------------------------
|
||||
|
||||
crating a new keymap file.
|
||||
|
||||
The names of the files are
|
||||
The names of the files are of the format;
|
||||
|
||||
km-xxxx.ini
|
||||
|
||||
where the xxx is replaces ny the hex number of the layout of interest.
|
||||
where the xxxx is replaced by the hex number of the layout of interest.
|
||||
|
||||
The files have 6 sections;
|
||||
|
||||
The files have 5 section
|
||||
[noshift], [shift], [altgr], [shiftaltgr], [capslock], [shiftcapslock]
|
||||
|
||||
[noshift], [shift], [altgr], [capslock], [shiftcapslock]
|
||||
In each section there are multiple lines for each key.
|
||||
|
||||
In each section there are multiple lines for each key
|
||||
An example line looks like
|
||||
An example line looks like;
|
||||
|
||||
Key10=49:49
|
||||
|
||||
In this line, 10 is the X11 scancode, the first 49 is the keysym value,
|
||||
the second 49 if the unicode value of the key. This is the definition
|
||||
for the 'noshift' '1' key on a en-us keyboard. In this case, the keysym
|
||||
and the unicode value are the same. Here is an example where they are
|
||||
not.
|
||||
This is the definition for the backspace key.
|
||||
and the unicode value are the same.
|
||||
|
||||
Here is an example where they are not;
|
||||
|
||||
This is the definition for the backspace key;
|
||||
Key22=65288:8
|
||||
|
||||
And this is the star on the keypad
|
||||
And this is the star on the keypad;
|
||||
Key63=65450:42
|
||||
|
||||
To create a new file run xrdp-genkeymap filename
|
||||
To create a new file run "xrdp-genkeymap <filename>"
|
||||
|
||||
Example: ./xrdp-genkeymap /etc/xrdp/km-0409.ini
|
||||
|
||||
Example ./xrdp-genkeymap /etc/xrdp/km-0409.ini
|
||||
Note: You need to have enough rights to be able to write to the
|
||||
/etc/xrdp directory.
|
||||
|
||||
Note: You need to have rights to the /etc/xrdp directory.
|
||||
Alternatively, create the keymap file in a directory of your choice, then
|
||||
copy or move it over to /etc/xrdp using sudo/su.
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
EXTRA_DIST = default.pa
|
||||
pulsedir=$(sysconfdir)/xrdp/pulse
|
||||
pulse_DATA = default.pa
|
@ -0,0 +1,7 @@
|
||||
.nofail
|
||||
.fail
|
||||
load-module module-augment-properties
|
||||
load-module module-xrdp-sink
|
||||
load-module module-xrdp-source
|
||||
load-module module-always-sink
|
||||
load-module module-native-protocol-unix
|
@ -0,0 +1 @@
|
||||
Subproject commit de6a45cba607b902da704304fa3de8ddd3d15239
|
@ -0,0 +1,916 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2014
|
||||
* Copyright (C) Idan Freiberg 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* RDP Capability Sets
|
||||
*/
|
||||
|
||||
#include "libxrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_send_monitorlayout(struct xrdp_rdp *self)
|
||||
{
|
||||
struct stream *s;
|
||||
int i;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
if (xrdp_rdp_init_data(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_uint32_le(s, self->client_info.monitorCount); /* monitorCount (4 bytes) */
|
||||
|
||||
/* TODO: validate for allowed monitors in terminal server (maybe by config?) */
|
||||
for (i = 0; i < self->client_info.monitorCount; i++)
|
||||
{
|
||||
out_uint32_le(s, self->client_info.minfo[i].left);
|
||||
out_uint32_le(s, self->client_info.minfo[i].top);
|
||||
out_uint32_le(s, self->client_info.minfo[i].right);
|
||||
out_uint32_le(s, self->client_info.minfo[i].bottom);
|
||||
out_uint32_le(s, self->client_info.minfo[i].is_primary);
|
||||
}
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
if (xrdp_rdp_send_data(self, s, 0x37) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int extraFlags;
|
||||
int client_does_fastpath_output;
|
||||
|
||||
if (len < 10 + 2)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_general: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 10);
|
||||
in_uint16_le(s, extraFlags);
|
||||
/* use_compact_packets is pretty much 'use rdp5' */
|
||||
self->client_info.use_compact_packets = (extraFlags != 0);
|
||||
/* op2 is a boolean to use compact bitmap headers in bitmap cache */
|
||||
/* set it to same as 'use rdp5' boolean */
|
||||
self->client_info.op2 = self->client_info.use_compact_packets;
|
||||
/* FASTPATH_OUTPUT_SUPPORTED 0x0001 */
|
||||
client_does_fastpath_output = extraFlags & FASTPATH_OUTPUT_SUPPORTED;
|
||||
if ((self->client_info.use_fast_path & 1) && !client_does_fastpath_output)
|
||||
{
|
||||
/* server supports fast path output and client does not, turn it off */
|
||||
self->client_info.use_fast_path &= ~1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
char order_caps[32];
|
||||
int ex_flags;
|
||||
int cap_flags;
|
||||
|
||||
DEBUG(("order capabilities"));
|
||||
if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_order: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 20); /* Terminal desc, pad */
|
||||
in_uint8s(s, 2); /* Cache X granularity */
|
||||
in_uint8s(s, 2); /* Cache Y granularity */
|
||||
in_uint8s(s, 2); /* Pad */
|
||||
in_uint8s(s, 2); /* Max order level */
|
||||
in_uint8s(s, 2); /* Number of fonts */
|
||||
in_uint16_le(s, cap_flags); /* Capability flags */
|
||||
in_uint8a(s, order_caps, 32); /* Orders supported */
|
||||
g_memcpy(self->client_info.orders, order_caps, 32);
|
||||
DEBUG(("dest blt-0 %d", order_caps[0]));
|
||||
DEBUG(("pat blt-1 %d", order_caps[1]));
|
||||
DEBUG(("screen blt-2 %d", order_caps[2]));
|
||||
DEBUG(("memblt-3-13 %d %d", order_caps[3], order_caps[13]));
|
||||
DEBUG(("triblt-4-14 %d %d", order_caps[4], order_caps[14]));
|
||||
DEBUG(("line-8 %d", order_caps[8]));
|
||||
DEBUG(("line-9 %d", order_caps[9]));
|
||||
DEBUG(("rect-10 %d", order_caps[10]));
|
||||
DEBUG(("desksave-11 %d", order_caps[11]));
|
||||
DEBUG(("polygon-20 %d", order_caps[20]));
|
||||
DEBUG(("polygon2-21 %d", order_caps[21]));
|
||||
DEBUG(("polyline-22 %d", order_caps[22]));
|
||||
DEBUG(("ellipse-25 %d", order_caps[25]));
|
||||
DEBUG(("ellipse2-26 %d", order_caps[26]));
|
||||
DEBUG(("text2-27 %d", order_caps[27]));
|
||||
DEBUG(("order_caps dump"));
|
||||
#if defined(XRDP_DEBUG)
|
||||
g_hexdump(order_caps, 32);
|
||||
#endif
|
||||
in_uint8s(s, 2); /* Text capability flags */
|
||||
/* read extended order support flags */
|
||||
in_uint16_le(s, ex_flags); /* Ex flags */
|
||||
|
||||
if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */
|
||||
{
|
||||
self->client_info.order_flags_ex = ex_flags;
|
||||
if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_order: bitmap cache v3 supported");
|
||||
self->client_info.bitmap_cache_version |= 4;
|
||||
}
|
||||
}
|
||||
in_uint8s(s, 4); /* Pad */
|
||||
|
||||
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
|
||||
self->client_info.desktop_cache = i;
|
||||
DEBUG(("desktop cache size %d", i));
|
||||
in_uint8s(s, 4); /* Unknown */
|
||||
in_uint8s(s, 4); /* Unknown */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get the bitmap cache size */
|
||||
static int APP_CC
|
||||
xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_bmpcache: error");
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 1;
|
||||
in_uint8s(s, 24);
|
||||
/* cache 1 */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache1_entries = i;
|
||||
in_uint16_le(s, self->client_info.cache1_size);
|
||||
/* cache 2 */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache2_entries = i;
|
||||
in_uint16_le(s, self->client_info.cache2_size);
|
||||
/* caceh 3 */
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache3_entries = i;
|
||||
in_uint16_le(s, self->client_info.cache3_size);
|
||||
DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries,
|
||||
self->client_info.cache1_size));
|
||||
DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries,
|
||||
self->client_info.cache2_size));
|
||||
DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries,
|
||||
self->client_info.cache3_size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get the bitmap cache size */
|
||||
static int APP_CC
|
||||
xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int Bpp = 0;
|
||||
int i = 0;
|
||||
|
||||
if (len < 2 + 2 + 4 + 4 + 4)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_bmpcache2: error");
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 2;
|
||||
Bpp = (self->client_info.bpp + 7) / 8;
|
||||
in_uint16_le(s, i); /* cache flags */
|
||||
self->client_info.bitmap_cache_persist_enable = i;
|
||||
in_uint8s(s, 2); /* number of caches in set, 3 */
|
||||
in_uint32_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache1_entries = i;
|
||||
self->client_info.cache1_size = 256 * Bpp;
|
||||
in_uint32_le(s, i);
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache2_entries = i;
|
||||
self->client_info.cache2_size = 1024 * Bpp;
|
||||
in_uint32_le(s, i);
|
||||
i = i & 0x7fffffff;
|
||||
i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX);
|
||||
i = MAX(i, 0);
|
||||
self->client_info.cache3_entries = i;
|
||||
self->client_info.cache3_size = 4096 * Bpp;
|
||||
DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries,
|
||||
self->client_info.cache1_size));
|
||||
DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries,
|
||||
self->client_info.cache2_size));
|
||||
DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries,
|
||||
self->client_info.cache3_size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int codec_id;
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_cache_v3_codec_id: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, codec_id);
|
||||
g_writeln("xrdp_caps_process_cache_v3_codec_id: cache_v3_codec_id %d",
|
||||
codec_id);
|
||||
self->client_info.v3_codec_id = codec_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get the number of client cursor cache */
|
||||
static int APP_CC
|
||||
xrdp_caps_process_pointer(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
int colorPointerFlag;
|
||||
int no_new_cursor;
|
||||
|
||||
if (len < 2 + 2 + 2)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_pointer: error");
|
||||
return 1;
|
||||
}
|
||||
no_new_cursor = self->client_info.pointer_flags & 2;
|
||||
in_uint16_le(s, colorPointerFlag);
|
||||
self->client_info.pointer_flags = colorPointerFlag;
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, 32);
|
||||
self->client_info.pointer_cache_entries = i;
|
||||
if (colorPointerFlag & 1)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_pointer: client supports "
|
||||
"new(color) cursor");
|
||||
in_uint16_le(s, i);
|
||||
i = MIN(i, 32);
|
||||
self->client_info.pointer_cache_entries = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("xrdp_caps_process_pointer: client does not support "
|
||||
"new(color) cursor");
|
||||
}
|
||||
if (no_new_cursor)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_pointer: new(color) cursor is "
|
||||
"disabled by config");
|
||||
self->client_info.pointer_flags = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int inputFlags;
|
||||
int client_does_fastpath_input;
|
||||
|
||||
in_uint16_le(s, inputFlags);
|
||||
client_does_fastpath_input = (inputFlags & INPUT_FLAG_FASTPATH_INPUT) ||
|
||||
(inputFlags & INPUT_FLAG_FASTPATH_INPUT2);
|
||||
if ((self->client_info.use_fast_path & 2) && !client_does_fastpath_input)
|
||||
{
|
||||
self->client_info.use_fast_path &= ~2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* get the type of client brush cache */
|
||||
int APP_CC
|
||||
xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int code;
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_brushcache: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, code);
|
||||
self->client_info.brush_cache_code = code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int i32;
|
||||
|
||||
if (len < 4 + 2 + 2)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_offscreen_bmpcache: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.offscreen_support_level = i32;
|
||||
in_uint16_le(s, i32);
|
||||
self->client_info.offscreen_cache_size = i32 * 1024;
|
||||
in_uint16_le(s, i32);
|
||||
self->client_info.offscreen_cache_entries = i32;
|
||||
g_writeln("xrdp_process_offscreen_bmpcache: support level %d "
|
||||
"cache size %d MB cache entries %d",
|
||||
self->client_info.offscreen_support_level,
|
||||
self->client_info.offscreen_cache_size,
|
||||
self->client_info.offscreen_cache_entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
{
|
||||
int i32;
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_rail: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.rail_support_level = i32;
|
||||
g_writeln("xrdp_process_capset_rail: rail_support_level %d",
|
||||
self->client_info.rail_support_level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
{
|
||||
int i32;
|
||||
|
||||
if (len < 4 + 1 + 2)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_window: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.wnd_support_level = i32;
|
||||
in_uint8(s, i32);
|
||||
self->client_info.wnd_num_icon_caches = i32;
|
||||
in_uint16_le(s, i32);
|
||||
self->client_info.wnd_num_icon_cache_entries = i32;
|
||||
g_writeln("xrdp_process_capset_window wnd_support_level %d "
|
||||
"wnd_num_icon_caches %d wnd_num_icon_cache_entries %d",
|
||||
self->client_info.wnd_support_level,
|
||||
self->client_info.wnd_num_icon_caches,
|
||||
self->client_info.wnd_num_icon_cache_entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
{
|
||||
int codec_id;
|
||||
int codec_count;
|
||||
int index;
|
||||
int codec_properties_length;
|
||||
int i1;
|
||||
char *codec_guid;
|
||||
char *next_guid;
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, codec_count);
|
||||
len--;
|
||||
|
||||
for (index = 0; index < codec_count; index++)
|
||||
{
|
||||
codec_guid = s->p;
|
||||
if (len < 16 + 1 + 2)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: error");
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 16);
|
||||
in_uint8(s, codec_id);
|
||||
in_uint16_le(s, codec_properties_length);
|
||||
len -= 16 + 1 + 2;
|
||||
if (len < codec_properties_length)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: error");
|
||||
return 1;
|
||||
}
|
||||
len -= codec_properties_length;
|
||||
next_guid = s->p + codec_properties_length;
|
||||
|
||||
if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: nscodec codec id %d prop len %d",
|
||||
codec_id, codec_properties_length);
|
||||
self->client_info.ns_codec_id = codec_id;
|
||||
i1 = MIN(64, codec_properties_length);
|
||||
g_memcpy(self->client_info.ns_prop, s->p, i1);
|
||||
self->client_info.ns_prop_len = i1;
|
||||
}
|
||||
else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: rfx codec id %d prop len %d",
|
||||
codec_id, codec_properties_length);
|
||||
self->client_info.rfx_codec_id = codec_id;
|
||||
i1 = MIN(64, codec_properties_length);
|
||||
g_memcpy(self->client_info.rfx_prop, s->p, i1);
|
||||
self->client_info.rfx_prop_len = i1;
|
||||
}
|
||||
else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0)
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: jpeg codec id %d prop len %d",
|
||||
codec_id, codec_properties_length);
|
||||
self->client_info.jpeg_codec_id = codec_id;
|
||||
i1 = MIN(64, codec_properties_length);
|
||||
g_memcpy(self->client_info.jpeg_prop, s->p, i1);
|
||||
self->client_info.jpeg_prop_len = i1;
|
||||
/* make sure that requested quality is between 0 to 100 */
|
||||
if (self->client_info.jpeg_prop[0] < 0 || self->client_info.jpeg_prop[0] > 100)
|
||||
{
|
||||
g_writeln(" Warning: the requested jpeg quality (%d) is invalid,"
|
||||
" falling back to default", self->client_info.jpeg_prop[0]);
|
||||
self->client_info.jpeg_prop[0] = 75; /* use default */
|
||||
}
|
||||
g_writeln(" jpeg quality set to %d", self->client_info.jpeg_prop[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_writeln("xrdp_caps_process_codecs: unknown codec id %d", codec_id);
|
||||
}
|
||||
|
||||
s->p = next_guid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int APP_CC
|
||||
xrdp_caps_process_multifragmetupdate(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
int MaxRequestSize;
|
||||
|
||||
in_uint32_le(s, MaxRequestSize);
|
||||
self->client_info.max_fastpath_frag_bytes = MaxRequestSize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
{
|
||||
int cap_len;
|
||||
int source_len;
|
||||
int num_caps;
|
||||
int index;
|
||||
int type;
|
||||
int len;
|
||||
char *p;
|
||||
|
||||
DEBUG(("in xrdp_caps_process_confirm_active"));
|
||||
in_uint8s(s, 4); /* rdp_shareid */
|
||||
in_uint8s(s, 2); /* userid */
|
||||
in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
|
||||
in_uint16_le(s, cap_len);
|
||||
in_uint8s(s, source_len);
|
||||
in_uint16_le(s, num_caps);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
|
||||
for (index = 0; index < num_caps; index++)
|
||||
{
|
||||
p = s->p;
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
g_writeln("xrdp_caps_process_confirm_active: error 1");
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, type);
|
||||
in_uint16_le(s, len);
|
||||
if ((len < 4) || !s_check_rem(s, len - 4))
|
||||
{
|
||||
g_writeln("xrdp_caps_process_confirm_active: error len %d", len, s->end - s->p);
|
||||
return 1;
|
||||
}
|
||||
len -= 4;
|
||||
switch (type)
|
||||
{
|
||||
case RDP_CAPSET_GENERAL: /* 1 */
|
||||
DEBUG(("RDP_CAPSET_GENERAL"));
|
||||
xrdp_caps_process_general(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BITMAP: /* 2 */
|
||||
DEBUG(("RDP_CAPSET_BITMAP"));
|
||||
break;
|
||||
case RDP_CAPSET_ORDER: /* 3 */
|
||||
DEBUG(("RDP_CAPSET_ORDER"));
|
||||
xrdp_caps_process_order(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCACHE: /* 4 */
|
||||
DEBUG(("RDP_CAPSET_BMPCACHE"));
|
||||
xrdp_caps_process_bmpcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_CONTROL: /* 5 */
|
||||
DEBUG(("RDP_CAPSET_CONTROL"));
|
||||
break;
|
||||
case 6:
|
||||
xrdp_caps_process_cache_v3_codec_id(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_ACTIVATE: /* 7 */
|
||||
DEBUG(("RDP_CAPSET_ACTIVATE"));
|
||||
break;
|
||||
case RDP_CAPSET_POINTER: /* 8 */
|
||||
DEBUG(("RDP_CAPSET_POINTER"));
|
||||
xrdp_caps_process_pointer(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_SHARE: /* 9 */
|
||||
DEBUG(("RDP_CAPSET_SHARE"));
|
||||
break;
|
||||
case RDP_CAPSET_COLCACHE: /* 10 */
|
||||
DEBUG(("RDP_CAPSET_COLCACHE"));
|
||||
break;
|
||||
case 12: /* 12 */
|
||||
DEBUG(("--12"));
|
||||
break;
|
||||
case 13: /* 13 */
|
||||
xrdp_caps_process_input(self, s, len);
|
||||
break;
|
||||
case 14: /* 14 */
|
||||
DEBUG(("--14"));
|
||||
break;
|
||||
case RDP_CAPSET_BRUSHCACHE: /* 15 */
|
||||
xrdp_caps_process_brushcache(self, s, len);
|
||||
break;
|
||||
case 16: /* 16 */
|
||||
DEBUG(("--16"));
|
||||
break;
|
||||
case 17: /* 17 */
|
||||
DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE"));
|
||||
xrdp_caps_process_offscreen_bmpcache(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCACHE2: /* 19 */
|
||||
DEBUG(("RDP_CAPSET_BMPCACHE2"));
|
||||
xrdp_caps_process_bmpcache2(self, s, len);
|
||||
break;
|
||||
case 20: /* 20 */
|
||||
DEBUG(("--20"));
|
||||
break;
|
||||
case 21: /* 21 */
|
||||
DEBUG(("--21"));
|
||||
break;
|
||||
case 22: /* 22 */
|
||||
DEBUG(("--22"));
|
||||
break;
|
||||
case 0x0017: /* 23 CAPSETTYPE_RAIL */
|
||||
xrdp_caps_process_rail(self, s, len);
|
||||
break;
|
||||
case 0x0018: /* 24 CAPSETTYPE_WINDOW */
|
||||
xrdp_caps_process_window(self, s, len);
|
||||
break;
|
||||
case 0x001A: /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */
|
||||
xrdp_caps_process_multifragmetupdate(self, s, len);
|
||||
break;
|
||||
case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */
|
||||
xrdp_caps_process_codecs(self, s, len);
|
||||
break;
|
||||
default:
|
||||
g_writeln("unknown in xrdp_caps_process_confirm_active %d", type);
|
||||
break;
|
||||
}
|
||||
|
||||
s->p = p + len + 4;
|
||||
}
|
||||
|
||||
DEBUG(("out xrdp_caps_process_confirm_active"));
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
int APP_CC
|
||||
xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
{
|
||||
struct stream *s;
|
||||
int caps_count;
|
||||
int caps_size;
|
||||
int codec_caps_count;
|
||||
int codec_caps_size;
|
||||
int flags;
|
||||
char *caps_count_ptr;
|
||||
char *caps_size_ptr;
|
||||
char *caps_ptr;
|
||||
char *codec_caps_count_ptr;
|
||||
char *codec_caps_size_ptr;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
DEBUG(("in xrdp_caps_send_demand_active"));
|
||||
|
||||
if (xrdp_rdp_init(self, s) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
caps_count = 0;
|
||||
out_uint32_le(s, self->share_id);
|
||||
out_uint16_le(s, 4); /* 4 chars for RDP\0 */
|
||||
/* 2 bytes size after num caps, set later */
|
||||
caps_size_ptr = s->p;
|
||||
out_uint8s(s, 2);
|
||||
out_uint8a(s, "RDP", 4);
|
||||
/* 4 byte num caps, set later */
|
||||
caps_count_ptr = s->p;
|
||||
out_uint8s(s, 4);
|
||||
caps_ptr = s->p;
|
||||
|
||||
/* Output share capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_SHARE);
|
||||
out_uint16_le(s, RDP_CAPLEN_SHARE);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
out_uint16_be(s, 0xb5e2); /* 0x73e1 */
|
||||
|
||||
/* Output general capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */
|
||||
out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */
|
||||
out_uint16_le(s, 1); /* OS major type */
|
||||
out_uint16_le(s, 3); /* OS minor type */
|
||||
out_uint16_le(s, 0x200); /* Protocol version */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, 0); /* Compression types */
|
||||
/* NO_BITMAP_COMPRESSION_HDR 0x0400
|
||||
FASTPATH_OUTPUT_SUPPORTED 0x0001 */
|
||||
if (self->client_info.use_fast_path & 1)
|
||||
{
|
||||
out_uint16_le(s, 0x401);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint16_le(s, 0x400);
|
||||
}
|
||||
out_uint16_le(s, 0); /* Update capability */
|
||||
out_uint16_le(s, 0); /* Remote unshare capability */
|
||||
out_uint16_le(s, 0); /* Compression level */
|
||||
out_uint16_le(s, 0); /* Pad */
|
||||
|
||||
/* Output bitmap capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */
|
||||
out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */
|
||||
out_uint16_le(s, self->client_info.bpp); /* Preferred BPP */
|
||||
out_uint16_le(s, 1); /* Receive 1 BPP */
|
||||
out_uint16_le(s, 1); /* Receive 4 BPP */
|
||||
out_uint16_le(s, 1); /* Receive 8 BPP */
|
||||
out_uint16_le(s, self->client_info.width); /* width */
|
||||
out_uint16_le(s, self->client_info.height); /* height */
|
||||
out_uint16_le(s, 0); /* Pad */
|
||||
out_uint16_le(s, 1); /* Allow resize */
|
||||
out_uint16_le(s, 1); /* bitmap compression */
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
|
||||
/* Output font capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */
|
||||
out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */
|
||||
|
||||
/* Output order capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */
|
||||
out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */
|
||||
out_uint8s(s, 16);
|
||||
out_uint32_be(s, 0x40420f00);
|
||||
out_uint16_le(s, 1); /* Cache X granularity */
|
||||
out_uint16_le(s, 20); /* Cache Y granularity */
|
||||
out_uint16_le(s, 0); /* Pad */
|
||||
out_uint16_le(s, 1); /* Max order level */
|
||||
out_uint16_le(s, 0x2f); /* Number of fonts */
|
||||
out_uint16_le(s, 0x22); /* Capability flags */
|
||||
/* caps */
|
||||
out_uint8(s, 1); /* NEG_DSTBLT_INDEX 0x00 0 */
|
||||
out_uint8(s, 1); /* NEG_PATBLT_INDEX 0x01 1 */
|
||||
out_uint8(s, 1); /* NEG_SCRBLT_INDEX 0x02 2 */
|
||||
out_uint8(s, 1); /* NEG_MEMBLT_INDEX 0x03 3 */
|
||||
out_uint8(s, 0); /* NEG_MEM3BLT_INDEX 0x04 4 */
|
||||
out_uint8(s, 0); /* NEG_ATEXTOUT_INDEX 0x05 5 */
|
||||
out_uint8(s, 0); /* NEG_AEXTTEXTOUT_INDEX 0x06 6 */
|
||||
out_uint8(s, 0); /* NEG_DRAWNINEGRID_INDEX 0x07 7 */
|
||||
out_uint8(s, 1); /* NEG_LINETO_INDEX 0x08 8 */
|
||||
out_uint8(s, 0); /* NEG_MULTI_DRAWNINEGRID_INDEX 0x09 9 */
|
||||
out_uint8(s, 1); /* NEG_OPAQUE_RECT_INDEX 0x0A 10 */
|
||||
out_uint8(s, 0); /* NEG_SAVEBITMAP_INDEX 0x0B 11 */
|
||||
out_uint8(s, 0); /* NEG_WTEXTOUT_INDEX 0x0C 12 */
|
||||
out_uint8(s, 0); /* NEG_MEMBLT_V2_INDEX 0x0D 13 */
|
||||
out_uint8(s, 0); /* NEG_MEM3BLT_V2_INDEX 0x0E 14 */
|
||||
out_uint8(s, 0); /* NEG_MULTIDSTBLT_INDEX 0x0F 15 */
|
||||
out_uint8(s, 0); /* NEG_MULTIPATBLT_INDEX 0x10 16 */
|
||||
out_uint8(s, 0); /* NEG_MULTISCRBLT_INDEX 0x11 17 */
|
||||
out_uint8(s, 1); /* NEG_MULTIOPAQUERECT_INDEX 0x12 18 */
|
||||
out_uint8(s, 0); /* NEG_FAST_INDEX_INDEX 0x13 19 */
|
||||
out_uint8(s, 0); /* NEG_POLYGON_SC_INDEX 0x14 20 */
|
||||
out_uint8(s, 0); /* NEG_POLYGON_CB_INDEX 0x15 21 */
|
||||
out_uint8(s, 0); /* NEG_POLYLINE_INDEX 0x16 22 */
|
||||
out_uint8(s, 0); /* unused 0x17 23 */
|
||||
out_uint8(s, 0); /* NEG_FAST_GLYPH_INDEX 0x18 24 */
|
||||
out_uint8(s, 0); /* NEG_ELLIPSE_SC_INDEX 0x19 25 */
|
||||
out_uint8(s, 0); /* NEG_ELLIPSE_CB_INDEX 0x1A 26 */
|
||||
out_uint8(s, 1); /* NEG_GLYPH_INDEX_INDEX 0x1B 27 */
|
||||
out_uint8(s, 0); /* NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C 28 */
|
||||
out_uint8(s, 0); /* NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D 29 */
|
||||
out_uint8(s, 0); /* NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E 30 */
|
||||
out_uint8(s, 0); /* unused 0x1F 31 */
|
||||
out_uint16_le(s, 0x6a1);
|
||||
/* declare support of bitmap cache rev3 */
|
||||
out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT);
|
||||
out_uint32_le(s, 0x0f4240); /* desk save */
|
||||
out_uint32_le(s, 0x0f4240); /* desk save */
|
||||
out_uint32_le(s, 1); /* ? */
|
||||
out_uint32_le(s, 0); /* ? */
|
||||
|
||||
/* Output bmpcodecs capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_BMPCODECS);
|
||||
codec_caps_size_ptr = s->p;
|
||||
out_uint8s(s, 2); /* cap len set later */
|
||||
codec_caps_count = 0;
|
||||
codec_caps_count_ptr = s->p;
|
||||
out_uint8s(s, 1); /* bitmapCodecCount set later */
|
||||
/* nscodec */
|
||||
codec_caps_count++;
|
||||
out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16);
|
||||
out_uint8(s, 1); /* codec id, must be 1 */
|
||||
out_uint16_le(s, 3);
|
||||
out_uint8(s, 0x01); /* fAllowDynamicFidelity */
|
||||
out_uint8(s, 0x01); /* fAllowSubsampling */
|
||||
out_uint8(s, 0x03); /* colorLossLevel */
|
||||
/* remotefx */
|
||||
codec_caps_count++;
|
||||
out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16);
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 256);
|
||||
out_uint8s(s, 256);
|
||||
/* jpeg */
|
||||
codec_caps_count++;
|
||||
out_uint8a(s, XR_CODEC_GUID_JPEG, 16);
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 1); /* ext length */
|
||||
out_uint8(s, 75);
|
||||
/* calculate and set size and count */
|
||||
codec_caps_size = (int)(s->p - codec_caps_size_ptr);
|
||||
codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */
|
||||
codec_caps_size_ptr[0] = codec_caps_size;
|
||||
codec_caps_size_ptr[1] = codec_caps_size >> 8;
|
||||
codec_caps_count_ptr[0] = codec_caps_count;
|
||||
|
||||
/* Output color cache capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_COLCACHE);
|
||||
out_uint16_le(s, RDP_CAPLEN_COLCACHE);
|
||||
out_uint16_le(s, 6); /* cache size */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
|
||||
/* Output pointer capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_POINTER);
|
||||
out_uint16_le(s, RDP_CAPLEN_POINTER);
|
||||
out_uint16_le(s, 1); /* Colour pointer */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
|
||||
/* Output input capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */
|
||||
out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */
|
||||
|
||||
/* INPUT_FLAG_SCANCODES 0x0001
|
||||
INPUT_FLAG_MOUSEX 0x0004
|
||||
INPUT_FLAG_FASTPATH_INPUT 0x0008
|
||||
INPUT_FLAG_FASTPATH_INPUT2 0x0020 */
|
||||
flags = 0x0001 | 0x0004;
|
||||
if (self->client_info.use_fast_path & 2)
|
||||
{
|
||||
/* 0x0008 INPUT_FLAG_FASTPATH_INPUT */
|
||||
/* 0x0020 INPUT_FLAG_FASTPATH_INPUT2 */
|
||||
flags |= 0x0008 | 0x0020;
|
||||
}
|
||||
out_uint16_le(s, flags);
|
||||
out_uint8s(s, 82);
|
||||
|
||||
/* Remote Programs Capability Set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */
|
||||
out_uint16_le(s, 8);
|
||||
out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED
|
||||
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
|
||||
|
||||
/* Window List Capability Set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */
|
||||
out_uint16_le(s, 11);
|
||||
out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */
|
||||
out_uint8(s, 3); /* NumIconCaches */
|
||||
out_uint16_le(s, 12); /* NumIconCacheEntries */
|
||||
|
||||
/* 6 - bitmap cache v3 codecid */
|
||||
caps_count++;
|
||||
out_uint16_le(s, 0x0006);
|
||||
out_uint16_le(s, 5);
|
||||
out_uint8(s, 0); /* client sets */
|
||||
|
||||
if (self->client_info.use_fast_path & 1) /* fastpath output on */
|
||||
{
|
||||
caps_count++;
|
||||
out_uint16_le(s, 0x001A); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */
|
||||
out_uint16_le(s, 8);
|
||||
out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */
|
||||
}
|
||||
|
||||
out_uint8s(s, 4); /* pad */
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
caps_size = (int)(s->end - caps_ptr);
|
||||
caps_size_ptr[0] = caps_size;
|
||||
caps_size_ptr[1] = caps_size >> 8;
|
||||
|
||||
caps_count_ptr[0] = caps_count;
|
||||
caps_count_ptr[1] = caps_count >> 8;
|
||||
caps_count_ptr[2] = caps_count >> 16;
|
||||
caps_count_ptr[3] = caps_count >> 24;
|
||||
|
||||
if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
DEBUG(("out (1) xrdp_caps_send_demand_active"));
|
||||
|
||||
/* send Monitor Layout PDU for dual monitor */
|
||||
if (self->client_info.monitorCount > 0 &&
|
||||
self->client_info.multimon == 1)
|
||||
{
|
||||
DEBUG(("xrdp_caps_send_demand_active: sending monitor layout pdu"));
|
||||
if (xrdp_caps_send_monitorlayout(self) != 0)
|
||||
{
|
||||
g_writeln("xrdp_caps_send_demand_active: error sending monitor layout pdu");
|
||||
}
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,41 @@
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
;The first six integer or pointer arguments are passed in registers
|
||||
;RDI, RSI, RDX, RCX, R8, and R9
|
||||
|
||||
;int
|
||||
;cpuid_amd64(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx)
|
||||
|
||||
PROC cpuid_amd64
|
||||
; save registers
|
||||
push rbx
|
||||
|
||||
push rdx
|
||||
push rcx
|
||||
push r8
|
||||
push r9
|
||||
|
||||
mov rax, rdi
|
||||
mov rcx, rsi
|
||||
cpuid
|
||||
pop rdi
|
||||
mov [rdi], edx
|
||||
pop rdi
|
||||
mov [rdi], ecx
|
||||
pop rdi
|
||||
mov [rdi], ebx
|
||||
pop rdi
|
||||
mov [rdi], eax
|
||||
mov eax, 0
|
||||
; restore registers
|
||||
pop rbx
|
||||
ret;
|
||||
align 16
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2014 Jay Sorg
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
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
|
||||
OPEN GROUP 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.
|
||||
|
||||
amd64 asm functions
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __FUNCS_AMD64_H
|
||||
#define __FUNCS_AMD64_H
|
||||
|
||||
int
|
||||
cpuid_amd64(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx);
|
||||
int
|
||||
yv12_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
i420_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
yuy2_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
uyvy_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,248 @@
|
||||
;
|
||||
;Copyright 2014 Jay Sorg
|
||||
;
|
||||
;Permission to use, copy, modify, distribute, and sell this software and its
|
||||
;documentation for any purpose is hereby granted without fee, provided that
|
||||
;the above copyright notice appear in all copies and that both that
|
||||
;copyright notice and this permission notice appear in supporting
|
||||
;documentation.
|
||||
;
|
||||
;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
|
||||
;OPEN GROUP 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.
|
||||
;
|
||||
;I420 to RGB32
|
||||
;amd64 SSE2 32 bit
|
||||
;
|
||||
; RGB to YUV
|
||||
; 0.299 0.587 0.114
|
||||
; -0.14713 -0.28886 0.436
|
||||
; 0.615 -0.51499 -0.10001
|
||||
; YUV to RGB
|
||||
; 1 0 1.13983
|
||||
; 1 -0.39465 -0.58060
|
||||
; 1 2.03211 0
|
||||
; shift left 12
|
||||
; 4096 0 4669
|
||||
; 4096 -1616 -2378
|
||||
; 4096 9324 0
|
||||
|
||||
SECTION .data
|
||||
align 16
|
||||
c128 times 8 dw 128
|
||||
c4669 times 8 dw 4669
|
||||
c1616 times 8 dw 1616
|
||||
c2378 times 8 dw 2378
|
||||
c9324 times 8 dw 9324
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
do8_uv:
|
||||
|
||||
; v
|
||||
movd xmm1, [rbx] ; 4 at a time
|
||||
lea rbx, [rbx + 4]
|
||||
punpcklbw xmm1, xmm1
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm1, xmm6
|
||||
movdqa xmm7, [rel c128]
|
||||
psubw xmm1, xmm7
|
||||
psllw xmm1, 4
|
||||
|
||||
; v
|
||||
movd xmm2, [rdx] ; 4 at a time
|
||||
lea rdx, [rdx + 4]
|
||||
punpcklbw xmm2, xmm2
|
||||
punpcklbw xmm2, xmm6
|
||||
psubw xmm2, xmm7
|
||||
psllw xmm2, 4
|
||||
|
||||
do8:
|
||||
|
||||
; y
|
||||
movq xmm0, [rsi] ; 8 at a time
|
||||
lea rsi, [rsi + 8]
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm0, xmm6
|
||||
|
||||
; r = y + hiword(4669 * (v << 4))
|
||||
movdqa xmm4, [rel c4669]
|
||||
pmulhw xmm4, xmm1
|
||||
movdqa xmm3, xmm0
|
||||
paddw xmm3, xmm4
|
||||
|
||||
; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4))
|
||||
movdqa xmm5, [rel c1616]
|
||||
pmulhw xmm5, xmm2
|
||||
movdqa xmm6, [rel c2378]
|
||||
pmulhw xmm6, xmm1
|
||||
movdqa xmm4, xmm0
|
||||
psubw xmm4, xmm5
|
||||
psubw xmm4, xmm6
|
||||
|
||||
; b = y + hiword(9324 * (u << 4))
|
||||
movdqa xmm6, [rel c9324]
|
||||
pmulhw xmm6, xmm2
|
||||
movdqa xmm5, xmm0
|
||||
paddw xmm5, xmm6
|
||||
|
||||
packuswb xmm3, xmm3 ; b
|
||||
packuswb xmm4, xmm4 ; g
|
||||
punpcklbw xmm3, xmm4 ; gb
|
||||
|
||||
pxor xmm4, xmm4 ; a
|
||||
packuswb xmm5, xmm5 ; r
|
||||
punpcklbw xmm5, xmm4 ; ar
|
||||
|
||||
movdqa xmm4, xmm3
|
||||
punpcklwd xmm3, xmm5 ; argb
|
||||
movdqa [rdi], xmm3
|
||||
lea rdi, [rdi + 16]
|
||||
punpckhwd xmm4, xmm5 ; argb
|
||||
movdqa [rdi], xmm4
|
||||
lea rdi, [rdi + 16]
|
||||
|
||||
ret;
|
||||
|
||||
;The first six integer or pointer arguments are passed in registers
|
||||
; RDI, RSI, RDX, RCX, R8, and R9
|
||||
|
||||
;int
|
||||
;i420_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC i420_to_rgb32_amd64_sse2
|
||||
push rbx
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
|
||||
push rdi
|
||||
push rdx
|
||||
mov rdi, rcx ; rgbs
|
||||
|
||||
mov rcx, rsi ; width
|
||||
mov rdx, rcx
|
||||
pop rbp ; height
|
||||
mov rax, rbp
|
||||
shr rbp, 1
|
||||
imul rax, rcx ; rax = width * height
|
||||
|
||||
pop rsi ; y
|
||||
|
||||
mov rbx, rsi ; u = y + width * height
|
||||
add rbx, rax
|
||||
|
||||
; local vars
|
||||
; char* yptr1
|
||||
; char* yptr2
|
||||
; char* uptr
|
||||
; char* vptr
|
||||
; int* rgbs1
|
||||
; int* rgbs2
|
||||
; int width
|
||||
sub rsp, 56 ; local vars, 56 bytes
|
||||
mov [rsp + 0], rsi ; save y1
|
||||
add rsi, rdx
|
||||
mov [rsp + 8], rsi ; save y2
|
||||
mov [rsp + 16], rbx ; save u
|
||||
shr rax, 2
|
||||
add rbx, rax ; v = u + (width * height / 4)
|
||||
mov [rsp + 24], rbx ; save v
|
||||
|
||||
mov [rsp + 32], rdi ; save rgbs1
|
||||
mov rax, rdx
|
||||
shl rax, 2
|
||||
add rdi, rax
|
||||
mov [rsp + 40], rdi ; save rgbs2
|
||||
|
||||
loop_y:
|
||||
|
||||
mov rcx, rdx ; width
|
||||
shr rcx, 3
|
||||
|
||||
; save rdx
|
||||
mov [rsp + 48], rdx
|
||||
|
||||
;prefetchnta 4096[rsp + 0] ; y
|
||||
;prefetchnta 1024[rsp + 16] ; u
|
||||
;prefetchnta 1024[rsp + 24] ; v
|
||||
|
||||
loop_x:
|
||||
|
||||
mov rsi, [rsp + 0] ; y1
|
||||
mov rbx, [rsp + 16] ; u
|
||||
mov rdx, [rsp + 24] ; v
|
||||
mov rdi, [rsp + 32] ; rgbs1
|
||||
|
||||
; y1
|
||||
call do8_uv
|
||||
|
||||
mov [rsp + 0], rsi ; y1
|
||||
mov [rsp + 32], rdi ; rgbs1
|
||||
|
||||
mov rsi, [rsp + 8] ; y2
|
||||
mov rdi, [rsp + 40] ; rgbs2
|
||||
|
||||
; y2
|
||||
call do8
|
||||
|
||||
mov [rsp + 8], rsi ; y2
|
||||
mov [rsp + 16], rbx ; u
|
||||
mov [rsp + 24], rdx ; v
|
||||
mov [rsp + 40], rdi ; rgbs2
|
||||
|
||||
dec rcx ; width
|
||||
jnz loop_x
|
||||
|
||||
; restore rdx
|
||||
mov rdx, [rsp + 48]
|
||||
|
||||
; update y1 and 2
|
||||
mov rax, [rsp + 0]
|
||||
mov rbx, rdx
|
||||
add rax, rbx
|
||||
mov [rsp + 0], rax
|
||||
|
||||
mov rax, [rsp + 8]
|
||||
add rax, rbx
|
||||
mov [rsp + 8], rax
|
||||
|
||||
; update rgb1 and 2
|
||||
mov rax, [rsp + 32]
|
||||
mov rbx, rdx
|
||||
shl rbx, 2
|
||||
add rax, rbx
|
||||
mov [rsp + 32], rax
|
||||
|
||||
mov rax, [rsp + 40]
|
||||
add rax, rbx
|
||||
mov [rsp + 40], rax
|
||||
|
||||
mov rcx, rbp
|
||||
dec rcx ; height
|
||||
mov rbp, rcx
|
||||
jnz loop_y
|
||||
|
||||
add rsp, 56
|
||||
|
||||
mov rax, 0
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbx
|
||||
ret
|
||||
align 16
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
;int
|
||||
;uyvy_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC uyvy_to_rgb32_amd64_sse2
|
||||
push rbx
|
||||
mov rax, 0
|
||||
pop rbx
|
||||
ret
|
||||
align 16
|
||||
|
@ -0,0 +1,17 @@
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
;int
|
||||
;yuy2_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC yuy2_to_rgb32_amd64_sse2
|
||||
push rbx
|
||||
mov rax, 0
|
||||
pop rbx
|
||||
ret
|
||||
align 16
|
||||
|
@ -0,0 +1,248 @@
|
||||
;
|
||||
;Copyright 2014 Jay Sorg
|
||||
;
|
||||
;Permission to use, copy, modify, distribute, and sell this software and its
|
||||
;documentation for any purpose is hereby granted without fee, provided that
|
||||
;the above copyright notice appear in all copies and that both that
|
||||
;copyright notice and this permission notice appear in supporting
|
||||
;documentation.
|
||||
;
|
||||
;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
|
||||
;OPEN GROUP 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.
|
||||
;
|
||||
;YV12 to RGB32
|
||||
;amd64 SSE2 32 bit
|
||||
;
|
||||
; RGB to YUV
|
||||
; 0.299 0.587 0.114
|
||||
; -0.14713 -0.28886 0.436
|
||||
; 0.615 -0.51499 -0.10001
|
||||
; YUV to RGB
|
||||
; 1 0 1.13983
|
||||
; 1 -0.39465 -0.58060
|
||||
; 1 2.03211 0
|
||||
; shift left 12
|
||||
; 4096 0 4669
|
||||
; 4096 -1616 -2378
|
||||
; 4096 9324 0
|
||||
|
||||
SECTION .data
|
||||
align 16
|
||||
c128 times 8 dw 128
|
||||
c4669 times 8 dw 4669
|
||||
c1616 times 8 dw 1616
|
||||
c2378 times 8 dw 2378
|
||||
c9324 times 8 dw 9324
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
do8_uv:
|
||||
|
||||
; u
|
||||
movd xmm1, [rbx] ; 4 at a time
|
||||
lea rbx, [rbx + 4]
|
||||
punpcklbw xmm1, xmm1
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm1, xmm6
|
||||
movdqa xmm7, [rel c128]
|
||||
psubw xmm1, xmm7
|
||||
psllw xmm1, 4
|
||||
|
||||
; v
|
||||
movd xmm2, [rdx] ; 4 at a time
|
||||
lea rdx, [rdx + 4]
|
||||
punpcklbw xmm2, xmm2
|
||||
punpcklbw xmm2, xmm6
|
||||
psubw xmm2, xmm7
|
||||
psllw xmm2, 4
|
||||
|
||||
do8:
|
||||
|
||||
; y
|
||||
movq xmm0, [rsi] ; 8 at a time
|
||||
lea rsi, [rsi + 8]
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm0, xmm6
|
||||
|
||||
; r = y + hiword(4669 * (v << 4))
|
||||
movdqa xmm4, [rel c4669]
|
||||
pmulhw xmm4, xmm2
|
||||
movdqa xmm3, xmm0
|
||||
paddw xmm3, xmm4
|
||||
|
||||
; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4))
|
||||
movdqa xmm5, [rel c1616]
|
||||
pmulhw xmm5, xmm1
|
||||
movdqa xmm6, [rel c2378]
|
||||
pmulhw xmm6, xmm2
|
||||
movdqa xmm4, xmm0
|
||||
psubw xmm4, xmm5
|
||||
psubw xmm4, xmm6
|
||||
|
||||
; b = y + hiword(9324 * (u << 4))
|
||||
movdqa xmm6, [rel c9324]
|
||||
pmulhw xmm6, xmm1
|
||||
movdqa xmm5, xmm0
|
||||
paddw xmm5, xmm6
|
||||
|
||||
packuswb xmm3, xmm3 ; b
|
||||
packuswb xmm4, xmm4 ; g
|
||||
punpcklbw xmm3, xmm4 ; gb
|
||||
|
||||
pxor xmm4, xmm4 ; a
|
||||
packuswb xmm5, xmm5 ; r
|
||||
punpcklbw xmm5, xmm4 ; ar
|
||||
|
||||
movdqa xmm4, xmm3
|
||||
punpcklwd xmm3, xmm5 ; argb
|
||||
movdqa [rdi], xmm3
|
||||
lea rdi, [rdi + 16]
|
||||
punpckhwd xmm4, xmm5 ; argb
|
||||
movdqa [rdi], xmm4
|
||||
lea rdi, [rdi + 16]
|
||||
|
||||
ret;
|
||||
|
||||
;The first six integer or pointer arguments are passed in registers
|
||||
; RDI, RSI, RDX, RCX, R8, and R9
|
||||
|
||||
;int
|
||||
;yv12_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC yv12_to_rgb32_amd64_sse2
|
||||
push rbx
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
|
||||
push rdi
|
||||
push rdx
|
||||
mov rdi, rcx ; rgbs
|
||||
|
||||
mov rcx, rsi ; width
|
||||
mov rdx, rcx
|
||||
pop rbp ; height
|
||||
mov rax, rbp
|
||||
shr rbp, 1
|
||||
imul rax, rcx ; rax = width * height
|
||||
|
||||
pop rsi ; y
|
||||
|
||||
mov rbx, rsi ; u = y + width * height
|
||||
add rbx, rax
|
||||
|
||||
; local vars
|
||||
; char* yptr1
|
||||
; char* yptr2
|
||||
; char* uptr
|
||||
; char* vptr
|
||||
; int* rgbs1
|
||||
; int* rgbs2
|
||||
; int width
|
||||
sub rsp, 56 ; local vars, 56 bytes
|
||||
mov [rsp + 0], rsi ; save y1
|
||||
add rsi, rdx
|
||||
mov [rsp + 8], rsi ; save y2
|
||||
mov [rsp + 16], rbx ; save u
|
||||
shr rax, 2
|
||||
add rbx, rax ; v = u + (width * height / 4)
|
||||
mov [rsp + 24], rbx ; save v
|
||||
|
||||
mov [rsp + 32], rdi ; save rgbs1
|
||||
mov rax, rdx
|
||||
shl rax, 2
|
||||
add rdi, rax
|
||||
mov [rsp + 40], rdi ; save rgbs2
|
||||
|
||||
loop_y:
|
||||
|
||||
mov rcx, rdx ; width
|
||||
shr rcx, 3
|
||||
|
||||
; save rdx
|
||||
mov [rsp + 48], rdx
|
||||
|
||||
;prefetchnta 4096[rsp + 0] ; y
|
||||
;prefetchnta 1024[rsp + 16] ; u
|
||||
;prefetchnta 1024[rsp + 24] ; v
|
||||
|
||||
loop_x:
|
||||
|
||||
mov rsi, [rsp + 0] ; y1
|
||||
mov rbx, [rsp + 16] ; u
|
||||
mov rdx, [rsp + 24] ; v
|
||||
mov rdi, [rsp + 32] ; rgbs1
|
||||
|
||||
; y1
|
||||
call do8_uv
|
||||
|
||||
mov [rsp + 0], rsi ; y1
|
||||
mov [rsp + 32], rdi ; rgbs1
|
||||
|
||||
mov rsi, [rsp + 8] ; y2
|
||||
mov rdi, [rsp + 40] ; rgbs2
|
||||
|
||||
; y2
|
||||
call do8
|
||||
|
||||
mov [rsp + 8], rsi ; y2
|
||||
mov [rsp + 16], rbx ; u
|
||||
mov [rsp + 24], rdx ; v
|
||||
mov [rsp + 40], rdi ; rgbs2
|
||||
|
||||
dec rcx ; width
|
||||
jnz loop_x
|
||||
|
||||
; restore rdx
|
||||
mov rdx, [rsp + 48]
|
||||
|
||||
; update y1 and 2
|
||||
mov rax, [rsp + 0]
|
||||
mov rbx, rdx
|
||||
add rax, rbx
|
||||
mov [rsp + 0], rax
|
||||
|
||||
mov rax, [rsp + 8]
|
||||
add rax, rbx
|
||||
mov [rsp + 8], rax
|
||||
|
||||
; update rgb1 and 2
|
||||
mov rax, [rsp + 32]
|
||||
mov rbx, rdx
|
||||
shl rbx, 2
|
||||
add rax, rbx
|
||||
mov [rsp + 32], rax
|
||||
|
||||
mov rax, [rsp + 40]
|
||||
add rax, rbx
|
||||
mov [rsp + 40], rax
|
||||
|
||||
mov rcx, rbp
|
||||
dec rcx ; height
|
||||
mov rbp, rcx
|
||||
jnz loop_y
|
||||
|
||||
add rsp, 56
|
||||
|
||||
mov rax, 0
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbx
|
||||
ret
|
||||
align 16
|
||||
|
||||
|
@ -0,0 +1,138 @@
|
||||
/*
|
||||
Copyright 2014 Jay Sorg
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
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
|
||||
OPEN GROUP 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.
|
||||
|
||||
SIMD function asign
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* this should be before all X11 .h files */
|
||||
#include <xorg-server.h>
|
||||
#include <xorgVersion.h>
|
||||
|
||||
/* all driver need this */
|
||||
#include <xf86.h>
|
||||
#include <xf86_OSproc.h>
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rdpXv.h"
|
||||
|
||||
/* use simd, run time */
|
||||
int g_simd_use_accel = 1;
|
||||
|
||||
/* use simd, compile time, if zero, g_simd_use_accel does not matter */
|
||||
#if !defined(SIMD_USE_ACCEL)
|
||||
#define SIMD_USE_ACCEL 0
|
||||
#endif
|
||||
|
||||
#if SIMD_USE_ACCEL
|
||||
#if defined(__x86_64__) || defined(__AMD64__) || defined (_M_AMD64)
|
||||
#include "amd64/funcs_amd64.h"
|
||||
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
|
||||
#include "x86/funcs_x86.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LOG_LEVEL 1
|
||||
#define LLOGLN(_level, _args) \
|
||||
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
|
||||
|
||||
/*****************************************************************************/
|
||||
Bool
|
||||
rdpSimdInit(ScreenPtr pScreen, ScrnInfoPtr pScrn)
|
||||
{
|
||||
rdpPtr dev;
|
||||
|
||||
dev = XRDPPTR(pScrn);
|
||||
/* assign functions */
|
||||
LLOGLN(0, ("rdpSimdInit: assigning yuv functions"));
|
||||
#if SIMD_USE_ACCEL
|
||||
if (g_simd_use_accel)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__AMD64__) || defined (_M_AMD64)
|
||||
int ax, bx, cx, dx;
|
||||
cpuid_amd64(1, 0, &ax, &bx, &cx, &dx);
|
||||
LLOGLN(0, ("rdpSimdInit: cpuid ax 1 cx 0 return ax 0x%8.8x bx "
|
||||
"0x%8.8x cx 0x%8.8x dx 0x%8.8x", ax, bx, cx, dx));
|
||||
if (dx & (1 << 26)) /* SSE 2 */
|
||||
{
|
||||
dev->yv12_to_rgb32 = yv12_to_rgb32_amd64_sse2;
|
||||
dev->i420_to_rgb32 = i420_to_rgb32_amd64_sse2;
|
||||
dev->yuy2_to_rgb32 = yuy2_to_rgb32_amd64_sse2;
|
||||
dev->uyvy_to_rgb32 = uyvy_to_rgb32_amd64_sse2;
|
||||
LLOGLN(0, ("rdpSimdInit: sse2 amd64 yuv functions assigned"));
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->yv12_to_rgb32 = YV12_to_RGB32;
|
||||
dev->i420_to_rgb32 = I420_to_RGB32;
|
||||
dev->yuy2_to_rgb32 = YUY2_to_RGB32;
|
||||
dev->uyvy_to_rgb32 = UYVY_to_RGB32;
|
||||
LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned"));
|
||||
}
|
||||
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
|
||||
int ax, bx, cx, dx;
|
||||
cpuid_x86(1, 0, &ax, &bx, &cx, &dx);
|
||||
LLOGLN(0, ("rdpSimdInit: cpuid ax 1 cx 0 return ax 0x%8.8x bx "
|
||||
"0x%8.8x cx 0x%8.8x dx 0x%8.8x", ax, bx, cx, dx));
|
||||
if (dx & (1 << 26)) /* SSE 2 */
|
||||
{
|
||||
dev->yv12_to_rgb32 = yv12_to_rgb32_x86_sse2;
|
||||
dev->i420_to_rgb32 = i420_to_rgb32_x86_sse2;
|
||||
dev->yuy2_to_rgb32 = yuy2_to_rgb32_x86_sse2;
|
||||
dev->uyvy_to_rgb32 = uyvy_to_rgb32_x86_sse2;
|
||||
LLOGLN(0, ("rdpSimdInit: sse2 x86 yuv functions assigned"));
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->yv12_to_rgb32 = YV12_to_RGB32;
|
||||
dev->i420_to_rgb32 = I420_to_RGB32;
|
||||
dev->yuy2_to_rgb32 = YUY2_to_RGB32;
|
||||
dev->uyvy_to_rgb32 = UYVY_to_RGB32;
|
||||
LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned"));
|
||||
}
|
||||
#else
|
||||
dev->yv12_to_rgb32 = YV12_to_RGB32;
|
||||
dev->i420_to_rgb32 = I420_to_RGB32;
|
||||
dev->yuy2_to_rgb32 = YUY2_to_RGB32;
|
||||
dev->uyvy_to_rgb32 = UYVY_to_RGB32;
|
||||
LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned"));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->yv12_to_rgb32 = YV12_to_RGB32;
|
||||
dev->i420_to_rgb32 = I420_to_RGB32;
|
||||
dev->yuy2_to_rgb32 = YUY2_to_RGB32;
|
||||
dev->uyvy_to_rgb32 = UYVY_to_RGB32;
|
||||
LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned"));
|
||||
}
|
||||
#else
|
||||
dev->yv12_to_rgb32 = YV12_to_RGB32;
|
||||
dev->i420_to_rgb32 = I420_to_RGB32;
|
||||
dev->yuy2_to_rgb32 = YUY2_to_RGB32;
|
||||
dev->uyvy_to_rgb32 = UYVY_to_RGB32;
|
||||
LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned"));
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2014 Jay Sorg
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
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
|
||||
OPEN GROUP 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.
|
||||
|
||||
SIMD function asign
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __RDPSIMD_H
|
||||
#define __RDPSIMD_H
|
||||
|
||||
#include <xorg-server.h>
|
||||
#include <xorgVersion.h>
|
||||
#include <xf86.h>
|
||||
|
||||
Bool
|
||||
rdpSimdInit(ScreenPtr pScreen, ScrnInfoPtr pScrn);
|
||||
|
||||
#endif
|
@ -0,0 +1,678 @@
|
||||
/*
|
||||
Copyright 2014 Jay Sorg
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
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
|
||||
OPEN GROUP 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.
|
||||
|
||||
XVideo
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* this should be before all X11 .h files */
|
||||
#include <xorg-server.h>
|
||||
#include <xorgVersion.h>
|
||||
|
||||
/* all driver need this */
|
||||
#include <xf86.h>
|
||||
#include <xf86_OSproc.h>
|
||||
|
||||
#include <xf86xv.h>
|
||||
#include <X11/extensions/Xv.h>
|
||||
#include <fourcc.h>
|
||||
|
||||
#include <fb.h>
|
||||
|
||||
#include "rdp.h"
|
||||
#include "rdpMisc.h"
|
||||
#include "rdpReg.h"
|
||||
#include "rdpClientCon.h"
|
||||
|
||||
#define LOG_LEVEL 1
|
||||
#define LLOGLN(_level, _args) \
|
||||
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
|
||||
|
||||
#define T_NUM_ENCODINGS 1
|
||||
static XF86VideoEncodingRec g_xrdpVidEncodings[T_NUM_ENCODINGS] =
|
||||
{ { 0, "XV_IMAGE", 2046, 2046, { 1, 1 } } };
|
||||
|
||||
#define T_NUM_FORMATS 1
|
||||
static XF86VideoFormatRec g_xrdpVidFormats[T_NUM_FORMATS] =
|
||||
{ { 0, TrueColor } };
|
||||
|
||||
/* YV12
|
||||
I420
|
||||
12 bpp planar
|
||||
YUV 4:2:0 8 bit Y plane followed by 8 bit 2x2 subsampled
|
||||
U and V planes. */
|
||||
|
||||
/* YUY2
|
||||
UYVY
|
||||
16 bpp packed
|
||||
YUV 4:2:2 Y sample at every pixel, U and V sampled at
|
||||
every second pixel */
|
||||
|
||||
/* XVIMAGE_YV12 FOURCC_YV12 0x32315659 */
|
||||
/* XVIMAGE_I420 FOURCC_I420 0x30323449 */
|
||||
/* XVIMAGE_YUY2 FOURCC_YUY2 0x32595559 */
|
||||
/* XVIMAGE_UYVY FOURCC_UYVY 0x59565955 */
|
||||
|
||||
static XF86ImageRec g_xrdpVidImages[] =
|
||||
{ XVIMAGE_YV12, XVIMAGE_I420, XVIMAGE_YUY2, XVIMAGE_UYVY };
|
||||
|
||||
#define T_MAX_PORTS 1
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidPutVideo(ScrnInfoPtr pScrn, short vid_x, short vid_y,
|
||||
short drw_x, short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
pointer data, DrawablePtr pDraw)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidPutVideo:"));
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidPutStill(ScrnInfoPtr pScrn, short vid_x, short vid_y,
|
||||
short drw_x, short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
pointer data, DrawablePtr pDraw)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidPutStill:"));
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidGetVideo(ScrnInfoPtr pScrn, short vid_x, short vid_y,
|
||||
short drw_x, short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
pointer data, DrawablePtr pDraw)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidGetVideo:"));
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidGetStill(ScrnInfoPtr pScrn, short vid_x, short vid_y,
|
||||
short drw_x, short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
pointer data, DrawablePtr pDraw)
|
||||
{
|
||||
LLOGLN(0, ("FBDevTIVidGetStill:"));
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
xrdpVidStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidStopVideo:"));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
|
||||
INT32 value, pointer data)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidSetPortAttribute:"));
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
|
||||
INT32 *value, pointer data)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidGetPortAttribute:"));
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
xrdpVidQueryBestSize(ScrnInfoPtr pScrn, Bool motion,
|
||||
short vid_w, short vid_h, short drw_w, short drw_h,
|
||||
unsigned int *p_w, unsigned int *p_h, pointer data)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidQueryBestSize:"));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
YV12_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
{
|
||||
int size_total;
|
||||
int y;
|
||||
int u;
|
||||
int v;
|
||||
int c;
|
||||
int d;
|
||||
int e;
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
int t;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
size_total = width * height;
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
y = yuvs[j * width + i];
|
||||
u = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total];
|
||||
v = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total + (size_total / 4)];
|
||||
c = y - 16;
|
||||
d = u - 128;
|
||||
e = v - 128;
|
||||
t = (298 * c + 409 * e + 128) >> 8;
|
||||
b = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c - 100 * d - 208 * e + 128) >> 8;
|
||||
g = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c + 516 * d + 128) >> 8;
|
||||
r = RDPCLAMP(t, 0, 255);
|
||||
rgbs[j * width + i] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
I420_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
{
|
||||
int size_total;
|
||||
int y;
|
||||
int u;
|
||||
int v;
|
||||
int c;
|
||||
int d;
|
||||
int e;
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
int t;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
size_total = width * height;
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
y = yuvs[j * width + i];
|
||||
v = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total];
|
||||
u = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total + (size_total / 4)];
|
||||
c = y - 16;
|
||||
d = u - 128;
|
||||
e = v - 128;
|
||||
t = (298 * c + 409 * e + 128) >> 8;
|
||||
b = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c - 100 * d - 208 * e + 128) >> 8;
|
||||
g = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c + 516 * d + 128) >> 8;
|
||||
r = RDPCLAMP(t, 0, 255);
|
||||
rgbs[j * width + i] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
YUY2_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
{
|
||||
int y1;
|
||||
int y2;
|
||||
int u;
|
||||
int v;
|
||||
int c;
|
||||
int d;
|
||||
int e;
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
int t;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
y1 = *(yuvs++);
|
||||
v = *(yuvs++);
|
||||
y2 = *(yuvs++);
|
||||
u = *(yuvs++);
|
||||
|
||||
c = y1 - 16;
|
||||
d = u - 128;
|
||||
e = v - 128;
|
||||
t = (298 * c + 409 * e + 128) >> 8;
|
||||
b = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c - 100 * d - 208 * e + 128) >> 8;
|
||||
g = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c + 516 * d + 128) >> 8;
|
||||
r = RDPCLAMP(t, 0, 255);
|
||||
rgbs[j * width + i] = (r << 16) | (g << 8) | b;
|
||||
|
||||
i++;
|
||||
c = y2 - 16;
|
||||
d = u - 128;
|
||||
e = v - 128;
|
||||
t = (298 * c + 409 * e + 128) >> 8;
|
||||
b = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c - 100 * d - 208 * e + 128) >> 8;
|
||||
g = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c + 516 * d + 128) >> 8;
|
||||
r = RDPCLAMP(t, 0, 255);
|
||||
rgbs[j * width + i] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
UYVY_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
{
|
||||
int y1;
|
||||
int y2;
|
||||
int u;
|
||||
int v;
|
||||
int c;
|
||||
int d;
|
||||
int e;
|
||||
int r;
|
||||
int g;
|
||||
int b;
|
||||
int t;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
v = *(yuvs++);
|
||||
y1 = *(yuvs++);
|
||||
u = *(yuvs++);
|
||||
y2 = *(yuvs++);
|
||||
|
||||
c = y1 - 16;
|
||||
d = u - 128;
|
||||
e = v - 128;
|
||||
t = (298 * c + 409 * e + 128) >> 8;
|
||||
b = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c - 100 * d - 208 * e + 128) >> 8;
|
||||
g = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c + 516 * d + 128) >> 8;
|
||||
r = RDPCLAMP(t, 0, 255);
|
||||
rgbs[j * width + i] = (r << 16) | (g << 8) | b;
|
||||
|
||||
i++;
|
||||
c = y2 - 16;
|
||||
d = u - 128;
|
||||
e = v - 128;
|
||||
t = (298 * c + 409 * e + 128) >> 8;
|
||||
b = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c - 100 * d - 208 * e + 128) >> 8;
|
||||
g = RDPCLAMP(t, 0, 255);
|
||||
t = (298 * c + 516 * d + 128) >> 8;
|
||||
r = RDPCLAMP(t, 0, 255);
|
||||
rgbs[j * width + i] = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
stretch_RGB32_RGB32(int *src, int src_width, int src_height,
|
||||
int src_x, int src_y, int src_w, int src_h,
|
||||
int *dst, int dst_w, int dst_h)
|
||||
{
|
||||
int mwidth;
|
||||
int mheight;
|
||||
int index;
|
||||
|
||||
mwidth = RDPMIN(src_width, dst_w);
|
||||
mheight = RDPMIN(src_height, dst_h);
|
||||
for (index = 0; index < mheight; index++)
|
||||
{
|
||||
g_memcpy(dst, src, mwidth * 4);
|
||||
src += src_width;
|
||||
dst += dst_w;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
stretch_RGB32_RGB32(int *src, int src_width, int src_height,
|
||||
int src_x, int src_y, int src_w, int src_h,
|
||||
int *dst, int dst_w, int dst_h)
|
||||
{
|
||||
int index;
|
||||
int jndex;
|
||||
int lndex;
|
||||
int last_lndex;
|
||||
int oh;
|
||||
int ih;
|
||||
int ov;
|
||||
int iv;
|
||||
int pix;
|
||||
int *src32;
|
||||
int *dst32;
|
||||
|
||||
LLOGLN(10, ("stretch_RGB32_RGB32: oh 0x%8.8x ov 0x%8.8x", oh, ov));
|
||||
oh = (src_w << 16) / dst_w;
|
||||
ov = (src_h << 16) / dst_h;
|
||||
iv = ov;
|
||||
lndex = src_y;
|
||||
last_lndex = -1;
|
||||
for (index = 0; index < dst_h; index++)
|
||||
{
|
||||
if (lndex == last_lndex)
|
||||
{
|
||||
/* repeat line */
|
||||
dst32 = dst + index * dst_w;
|
||||
src32 = dst32 - dst_w;
|
||||
g_memcpy(dst32, src32, dst_w * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
ih = oh;
|
||||
src32 = src + lndex * src_width + src_x;
|
||||
pix = *src32;
|
||||
dst32 = dst + index * dst_w;
|
||||
for (jndex = 0; jndex < dst_w; jndex++)
|
||||
{
|
||||
*dst32 = pix;
|
||||
while (ih > (1 << 16) - 1)
|
||||
{
|
||||
ih -= 1 << 16;
|
||||
src32++;
|
||||
}
|
||||
pix = *src32;
|
||||
ih += oh;
|
||||
dst32++;
|
||||
}
|
||||
}
|
||||
last_lndex = lndex;
|
||||
while (iv > (1 << 16) - 1)
|
||||
{
|
||||
iv -= 1 << 16;
|
||||
lndex++;
|
||||
}
|
||||
iv += ov;
|
||||
|
||||
}
|
||||
LLOGLN(10, ("stretch_RGB32_RGB32: out"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns error */
|
||||
static CARD32
|
||||
rdpDeferredXvCleanup(OsTimerPtr timer, CARD32 now, pointer arg)
|
||||
{
|
||||
rdpPtr dev;
|
||||
|
||||
LLOGLN(0, ("rdpDeferredXvCleanup:"));
|
||||
dev = (rdpPtr) arg;
|
||||
dev->xv_timer_schedualed = 0;
|
||||
dev->xv_data_bytes = 0;
|
||||
g_free(dev->xv_data);
|
||||
dev->xv_data = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* see hw/xfree86/common/xf86xv.c for info */
|
||||
static int
|
||||
xrdpVidPutImage(ScrnInfoPtr pScrn,
|
||||
short src_x, short src_y, short drw_x, short drw_y,
|
||||
short src_w, short src_h, short drw_w, short drw_h,
|
||||
int format, unsigned char* buf,
|
||||
short width, short height,
|
||||
Bool sync, RegionPtr clipBoxes,
|
||||
pointer data, DrawablePtr dst)
|
||||
{
|
||||
rdpPtr dev;
|
||||
int *rgborg32;
|
||||
int *rgbend32;
|
||||
int index;
|
||||
int error;
|
||||
GCPtr tempGC;
|
||||
|
||||
LLOGLN(10, ("xrdpVidPutImage: format 0x%8.8x", format));
|
||||
LLOGLN(10, ("xrdpVidPutImage: src_x %d srcy_y %d", src_x, src_y));
|
||||
dev = XRDPPTR(pScrn);
|
||||
|
||||
if (dev->xv_timer_schedualed)
|
||||
{
|
||||
TimerCancel(dev->xv_timer);
|
||||
dev->xv_timer = TimerSet(dev->xv_timer, 0, 2000,
|
||||
rdpDeferredXvCleanup, dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->xv_timer_schedualed = 1;
|
||||
dev->xv_timer = TimerSet(dev->xv_timer, 0, 2000,
|
||||
rdpDeferredXvCleanup, dev);
|
||||
}
|
||||
|
||||
index = width * height * 4 + drw_w * drw_h * 4 + 64;
|
||||
if (index > dev->xv_data_bytes)
|
||||
{
|
||||
g_free(dev->xv_data);
|
||||
dev->xv_data = g_malloc(index, 0);
|
||||
if (dev->xv_data == NULL)
|
||||
{
|
||||
LLOGLN(0, ("xrdpVidPutImage: memory alloc error"));
|
||||
dev->xv_data_bytes = 0;
|
||||
return Success;
|
||||
}
|
||||
dev->xv_data_bytes = index;
|
||||
}
|
||||
rgborg32 = (int *) RDPALIGN(dev->xv_data, 16);
|
||||
rgbend32 = rgborg32 + width * height;
|
||||
rgbend32 = (int *) RDPALIGN(rgbend32, 16);
|
||||
error = 0;
|
||||
switch (format)
|
||||
{
|
||||
case FOURCC_YV12:
|
||||
LLOGLN(10, ("xrdpVidPutImage: FOURCC_YV12"));
|
||||
error = dev->yv12_to_rgb32(buf, width, height, rgborg32);
|
||||
break;
|
||||
case FOURCC_I420:
|
||||
LLOGLN(10, ("xrdpVidPutImage: FOURCC_I420"));
|
||||
error = dev->i420_to_rgb32(buf, width, height, rgborg32);
|
||||
break;
|
||||
case FOURCC_YUY2:
|
||||
LLOGLN(10, ("xrdpVidPutImage: FOURCC_YUY2"));
|
||||
error = dev->yuy2_to_rgb32(buf, width, height, rgborg32);
|
||||
break;
|
||||
case FOURCC_UYVY:
|
||||
LLOGLN(10, ("xrdpVidPutImage: FOURCC_UYVY"));
|
||||
error = dev->uyvy_to_rgb32(buf, width, height, rgborg32);
|
||||
break;
|
||||
default:
|
||||
LLOGLN(0, ("xrdpVidPutImage: unknown format 0x%8.8x", format));
|
||||
return Success;
|
||||
}
|
||||
if (error != 0)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
error = stretch_RGB32_RGB32(rgborg32, width, height,
|
||||
src_x, src_y, src_w, src_h,
|
||||
rgbend32, drw_w, drw_h);
|
||||
if (error != 0)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
tempGC = GetScratchGC(dst->depth, pScrn->pScreen);
|
||||
if (tempGC != NULL)
|
||||
{
|
||||
ValidateGC(dst, tempGC);
|
||||
(*tempGC->ops->PutImage)(dst, tempGC, 24,
|
||||
drw_x - dst->x, drw_y - dst->y,
|
||||
drw_w, drw_h, 0, ZPixmap, (char*)rgbend32);
|
||||
FreeScratchGC(tempGC);
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdpVidQueryImageAttributes(ScrnInfoPtr pScrn, int id,
|
||||
unsigned short *w, unsigned short *h,
|
||||
int *pitches, int *offsets)
|
||||
{
|
||||
int size, tmp;
|
||||
|
||||
LLOGLN(10, ("xrdpVidQueryImageAttributes:"));
|
||||
/* this is same code as all drivers currently have */
|
||||
if (*w > 2046)
|
||||
{
|
||||
*w = 2046;
|
||||
}
|
||||
if (*h > 2046)
|
||||
{
|
||||
*h = 2046;
|
||||
}
|
||||
/* make w multiple of 4 so that resizing works properly */
|
||||
*w = (*w + 3) & ~3;
|
||||
if (offsets != NULL)
|
||||
{
|
||||
offsets[0] = 0;
|
||||
}
|
||||
switch (id)
|
||||
{
|
||||
case FOURCC_YV12:
|
||||
case FOURCC_I420:
|
||||
/* make h be even */
|
||||
*h = (*h + 1) & ~1;
|
||||
/* make w be multiple of 4 (ie. pad it) */
|
||||
size = (*w + 3) & ~3;
|
||||
/* width of a Y row => width of image */
|
||||
if (pitches != NULL)
|
||||
{
|
||||
pitches[0] = size;
|
||||
}
|
||||
/* offset of U plane => w * h */
|
||||
size *= *h;
|
||||
if (offsets != NULL)
|
||||
{
|
||||
offsets[1] = size;
|
||||
}
|
||||
/* width of U, V row => width / 2 */
|
||||
tmp = ((*w >> 1) + 3) & ~3;
|
||||
if (pitches != NULL)
|
||||
{
|
||||
pitches[1] = pitches[2] = tmp;
|
||||
}
|
||||
/* offset of V => Y plane + U plane (w * h + w / 2 * h / 2) */
|
||||
tmp *= (*h >> 1);
|
||||
size += tmp;
|
||||
if (offsets != NULL)
|
||||
{
|
||||
offsets[2] = size;
|
||||
}
|
||||
size += tmp;
|
||||
break;
|
||||
case FOURCC_YUY2:
|
||||
case FOURCC_UYVY:
|
||||
size = (*w) * 2;
|
||||
if (pitches != NULL)
|
||||
{
|
||||
pitches[0] = size;
|
||||
}
|
||||
size *= *h;
|
||||
break;
|
||||
default:
|
||||
LLOGLN(0, ("xrdpVidQueryImageAttributes: Unsupported image"));
|
||||
return 0;
|
||||
}
|
||||
LLOGLN(10, ("xrdpVidQueryImageAttributes: finished size %d id 0x%x", size, id));
|
||||
return size;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
Bool
|
||||
rdpXvInit(ScreenPtr pScreen, ScrnInfoPtr pScrn)
|
||||
{
|
||||
XF86VideoAdaptorPtr adaptor;
|
||||
DevUnion* pDevUnion;
|
||||
int bytes;
|
||||
|
||||
adaptor = xf86XVAllocateVideoAdaptorRec(pScrn);
|
||||
if (adaptor == 0)
|
||||
{
|
||||
LLOGLN(0, ("rdpXvInit: xf86XVAllocateVideoAdaptorRec failed"));
|
||||
return 0;
|
||||
}
|
||||
adaptor->type = XvInputMask | XvImageMask | XvVideoMask | XvStillMask | XvWindowMask | XvPixmapMask;
|
||||
//adaptor->flags = VIDEO_NO_CLIPPING;
|
||||
//adaptor->flags = VIDEO_CLIP_TO_VIEWPORT;
|
||||
adaptor->flags = 0;
|
||||
adaptor->name = XRDP_MODULE_NAME " XVideo Adaptor";
|
||||
adaptor->nEncodings = T_NUM_ENCODINGS;
|
||||
adaptor->pEncodings = &(g_xrdpVidEncodings[0]);
|
||||
adaptor->nFormats = T_NUM_FORMATS;
|
||||
adaptor->pFormats = &(g_xrdpVidFormats[0]);
|
||||
adaptor->pFormats[0].depth = pScrn->depth;
|
||||
LLOGLN(0, ("rdpXvInit: depth %d", pScrn->depth));
|
||||
adaptor->nImages = sizeof(g_xrdpVidImages) / sizeof(XF86ImageRec);
|
||||
adaptor->pImages = g_xrdpVidImages;
|
||||
adaptor->nAttributes = 0;
|
||||
adaptor->pAttributes = 0;
|
||||
adaptor->nPorts = T_MAX_PORTS;
|
||||
bytes = sizeof(DevUnion) * T_MAX_PORTS;
|
||||
pDevUnion = (DevUnion*) g_malloc(bytes, 1);
|
||||
adaptor->pPortPrivates = pDevUnion;
|
||||
adaptor->PutVideo = xrdpVidPutVideo;
|
||||
adaptor->PutStill = xrdpVidPutStill;
|
||||
adaptor->GetVideo = xrdpVidGetVideo;
|
||||
adaptor->GetStill = xrdpVidGetStill;
|
||||
adaptor->StopVideo = xrdpVidStopVideo;
|
||||
adaptor->SetPortAttribute = xrdpVidSetPortAttribute;
|
||||
adaptor->GetPortAttribute = xrdpVidGetPortAttribute;
|
||||
adaptor->QueryBestSize = xrdpVidQueryBestSize;
|
||||
adaptor->PutImage = xrdpVidPutImage;
|
||||
adaptor->QueryImageAttributes = xrdpVidQueryImageAttributes;
|
||||
if (!xf86XVScreenInit(pScreen, &adaptor, 1))
|
||||
{
|
||||
LLOGLN(0, ("rdpXvInit: xf86XVScreenInit failed"));
|
||||
return 0;
|
||||
}
|
||||
xf86XVFreeVideoAdaptorRec(adaptor);
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2014 Jay Sorg
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
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
|
||||
OPEN GROUP 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.
|
||||
|
||||
XVideo
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __RDPXV_H
|
||||
#define __RDPXV_H
|
||||
|
||||
#include <xorg-server.h>
|
||||
#include <xorgVersion.h>
|
||||
#include <xf86.h>
|
||||
|
||||
Bool
|
||||
rdpXvInit(ScreenPtr pScreen, ScrnInfoPtr pScrn);
|
||||
|
||||
int
|
||||
YV12_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
I420_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
YUY2_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
UYVY_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
|
||||
#endif
|
@ -0,0 +1,39 @@
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
;int
|
||||
;cpuid_x86(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx)
|
||||
|
||||
PROC cpuid_x86
|
||||
; save registers
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
; cpuid
|
||||
mov eax, [esp + 20]
|
||||
mov ecx, [esp + 24]
|
||||
cpuid
|
||||
mov edi, [esp + 28]
|
||||
mov [edi], eax
|
||||
mov edi, [esp + 32]
|
||||
mov [edi], ebx
|
||||
mov edi, [esp + 36]
|
||||
mov [edi], ecx
|
||||
mov edi, [esp + 40]
|
||||
mov [edi], edx
|
||||
mov eax, 0
|
||||
; restore registers
|
||||
pop edi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
ret;
|
||||
align 16
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2014 Jay Sorg
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
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
|
||||
OPEN GROUP 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.
|
||||
|
||||
x86 asm files
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __FUNCS_X86_H
|
||||
#define __FUNCS_X86_H
|
||||
|
||||
int
|
||||
cpuid_x86(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx);
|
||||
int
|
||||
yv12_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
i420_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
yuy2_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
int
|
||||
uyvy_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,243 @@
|
||||
;
|
||||
;Copyright 2014 Jay Sorg
|
||||
;
|
||||
;Permission to use, copy, modify, distribute, and sell this software and its
|
||||
;documentation for any purpose is hereby granted without fee, provided that
|
||||
;the above copyright notice appear in all copies and that both that
|
||||
;copyright notice and this permission notice appear in supporting
|
||||
;documentation.
|
||||
;
|
||||
;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
|
||||
;OPEN GROUP 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.
|
||||
;
|
||||
;I420 to RGB32
|
||||
;x86 SSE2 32 bit
|
||||
;
|
||||
; RGB to YUV
|
||||
; 0.299 0.587 0.114
|
||||
; -0.14713 -0.28886 0.436
|
||||
; 0.615 -0.51499 -0.10001
|
||||
; YUV to RGB
|
||||
; 1 0 1.13983
|
||||
; 1 -0.39465 -0.58060
|
||||
; 1 2.03211 0
|
||||
; shift left 12
|
||||
; 4096 0 4669
|
||||
; 4096 -1616 -2378
|
||||
; 4096 9324 0
|
||||
|
||||
SECTION .data
|
||||
align 16
|
||||
c128 times 8 dw 128
|
||||
c4669 times 8 dw 4669
|
||||
c1616 times 8 dw 1616
|
||||
c2378 times 8 dw 2378
|
||||
c9324 times 8 dw 9324
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
do8_uv:
|
||||
|
||||
; v
|
||||
movd xmm1, [ebx] ; 4 at a time
|
||||
lea ebx, [ebx + 4]
|
||||
punpcklbw xmm1, xmm1
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm1, xmm6
|
||||
movdqa xmm7, [c128]
|
||||
psubw xmm1, xmm7
|
||||
psllw xmm1, 4
|
||||
|
||||
; u
|
||||
movd xmm2, [edx] ; 4 at a time
|
||||
lea edx, [edx + 4]
|
||||
punpcklbw xmm2, xmm2
|
||||
punpcklbw xmm2, xmm6
|
||||
psubw xmm2, xmm7
|
||||
psllw xmm2, 4
|
||||
|
||||
do8:
|
||||
|
||||
; y
|
||||
movq xmm0, [esi] ; 8 at a time
|
||||
lea esi, [esi + 8]
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm0, xmm6
|
||||
|
||||
; r = y + hiword(4669 * (v << 4))
|
||||
movdqa xmm4, [c4669]
|
||||
pmulhw xmm4, xmm1
|
||||
movdqa xmm3, xmm0
|
||||
paddw xmm3, xmm4
|
||||
|
||||
; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4))
|
||||
movdqa xmm5, [c1616]
|
||||
pmulhw xmm5, xmm2
|
||||
movdqa xmm6, [c2378]
|
||||
pmulhw xmm6, xmm1
|
||||
movdqa xmm4, xmm0
|
||||
psubw xmm4, xmm5
|
||||
psubw xmm4, xmm6
|
||||
|
||||
; b = y + hiword(9324 * (u << 4))
|
||||
movdqa xmm6, [c9324]
|
||||
pmulhw xmm6, xmm2
|
||||
movdqa xmm5, xmm0
|
||||
paddw xmm5, xmm6
|
||||
|
||||
packuswb xmm3, xmm3 ; b
|
||||
packuswb xmm4, xmm4 ; g
|
||||
punpcklbw xmm3, xmm4 ; gb
|
||||
|
||||
pxor xmm4, xmm4 ; a
|
||||
packuswb xmm5, xmm5 ; r
|
||||
punpcklbw xmm5, xmm4 ; ar
|
||||
|
||||
movdqa xmm4, xmm3
|
||||
punpcklwd xmm3, xmm5 ; argb
|
||||
movdqa [edi], xmm3
|
||||
lea edi, [edi + 16]
|
||||
punpckhwd xmm4, xmm5 ; argb
|
||||
movdqa [edi], xmm4
|
||||
lea edi, [edi + 16]
|
||||
|
||||
ret;
|
||||
|
||||
;int
|
||||
;i420_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC i420_to_rgb32_x86_sse2
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [esp + 32] ; rgbs
|
||||
|
||||
mov ecx, [esp + 24] ; width
|
||||
mov edx, ecx
|
||||
mov ebp, [esp + 28] ; height
|
||||
mov eax, ebp
|
||||
shr ebp, 1
|
||||
imul eax, ecx ; eax = width * height
|
||||
|
||||
mov esi, [esp + 20] ; y
|
||||
|
||||
mov ebx, esi ; u = y + width * height
|
||||
add ebx, eax
|
||||
|
||||
; local vars
|
||||
; char* yptr1
|
||||
; char* yptr2
|
||||
; char* uptr
|
||||
; char* vptr
|
||||
; int* rgbs1
|
||||
; int* rgbs2
|
||||
; int width
|
||||
sub esp, 28 ; local vars, 28 bytes
|
||||
mov [esp + 0], esi ; save y1
|
||||
add esi, edx
|
||||
mov [esp + 4], esi ; save y2
|
||||
mov [esp + 8], ebx ; save u
|
||||
shr eax, 2
|
||||
add ebx, eax ; v = u + (width * height / 4)
|
||||
mov [esp + 12], ebx ; save v
|
||||
|
||||
mov [esp + 16], edi ; save rgbs1
|
||||
mov eax, edx
|
||||
shl eax, 2
|
||||
add edi, eax
|
||||
mov [esp + 20], edi ; save rgbs2
|
||||
|
||||
loop_y:
|
||||
|
||||
mov ecx, edx ; width
|
||||
shr ecx, 3
|
||||
|
||||
; save edx
|
||||
mov [esp + 24], edx
|
||||
|
||||
;prefetchnta 4096[esp + 0] ; y
|
||||
;prefetchnta 1024[esp + 8] ; u
|
||||
;prefetchnta 1024[esp + 12] ; v
|
||||
|
||||
loop_x:
|
||||
|
||||
mov esi, [esp + 0] ; y1
|
||||
mov ebx, [esp + 8] ; u
|
||||
mov edx, [esp + 12] ; v
|
||||
mov edi, [esp + 16] ; rgbs1
|
||||
|
||||
; y1
|
||||
call do8_uv
|
||||
|
||||
mov [esp + 0], esi ; y1
|
||||
mov [esp + 16], edi ; rgbs1
|
||||
|
||||
mov esi, [esp + 4] ; y2
|
||||
mov edi, [esp + 20] ; rgbs2
|
||||
|
||||
; y2
|
||||
call do8
|
||||
|
||||
mov [esp + 4], esi ; y2
|
||||
mov [esp + 8], ebx ; u
|
||||
mov [esp + 12], edx ; v
|
||||
mov [esp + 20], edi ; rgbs2
|
||||
|
||||
dec ecx ; width
|
||||
jnz loop_x
|
||||
|
||||
; restore edx
|
||||
mov edx, [esp + 24]
|
||||
|
||||
; update y1 and 2
|
||||
mov eax, [esp + 0]
|
||||
mov ebx, edx
|
||||
add eax, ebx
|
||||
mov [esp + 0], eax
|
||||
|
||||
mov eax, [esp + 4]
|
||||
add eax, ebx
|
||||
mov [esp + 4], eax
|
||||
|
||||
; update rgb1 and 2
|
||||
mov eax, [esp + 16]
|
||||
mov ebx, edx
|
||||
shl ebx, 2
|
||||
add eax, ebx
|
||||
mov [esp + 16], eax
|
||||
|
||||
mov eax, [esp + 20]
|
||||
add eax, ebx
|
||||
mov [esp + 20], eax
|
||||
|
||||
mov ecx, ebp
|
||||
dec ecx ; height
|
||||
mov ebp, ecx
|
||||
jnz loop_y
|
||||
|
||||
add esp, 28
|
||||
|
||||
mov eax, 0
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
ret
|
||||
align 16
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
;int
|
||||
;uyvy_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC uyvy_to_rgb32_x86_sse2
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov eax, 0
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
ret
|
||||
align 16
|
||||
|
@ -0,0 +1,22 @@
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
;int
|
||||
;yuy2_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC yuy2_to_rgb32_x86_sse2
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov eax, 0
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
ret
|
||||
align 16
|
||||
|
@ -0,0 +1,243 @@
|
||||
;
|
||||
;Copyright 2014 Jay Sorg
|
||||
;
|
||||
;Permission to use, copy, modify, distribute, and sell this software and its
|
||||
;documentation for any purpose is hereby granted without fee, provided that
|
||||
;the above copyright notice appear in all copies and that both that
|
||||
;copyright notice and this permission notice appear in supporting
|
||||
;documentation.
|
||||
;
|
||||
;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
|
||||
;OPEN GROUP 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.
|
||||
;
|
||||
;YV12 to RGB32
|
||||
;x86 SSE2 32 bit
|
||||
;
|
||||
; RGB to YUV
|
||||
; 0.299 0.587 0.114
|
||||
; -0.14713 -0.28886 0.436
|
||||
; 0.615 -0.51499 -0.10001
|
||||
; YUV to RGB
|
||||
; 1 0 1.13983
|
||||
; 1 -0.39465 -0.58060
|
||||
; 1 2.03211 0
|
||||
; shift left 12
|
||||
; 4096 0 4669
|
||||
; 4096 -1616 -2378
|
||||
; 4096 9324 0
|
||||
|
||||
SECTION .data
|
||||
align 16
|
||||
c128 times 8 dw 128
|
||||
c4669 times 8 dw 4669
|
||||
c1616 times 8 dw 1616
|
||||
c2378 times 8 dw 2378
|
||||
c9324 times 8 dw 9324
|
||||
|
||||
SECTION .text
|
||||
|
||||
%macro PROC 1
|
||||
align 16
|
||||
global %1
|
||||
%1:
|
||||
%endmacro
|
||||
|
||||
do8_uv:
|
||||
|
||||
; u
|
||||
movd xmm1, [ebx] ; 4 at a time
|
||||
lea ebx, [ebx + 4]
|
||||
punpcklbw xmm1, xmm1
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm1, xmm6
|
||||
movdqa xmm7, [c128]
|
||||
psubw xmm1, xmm7
|
||||
psllw xmm1, 4
|
||||
|
||||
; v
|
||||
movd xmm2, [edx] ; 4 at a time
|
||||
lea edx, [edx + 4]
|
||||
punpcklbw xmm2, xmm2
|
||||
punpcklbw xmm2, xmm6
|
||||
psubw xmm2, xmm7
|
||||
psllw xmm2, 4
|
||||
|
||||
do8:
|
||||
|
||||
; y
|
||||
movq xmm0, [esi] ; 8 at a time
|
||||
lea esi, [esi + 8]
|
||||
pxor xmm6, xmm6
|
||||
punpcklbw xmm0, xmm6
|
||||
|
||||
; r = y + hiword(4669 * (v << 4))
|
||||
movdqa xmm4, [c4669]
|
||||
pmulhw xmm4, xmm2
|
||||
movdqa xmm3, xmm0
|
||||
paddw xmm3, xmm4
|
||||
|
||||
; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4))
|
||||
movdqa xmm5, [c1616]
|
||||
pmulhw xmm5, xmm1
|
||||
movdqa xmm6, [c2378]
|
||||
pmulhw xmm6, xmm2
|
||||
movdqa xmm4, xmm0
|
||||
psubw xmm4, xmm5
|
||||
psubw xmm4, xmm6
|
||||
|
||||
; b = y + hiword(9324 * (u << 4))
|
||||
movdqa xmm6, [c9324]
|
||||
pmulhw xmm6, xmm1
|
||||
movdqa xmm5, xmm0
|
||||
paddw xmm5, xmm6
|
||||
|
||||
packuswb xmm3, xmm3 ; b
|
||||
packuswb xmm4, xmm4 ; g
|
||||
punpcklbw xmm3, xmm4 ; gb
|
||||
|
||||
pxor xmm4, xmm4 ; a
|
||||
packuswb xmm5, xmm5 ; r
|
||||
punpcklbw xmm5, xmm4 ; ar
|
||||
|
||||
movdqa xmm4, xmm3
|
||||
punpcklwd xmm3, xmm5 ; argb
|
||||
movdqa [edi], xmm3
|
||||
lea edi, [edi + 16]
|
||||
punpckhwd xmm4, xmm5 ; argb
|
||||
movdqa [edi], xmm4
|
||||
lea edi, [edi + 16]
|
||||
|
||||
ret;
|
||||
|
||||
;int
|
||||
;yv12_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs)
|
||||
|
||||
PROC yv12_to_rgb32_x86_sse2
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
push ebp
|
||||
|
||||
mov edi, [esp + 32] ; rgbs
|
||||
|
||||
mov ecx, [esp + 24] ; width
|
||||
mov edx, ecx
|
||||
mov ebp, [esp + 28] ; height
|
||||
mov eax, ebp
|
||||
shr ebp, 1
|
||||
imul eax, ecx ; eax = width * height
|
||||
|
||||
mov esi, [esp + 20] ; y
|
||||
|
||||
mov ebx, esi ; u = y + width * height
|
||||
add ebx, eax
|
||||
|
||||
; local vars
|
||||
; char* yptr1
|
||||
; char* yptr2
|
||||
; char* uptr
|
||||
; char* vptr
|
||||
; int* rgbs1
|
||||
; int* rgbs2
|
||||
; int width
|
||||
sub esp, 28 ; local vars, 28 bytes
|
||||
mov [esp + 0], esi ; save y1
|
||||
add esi, edx
|
||||
mov [esp + 4], esi ; save y2
|
||||
mov [esp + 8], ebx ; save u
|
||||
shr eax, 2
|
||||
add ebx, eax ; v = u + (width * height / 4)
|
||||
mov [esp + 12], ebx ; save v
|
||||
|
||||
mov [esp + 16], edi ; save rgbs1
|
||||
mov eax, edx
|
||||
shl eax, 2
|
||||
add edi, eax
|
||||
mov [esp + 20], edi ; save rgbs2
|
||||
|
||||
loop_y:
|
||||
|
||||
mov ecx, edx ; width
|
||||
shr ecx, 3
|
||||
|
||||
; save edx
|
||||
mov [esp + 24], edx
|
||||
|
||||
;prefetchnta 4096[esp + 0] ; y
|
||||
;prefetchnta 1024[esp + 8] ; u
|
||||
;prefetchnta 1024[esp + 12] ; v
|
||||
|
||||
loop_x:
|
||||
|
||||
mov esi, [esp + 0] ; y1
|
||||
mov ebx, [esp + 8] ; u
|
||||
mov edx, [esp + 12] ; v
|
||||
mov edi, [esp + 16] ; rgbs1
|
||||
|
||||
; y1
|
||||
call do8_uv
|
||||
|
||||
mov [esp + 0], esi ; y1
|
||||
mov [esp + 16], edi ; rgbs1
|
||||
|
||||
mov esi, [esp + 4] ; y2
|
||||
mov edi, [esp + 20] ; rgbs2
|
||||
|
||||
; y2
|
||||
call do8
|
||||
|
||||
mov [esp + 4], esi ; y2
|
||||
mov [esp + 8], ebx ; u
|
||||
mov [esp + 12], edx ; v
|
||||
mov [esp + 20], edi ; rgbs2
|
||||
|
||||
dec ecx ; width
|
||||
jnz loop_x
|
||||
|
||||
; restore edx
|
||||
mov edx, [esp + 24]
|
||||
|
||||
; update y1 and 2
|
||||
mov eax, [esp + 0]
|
||||
mov ebx, edx
|
||||
add eax, ebx
|
||||
mov [esp + 0], eax
|
||||
|
||||
mov eax, [esp + 4]
|
||||
add eax, ebx
|
||||
mov [esp + 4], eax
|
||||
|
||||
; update rgb1 and 2
|
||||
mov eax, [esp + 16]
|
||||
mov ebx, edx
|
||||
shl ebx, 2
|
||||
add eax, ebx
|
||||
mov [esp + 16], eax
|
||||
|
||||
mov eax, [esp + 20]
|
||||
add eax, ebx
|
||||
mov [esp + 20], eax
|
||||
|
||||
mov ecx, ebp
|
||||
dec ecx ; height
|
||||
mov ebp, ecx
|
||||
jnz loop_y
|
||||
|
||||
add esp, 28
|
||||
|
||||
mov eax, 0
|
||||
pop ebp
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
ret
|
||||
align 16
|
||||
|
||||
|
@ -0,0 +1,479 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Laxmikant Rashinkar 2004-2014
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
#include "xrdp_encoder.h"
|
||||
#include "xrdp.h"
|
||||
#include "thread_calls.h"
|
||||
#include "fifo.h"
|
||||
|
||||
#ifdef XRDP_RFXCODEC
|
||||
#include "rfxcodec_encode.h"
|
||||
#endif
|
||||
|
||||
#define LLOG_LEVEL 1
|
||||
#define LLOGLN(_level, _args) \
|
||||
do \
|
||||
{ \
|
||||
if (_level < LLOG_LEVEL) \
|
||||
{ \
|
||||
g_write("xrdp:xrdp_encoder [%10.10u]: ", g_time3()); \
|
||||
g_writeln _args ; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define JPG_CODEC 0
|
||||
#define RFX_CODEC 1
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc);
|
||||
static int
|
||||
process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc);
|
||||
|
||||
/**
|
||||
* Init encoder
|
||||
*
|
||||
* @return 0 on success, -1 on failure
|
||||
*****************************************************************************/
|
||||
/* called from main thread */
|
||||
int APP_CC
|
||||
init_xrdp_encoder(struct xrdp_mm *self)
|
||||
{
|
||||
char buf[1024];
|
||||
int pid;
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
LLOGLN(0, ("init_xrdp_encoder: initing encoder codec_id %d", self->codec_id));
|
||||
|
||||
/* setup required FIFOs */
|
||||
self->fifo_to_proc = fifo_create();
|
||||
self->fifo_processed = fifo_create();
|
||||
self->mutex = tc_mutex_create();
|
||||
|
||||
pid = g_getpid();
|
||||
/* setup wait objects for signalling */
|
||||
g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_event_to_proc", pid);
|
||||
self->xrdp_encoder_event_to_proc = g_create_wait_obj(buf);
|
||||
g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_event_processed", pid);
|
||||
self->xrdp_encoder_event_processed = g_create_wait_obj(buf);
|
||||
g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_term", pid);
|
||||
self->xrdp_encoder_term = g_create_wait_obj(buf);
|
||||
|
||||
switch (self->codec_id)
|
||||
{
|
||||
case 2:
|
||||
self->process_enc = process_enc_jpg;
|
||||
break;
|
||||
case 3:
|
||||
self->process_enc = process_enc_rfx;
|
||||
#ifdef XRDP_RFXCODEC
|
||||
self->codec_handle =
|
||||
rfxcodec_encode_create(self->wm->screen->width,
|
||||
self->wm->screen->height,
|
||||
RFX_FORMAT_YUV, 0);
|
||||
//RFX_FORMAT_BGRA, 0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
LLOGLN(0, ("init_xrdp_encoder: unknown codec_id %d",
|
||||
self->codec_id));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* create thread to process messages */
|
||||
tc_thread_create(proc_enc_msg, self);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinit xrdp encoder
|
||||
*****************************************************************************/
|
||||
/* called from main thread */
|
||||
void APP_CC
|
||||
deinit_xrdp_encoder(struct xrdp_mm *self)
|
||||
{
|
||||
XRDP_ENC_DATA *enc;
|
||||
XRDP_ENC_DATA_DONE *enc_done;
|
||||
FIFO *fifo;
|
||||
|
||||
LLOGLN(0, ("deinit_xrdp_encoder: deiniting encoder"));
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->in_codec_mode == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* tell worker thread to shut down */
|
||||
g_set_wait_obj(self->xrdp_encoder_term);
|
||||
g_sleep(1000);
|
||||
|
||||
if (self->codec_id == 3)
|
||||
{
|
||||
#ifdef XRDP_RFXCODEC
|
||||
rfxcodec_encode_destroy(self->codec_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* destroy wait objects used for signalling */
|
||||
g_delete_wait_obj(self->xrdp_encoder_event_to_proc);
|
||||
g_delete_wait_obj(self->xrdp_encoder_event_processed);
|
||||
g_delete_wait_obj(self->xrdp_encoder_term);
|
||||
|
||||
/* cleanup fifo_to_proc */
|
||||
fifo = self->fifo_to_proc;
|
||||
if (fifo)
|
||||
{
|
||||
while (!fifo_is_empty(fifo))
|
||||
{
|
||||
enc = fifo_remove_item(fifo);
|
||||
if (enc == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
g_free(enc->drects);
|
||||
g_free(enc->crects);
|
||||
g_free(enc);
|
||||
}
|
||||
|
||||
fifo_delete(fifo);
|
||||
}
|
||||
|
||||
/* cleanup fifo_processed */
|
||||
fifo = self->fifo_processed;
|
||||
if (fifo)
|
||||
{
|
||||
while (!fifo_is_empty(fifo))
|
||||
{
|
||||
enc_done = fifo_remove_item(fifo);
|
||||
if (enc == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
g_free(enc_done->comp_pad_data);
|
||||
g_free(enc_done);
|
||||
}
|
||||
fifo_delete(fifo);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* called from encoder thread */
|
||||
static int
|
||||
process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc)
|
||||
{
|
||||
int index;
|
||||
int x;
|
||||
int y;
|
||||
int cx;
|
||||
int cy;
|
||||
int quality;
|
||||
int error;
|
||||
int out_data_bytes;
|
||||
int count;
|
||||
char *out_data;
|
||||
XRDP_ENC_DATA_DONE *enc_done;
|
||||
FIFO *fifo_processed;
|
||||
tbus mutex;
|
||||
tbus event_processed;
|
||||
|
||||
LLOGLN(10, ("process_enc_jpg:"));
|
||||
quality = self->codec_quality;
|
||||
fifo_processed = self->fifo_processed;
|
||||
mutex = self->mutex;
|
||||
event_processed = self->xrdp_encoder_event_processed;
|
||||
count = enc->num_crects;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
x = enc->crects[index * 4 + 0];
|
||||
y = enc->crects[index * 4 + 1];
|
||||
cx = enc->crects[index * 4 + 2];
|
||||
cy = enc->crects[index * 4 + 3];
|
||||
if (cx < 1 || cy < 1)
|
||||
{
|
||||
LLOGLN(0, ("process_enc_jpg: error 1"));
|
||||
continue;
|
||||
}
|
||||
|
||||
LLOGLN(10, ("process_enc_jpg: x %d y %d cx %d cy %d", x, y, cx, cy));
|
||||
|
||||
out_data_bytes = MAX((cx + 4) * cy * 4, 8192);
|
||||
if ((out_data_bytes < 1) || (out_data_bytes > 16 * 1024 * 1024))
|
||||
{
|
||||
LLOGLN(0, ("process_enc_jpg: error 2"));
|
||||
return 1;
|
||||
}
|
||||
out_data = (char *) g_malloc(out_data_bytes + 256 + 2, 0);
|
||||
if (out_data == 0)
|
||||
{
|
||||
LLOGLN(0, ("process_enc_jpg: error 3"));
|
||||
return 1;
|
||||
}
|
||||
out_data[256] = 0; /* header bytes */
|
||||
out_data[257] = 0;
|
||||
error = libxrdp_codec_jpeg_compress(self->wm->session, 0, enc->data,
|
||||
enc->width, enc->height,
|
||||
enc->width * 4, x, y, cx, cy,
|
||||
quality,
|
||||
out_data + 256 + 2, &out_data_bytes);
|
||||
if (error < 0)
|
||||
{
|
||||
LLOGLN(0, ("process_enc_jpg: jpeg error %d bytes %d",
|
||||
error, out_data_bytes));
|
||||
g_free(out_data);
|
||||
return 1;
|
||||
}
|
||||
LLOGLN(10, ("jpeg error %d bytes %d", error, out_data_bytes));
|
||||
enc_done = (XRDP_ENC_DATA_DONE *)
|
||||
g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1);
|
||||
enc_done->comp_bytes = out_data_bytes + 2;
|
||||
enc_done->pad_bytes = 256;
|
||||
enc_done->comp_pad_data = out_data;
|
||||
enc_done->enc = enc;
|
||||
enc_done->last = index == (enc->num_crects - 1);
|
||||
enc_done->x = x;
|
||||
enc_done->y = y;
|
||||
enc_done->cx = cx;
|
||||
enc_done->cy = cy;
|
||||
/* done with msg */
|
||||
/* inform main thread done */
|
||||
tc_mutex_lock(mutex);
|
||||
fifo_add_item(fifo_processed, enc_done);
|
||||
tc_mutex_unlock(mutex);
|
||||
/* signal completion for main thread */
|
||||
g_set_wait_obj(event_processed);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef XRDP_RFXCODEC
|
||||
|
||||
/*****************************************************************************/
|
||||
/* called from encoder thread */
|
||||
static int
|
||||
process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc)
|
||||
{
|
||||
int index;
|
||||
int x;
|
||||
int y;
|
||||
int cx;
|
||||
int cy;
|
||||
int out_data_bytes;
|
||||
int count;
|
||||
int error;
|
||||
char *out_data;
|
||||
XRDP_ENC_DATA_DONE *enc_done;
|
||||
FIFO *fifo_processed;
|
||||
tbus mutex;
|
||||
tbus event_processed;
|
||||
struct rfx_tile *tiles;
|
||||
struct rfx_rect *rfxrects;
|
||||
|
||||
LLOGLN(10, ("process_enc_rfx:"));
|
||||
LLOGLN(10, ("process_enc_rfx: num_crects %d num_drects %d",
|
||||
enc->num_crects, enc->num_drects));
|
||||
fifo_processed = self->fifo_processed;
|
||||
mutex = self->mutex;
|
||||
event_processed = self->xrdp_encoder_event_processed;
|
||||
|
||||
if ((enc->num_crects > 512) || (enc->num_drects > 512))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_data_bytes = 16 * 1024 * 1024;
|
||||
index = 256 + sizeof(struct rfx_tile) * 512 +
|
||||
sizeof(struct rfx_rect) * 512;
|
||||
out_data = (char *) g_malloc(out_data_bytes + index, 0);
|
||||
if (out_data == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
tiles = (struct rfx_tile *) (out_data + out_data_bytes + 256);
|
||||
rfxrects = (struct rfx_rect *) (tiles + 512);
|
||||
|
||||
count = enc->num_crects;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
x = enc->crects[index * 4 + 0];
|
||||
y = enc->crects[index * 4 + 1];
|
||||
cx = enc->crects[index * 4 + 2];
|
||||
cy = enc->crects[index * 4 + 3];
|
||||
LLOGLN(10, ("process_enc_rfx:"));
|
||||
tiles[index].x = x;
|
||||
tiles[index].y = y;
|
||||
tiles[index].cx = cx;
|
||||
tiles[index].cy = cy;
|
||||
LLOGLN(10, ("x %d y %d cx %d cy %d", x, y, cx, cy));
|
||||
tiles[index].quant_y = 0;
|
||||
tiles[index].quant_cb = 0;
|
||||
tiles[index].quant_cr = 0;
|
||||
}
|
||||
|
||||
count = enc->num_drects;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
x = enc->drects[index * 4 + 0];
|
||||
y = enc->drects[index * 4 + 1];
|
||||
cx = enc->drects[index * 4 + 2];
|
||||
cy = enc->drects[index * 4 + 3];
|
||||
LLOGLN(10, ("process_enc_rfx:"));
|
||||
rfxrects[index].x = x;
|
||||
rfxrects[index].y = y;
|
||||
rfxrects[index].cx = cx;
|
||||
rfxrects[index].cy = cy;
|
||||
}
|
||||
|
||||
error = rfxcodec_encode(self->codec_handle, out_data + 256, &out_data_bytes,
|
||||
enc->data, enc->width, enc->height, enc->width * 4,
|
||||
rfxrects, enc->num_drects,
|
||||
tiles, enc->num_crects, 0, 0);
|
||||
LLOGLN(10, ("process_enc_rfx: rfxcodec_encode rv %d", error));
|
||||
|
||||
enc_done = (XRDP_ENC_DATA_DONE *)
|
||||
g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1);
|
||||
enc_done->comp_bytes = out_data_bytes;
|
||||
enc_done->pad_bytes = 256;
|
||||
enc_done->comp_pad_data = out_data;
|
||||
enc_done->enc = enc;
|
||||
enc_done->last = 1;
|
||||
enc_done->cx = self->wm->screen->width;
|
||||
enc_done->cy = self->wm->screen->height;
|
||||
|
||||
/* done with msg */
|
||||
/* inform main thread done */
|
||||
tc_mutex_lock(mutex);
|
||||
fifo_add_item(fifo_processed, enc_done);
|
||||
tc_mutex_unlock(mutex);
|
||||
/* signal completion for main thread */
|
||||
g_set_wait_obj(event_processed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*****************************************************************************/
|
||||
/* called from encoder thread */
|
||||
static int
|
||||
process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Encoder thread main loop
|
||||
*****************************************************************************/
|
||||
THREAD_RV THREAD_CC
|
||||
proc_enc_msg(void *arg)
|
||||
{
|
||||
XRDP_ENC_DATA *enc;
|
||||
FIFO *fifo_to_proc;
|
||||
tbus mutex;
|
||||
tbus event_to_proc;
|
||||
tbus term_obj;
|
||||
tbus lterm_obj;
|
||||
int robjs_count;
|
||||
int wobjs_count;
|
||||
int cont;
|
||||
int timeout;
|
||||
tbus robjs[32];
|
||||
tbus wobjs[32];
|
||||
struct xrdp_mm *self;
|
||||
|
||||
LLOGLN(0, ("proc_enc_msg: thread is running"));
|
||||
|
||||
self = (struct xrdp_mm *) arg;
|
||||
if (self == 0)
|
||||
{
|
||||
LLOGLN(0, ("proc_enc_msg: self nil"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
fifo_to_proc = self->fifo_to_proc;
|
||||
mutex = self->mutex;
|
||||
event_to_proc = self->xrdp_encoder_event_to_proc;
|
||||
|
||||
term_obj = g_get_term_event();
|
||||
lterm_obj = self->xrdp_encoder_term;
|
||||
|
||||
cont = 1;
|
||||
while (cont)
|
||||
{
|
||||
timeout = -1;
|
||||
robjs_count = 0;
|
||||
wobjs_count = 0;
|
||||
robjs[robjs_count++] = term_obj;
|
||||
robjs[robjs_count++] = lterm_obj;
|
||||
robjs[robjs_count++] = event_to_proc;
|
||||
|
||||
if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
|
||||
{
|
||||
/* error, should not get here */
|
||||
g_sleep(100);
|
||||
}
|
||||
|
||||
if (g_is_wait_obj_set(term_obj)) /* global term */
|
||||
{
|
||||
LLOGLN(0, ("proc_enc_msg: global term"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_is_wait_obj_set(lterm_obj)) /* xrdp_mm term */
|
||||
{
|
||||
LLOGLN(0, ("proc_enc_msg: xrdp_mm term"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_is_wait_obj_set(event_to_proc))
|
||||
{
|
||||
/* clear it right away */
|
||||
g_reset_wait_obj(event_to_proc);
|
||||
/* get first msg */
|
||||
tc_mutex_lock(mutex);
|
||||
enc = (XRDP_ENC_DATA *) fifo_remove_item(fifo_to_proc);
|
||||
tc_mutex_unlock(mutex);
|
||||
while (enc != 0)
|
||||
{
|
||||
/* do work */
|
||||
self->process_enc(self, enc);
|
||||
/* get next msg */
|
||||
tc_mutex_lock(mutex);
|
||||
enc = (XRDP_ENC_DATA *) fifo_remove_item(fifo_to_proc);
|
||||
tc_mutex_unlock(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
} /* end while (cont) */
|
||||
LLOGLN(0, ("proc_enc_msg: thread exit"));
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
|
||||
#ifndef _XRDP_ENCODER_H
|
||||
#define _XRDP_ENCODER_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
struct xrdp_mm;
|
||||
|
||||
int APP_CC
|
||||
init_xrdp_encoder(struct xrdp_mm *self);
|
||||
void APP_CC
|
||||
deinit_xrdp_encoder(struct xrdp_mm *self);
|
||||
THREAD_RV THREAD_CC
|
||||
proc_enc_msg(void *arg);
|
||||
|
||||
#endif
|
@ -0,0 +1,105 @@
|
||||
#
|
||||
# RDP Keyboard <-> X11 Keyboard layout map
|
||||
#
|
||||
# How this file works:
|
||||
# 1. load the file and scan each section to find matching "keyboard_type"
|
||||
# and "keyboard_subtype" based on the values received from the client.
|
||||
# If not found, then jump to default section.
|
||||
# 2. in the selected section, look for "rdp_layouts" and "layouts_map".
|
||||
# Based on the "keylayout" value from the client, find the right x11
|
||||
# layout value.
|
||||
# 3. model/variant are inferred based on the "keyboard_type" and
|
||||
# "keyboard_subtype", but they can be overridden.
|
||||
#
|
||||
|
||||
#
|
||||
# RDP Keyboard Type (http://msdn.microsoft.com/en-us/library/cc240563.aspx)
|
||||
#
|
||||
# 0 is not a valid value
|
||||
#
|
||||
# 1 - IBM PC/XT or compatible (83-key) keyboard
|
||||
# 2 - Olivetti "ICO" (102-key) keyboard
|
||||
# 3 - IBM PC/AT (84-key) or similar keyboard
|
||||
# 4 - IBM enhanced (101- or 102-key) keyboard
|
||||
# 5 - Nokia 1050 and similar keyboards
|
||||
# 6 - Nokia 9140 and similar keyboards
|
||||
# 7 - Japanese keyboard
|
||||
#
|
||||
# RDP Keyboard Subtype is vendor dependent. XRDP defines as follows:
|
||||
#
|
||||
# 0 is not a valid value
|
||||
#
|
||||
# 1 - Standard
|
||||
# 2 - FreeRDP JP keyboard
|
||||
# 3 - Macintosh
|
||||
# ... - < any vendor dependent subtype >
|
||||
#
|
||||
# The list can be augmented.
|
||||
#
|
||||
|
||||
|
||||
# default
|
||||
[default]
|
||||
# keyboard_type and keyboard_subtype is not readed for default section. It
|
||||
# is only as a place holder to keep consistency. Default model/variant are
|
||||
# platform dependent, and could be overridden if needed.
|
||||
keyboard_type=0
|
||||
keyboard_subtype=0
|
||||
|
||||
# user could override variant and model, but generally they should be inferred
|
||||
# automatically based on keyboard type and subtype
|
||||
#variant=
|
||||
#model=
|
||||
|
||||
# A list of supported RDP keyboard layouts
|
||||
rdp_layouts=default_rdp_layouts
|
||||
# The map from RDP keyboard layout to X11 keyboard layout
|
||||
layouts_map=default_layouts_map
|
||||
|
||||
[default_rdp_layouts]
|
||||
rdp_layout_us=0x00000409
|
||||
rdp_layout_de=0x00000407
|
||||
rdp_layout_fr=0x0000040C
|
||||
rdp_layout_it=0x00000410
|
||||
rdp_layout_jp=0x00000411
|
||||
rdp_layout_ru=0x00000419
|
||||
rdp_layout_se=0x0000041D
|
||||
rdp_layout_pt=0x00000816
|
||||
rdp_layout_br=0x00000416
|
||||
|
||||
# <rdp layout name> = <X11 keyboard layout value>
|
||||
[default_layouts_map]
|
||||
rdp_layout_us=us
|
||||
rdp_layout_de=de
|
||||
rdp_layout_fr=fr
|
||||
rdp_layout_it=it
|
||||
rdp_layout_jp=jp
|
||||
rdp_layout_ru=ru
|
||||
rdp_layout_se=se
|
||||
rdp_layout_pt=pt
|
||||
rdp_layout_br=br(abnt2)
|
||||
|
||||
# if two sections have the same keyboard_type and keyboard_subtype, then
|
||||
# the latter could override the former.
|
||||
[rdp_keyboard_mac]
|
||||
keyboard_type=4
|
||||
keyboard_subtype=3
|
||||
rdp_layouts=default_rdp_layouts
|
||||
layouts_map=rdp_layouts_map_mac
|
||||
|
||||
[rdp_keyboard_jp]
|
||||
keyboard_type=7
|
||||
keyboard_subtype=2
|
||||
rdp_layouts=default_rdp_layouts
|
||||
layouts_map=default_layouts_map
|
||||
|
||||
[rdp_layouts_map_mac]
|
||||
rdp_layout_us=us
|
||||
rdp_layout_de=de
|
||||
rdp_layout_fr=fr
|
||||
rdp_layout_jp=jp
|
||||
rdp_layout_it=it
|
||||
rdp_layout_ru=ru
|
||||
rdp_layout_se=se
|
||||
rdp_layout_pt=pt
|
||||
rdp_layout_br=br(abnt2)
|
Loading…
Reference in new issue