gstreamer/sys/d3dvideosink/directx/dx.c
2012-09-11 15:12:55 +02:00

282 lines
6.9 KiB
C

/* GStreamer
* Copyright (C) 2011 David Hoyt <dhoyt@hoytsoft.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <glib.h>
#include <glib/gprintf.h>
#include <gmodule.h>
#include "dx.h"
#include "directx9/dx9.h"
#include "directx10/dx10.h"
#include "directx11/dx11.h"
static void
init_supported_apis (void)
{
/* Gather information we'll need about each version of DirectX. */
/* Insert in reverse order of desired priority due to the g_list_prepend() call in directx_determine_best_available_api(). */
INITIALIZE_SUPPORTED_DIRECTX_API (DIRECTX_9);
/* TODO: Add DirectX 10 support. */
/*INITIALIZE_SUPPORTED_DIRECTX_API(DIRECTX_10); */
/* TODO: Add DirectX 11 support. */
/*INITIALIZE_SUPPORTED_DIRECTX_API(DIRECTX_11); */
}
/* Function declarations */
static DirectXAPI *directx_determine_best_available_api (void);
/* Mutex macros */
#define DIRECTX_LOCK g_rec_mutex_lock (&dx_lock);
#define DIRECTX_UNLOCK g_rec_mutex_unlock (&dx_lock);
typedef struct _DirectXInfo DirectXInfo;
struct _DirectXInfo
{
gboolean initialized;
gboolean supported;
DirectXInitParams *init_params;
DirectXAPI *best_api;
GList *supported_api_list;
gint32 supported_api_count;
};
/* Private vars */
static DirectXInfo dx;
static GRecMutex dx_lock;
gboolean
directx_initialize (DirectXInitParams * init_params)
{
DIRECTX_LOCK if (dx.initialized)
goto success;
dx.init_params = NULL;
dx.init_params = init_params;
init_supported_apis ();
dx.best_api = directx_determine_best_available_api ();
dx.supported = (dx.best_api != NULL
&& !DIRECTX_VERSION_IS_UNKNOWN (dx.best_api->version));
dx.initialized = TRUE;
success:
DIRECTX_UNLOCK return TRUE;
}
gboolean
directx_api_initialize (DirectXAPI * api)
{
if (!api)
return FALSE;
DIRECTX_LOCK if (!directx_is_initialized ())
goto error;
if (api->initialized)
goto success;
/* API init */
api->initialize (api);
/* Component initialization */
DIRECTX_COMPONENT_INIT (DIRECTX_D3D (api));
DIRECTX_COMPONENT_INIT (DIRECTX_DINPUT (api));
DIRECTX_COMPONENT_INIT (DIRECTX_DSOUND (api));
DIRECTX_COMPONENT_INIT (DIRECTX_DWRITE (api));
DIRECTX_COMPONENT_INIT (DIRECTX_D2D (api));
DIRECTX_COMPONENT_INIT (DIRECTX_DCOMPUTE (api));
/* All done */
api->initialized = TRUE;
success:
DIRECTX_UNLOCK return TRUE;
error:
DIRECTX_UNLOCK return FALSE;
}
gboolean
directx_initialize_best_available_api (void)
{
return directx_api_initialize (directx_get_best_available_api ());
}
gboolean
directx_is_initialized (void)
{
gboolean initialized = FALSE;
DIRECTX_LOCK initialized = dx.initialized;
DIRECTX_UNLOCK return initialized;
}
gboolean
directx_api_is_initialized (const DirectXAPI * api)
{
if (!api)
return FALSE;
{
gboolean initialized;
DIRECTX_LOCK initialized = api->initialized;
DIRECTX_UNLOCK return initialized;
}
}
gboolean
directx_best_available_api_is_initialized (void)
{
return directx_api_is_initialized (directx_get_best_available_api ());
}
gboolean
directx_is_supported (void)
{
return dx.supported;
}
GList *
directx_get_supported_apis (void)
{
return dx.supported_api_list;
}
gint32
directx_get_supported_api_count (void)
{
return dx.supported_api_count;
}
DirectXAPI *
directx_get_best_available_api (void)
{
return dx.best_api;
}
void
directx_log_debug (const gchar * file, const gchar * function, gint line,
const gchar * format, ...)
{
if (!dx.init_params || !dx.init_params->log_debug)
return;
{
va_list args;
va_start (args, format);
dx.init_params->log_debug (file, function, line, format, args);
va_end (args);
}
}
void
directx_log_warning (const gchar * file, const gchar * function, gint line,
const gchar * format, ...)
{
if (!dx.init_params || !dx.init_params->log_warning)
return;
{
va_list args;
va_start (args, format);
dx.init_params->log_warning (file, function, line, format, args);
va_end (args);
}
}
void
directx_log_error (const gchar * file, const gchar * function, gint line,
const gchar * format, ...)
{
if (!dx.init_params || !dx.init_params->log_error)
return;
{
va_list args;
va_start (args, format);
dx.init_params->log_error (file, function, line, format, args);
va_end (args);
}
}
/* This should only be called through use of the DIRECTX_API() macro. It should never be called directly. */
gboolean
directx_add_supported_api (DirectXAPI * api)
{
if (!api)
return FALSE;
DIRECTX_LOCK {
/* Add to our GList containing all of our supported APIs. */
/* GLists are doubly-linked lists and calling prepend() prevents it from having to traverse the entire list just to add one item. */
dx.supported_api_list = g_list_prepend (dx.supported_api_list, api);
dx.supported_api_count++;
}
/*success:*/
DIRECTX_UNLOCK return TRUE;
}
static DirectXAPI *
directx_determine_best_available_api (void)
{
if (!g_module_supported ())
return NULL;
{
GList *item;
GModule *lib;
DirectXAPI *dxlib = NULL;
DIRECTX_LOCK {
/* Search supported APIs (DirectX9, DirectX10, etc.) looking for the first one that works. */
DIRECTX_DEBUG
("Searching supported DirectX APIs for the best (most recent) one available");
for (item = g_list_first (dx.supported_api_list); item; item = item->next) {
if ((dxlib = (DirectXAPI *) item->data) == NULL)
continue;
DIRECTX_DEBUG ("Determining support for %s", dxlib->description);
DIRECTX_DEBUG ("Searching for module \"%s\" with the symbol \"%s\"",
dxlib->module_test, dxlib->symbol_test);
/* Can we locate and open a Direct3D library (e.g. d3d9.dll or d3d10.dll)? */
if ((lib =
g_module_open (dxlib->module_test,
G_MODULE_BIND_LAZY)) != NULL) {
/* Look for a symbol/function (e.g. "Direct3DCreate9") in the module and if it exists, we found one! */
gpointer symbol;
if (g_module_symbol (lib, dxlib->symbol_test, &symbol)) {
g_module_close (lib);
DIRECTX_DEBUG ("Selected %s", dxlib->description);
goto done;
}
/* Ensure we don't have a mem leak. */
g_module_close (lib);
}
}
}
done:
DIRECTX_UNLOCK return dxlib;
}
}