Tizen 2.0 Release
[framework/multimedia/gst-plugins-bad0.10.git] / sys / d3dvideosink / directx / dx.c
1 /* GStreamer
2  * Copyright (C) 2011 David Hoyt <dhoyt@hoytsoft.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <glib.h>
21 #include <glib/gprintf.h>
22 #include <gmodule.h>
23
24 #include "dx.h"
25 #include "directx9/dx9.h"
26 #include "directx10/dx10.h"
27 #include "directx11/dx11.h"
28
29
30
31 static void
32 init_supported_apis (void)
33 {
34   /* Gather information we'll need about each version of DirectX. */
35   /* Insert in reverse order of desired priority due to the g_list_prepend() call in directx_determine_best_available_api(). */
36   INITIALIZE_SUPPORTED_DIRECTX_API (DIRECTX_9);
37   /* TODO: Add DirectX 10 support. */
38   /*INITIALIZE_SUPPORTED_DIRECTX_API(DIRECTX_10); */
39   /* TODO: Add DirectX 11 support. */
40   /*INITIALIZE_SUPPORTED_DIRECTX_API(DIRECTX_11); */
41 }
42
43
44
45 /* Function declarations */
46 static DirectXAPI *directx_determine_best_available_api (void);
47
48 /* Mutex macros */
49 #define DIRECTX_LOCK      g_static_rec_mutex_lock (&dx_lock);
50 #define DIRECTX_UNLOCK  g_static_rec_mutex_unlock (&dx_lock);
51
52 typedef struct _DirectXInfo DirectXInfo;
53 struct _DirectXInfo
54 {
55   gboolean initialized;
56   gboolean supported;
57
58   DirectXInitParams *init_params;
59   DirectXAPI *best_api;
60   GList *supported_api_list;
61   gint32 supported_api_count;
62 };
63
64 /* Private vars */
65 static DirectXInfo dx;
66 static GStaticRecMutex dx_lock = G_STATIC_REC_MUTEX_INIT;
67
68 gboolean
69 directx_initialize (DirectXInitParams * init_params)
70 {
71   DIRECTX_LOCK if (dx.initialized)
72       goto success;
73
74   dx.init_params = NULL;
75   dx.init_params = init_params;
76
77   init_supported_apis ();
78
79   dx.best_api = directx_determine_best_available_api ();
80   dx.supported = (dx.best_api != NULL
81       && !DIRECTX_VERSION_IS_UNKNOWN (dx.best_api->version));
82   dx.initialized = TRUE;
83
84 success:
85   DIRECTX_UNLOCK return TRUE;
86 }
87
88 gboolean
89 directx_api_initialize (DirectXAPI * api)
90 {
91   if (!api)
92     return FALSE;
93
94   DIRECTX_LOCK if (!directx_is_initialized ())
95       goto error;
96
97   if (api->initialized)
98     goto success;
99
100   /* API init */
101   api->initialize (api);
102
103   /* Component initialization */
104   DIRECTX_COMPONENT_INIT (DIRECTX_D3D (api));
105   DIRECTX_COMPONENT_INIT (DIRECTX_DINPUT (api));
106   DIRECTX_COMPONENT_INIT (DIRECTX_DSOUND (api));
107   DIRECTX_COMPONENT_INIT (DIRECTX_DWRITE (api));
108   DIRECTX_COMPONENT_INIT (DIRECTX_D2D (api));
109   DIRECTX_COMPONENT_INIT (DIRECTX_DCOMPUTE (api));
110
111   /* All done */
112   api->initialized = TRUE;
113
114 success:
115   DIRECTX_UNLOCK return TRUE;
116 error:
117   DIRECTX_UNLOCK return FALSE;
118 }
119
120 gboolean
121 directx_initialize_best_available_api (void)
122 {
123   return directx_api_initialize (directx_get_best_available_api ());
124 }
125
126 gboolean
127 directx_is_initialized (void)
128 {
129   gboolean initialized = FALSE;
130
131   DIRECTX_LOCK initialized = dx.initialized;
132   DIRECTX_UNLOCK return initialized;
133 }
134
135 gboolean
136 directx_api_is_initialized (const DirectXAPI * api)
137 {
138   if (!api)
139     return FALSE;
140   {
141     gboolean initialized;
142
143     DIRECTX_LOCK initialized = api->initialized;
144     DIRECTX_UNLOCK return initialized;
145   }
146 }
147
148 gboolean
149 directx_best_available_api_is_initialized (void)
150 {
151   return directx_api_is_initialized (directx_get_best_available_api ());
152 }
153
154 gboolean
155 directx_is_supported (void)
156 {
157   return dx.supported;
158 }
159
160 GList *
161 directx_get_supported_apis (void)
162 {
163   return dx.supported_api_list;
164 }
165
166 gint32
167 directx_get_supported_api_count (void)
168 {
169   return dx.supported_api_count;
170 }
171
172 DirectXAPI *
173 directx_get_best_available_api (void)
174 {
175   return dx.best_api;
176 }
177
178 void
179 directx_log_debug (const gchar * file, const gchar * function, gint line,
180     const gchar * format, ...)
181 {
182   if (!dx.init_params || !dx.init_params->log_debug)
183     return;
184   {
185     va_list args;
186     va_start (args, format);
187     dx.init_params->log_debug (file, function, line, format, args);
188     va_end (args);
189   }
190 }
191
192 void
193 directx_log_warning (const gchar * file, const gchar * function, gint line,
194     const gchar * format, ...)
195 {
196   if (!dx.init_params || !dx.init_params->log_warning)
197     return;
198   {
199     va_list args;
200     va_start (args, format);
201     dx.init_params->log_warning (file, function, line, format, args);
202     va_end (args);
203   }
204 }
205
206 void
207 directx_log_error (const gchar * file, const gchar * function, gint line,
208     const gchar * format, ...)
209 {
210   if (!dx.init_params || !dx.init_params->log_error)
211     return;
212   {
213     va_list args;
214     va_start (args, format);
215     dx.init_params->log_error (file, function, line, format, args);
216     va_end (args);
217   }
218 }
219
220 /* This should only be called through use of the DIRECTX_API() macro. It should never be called directly. */
221 gboolean
222 directx_add_supported_api (DirectXAPI * api)
223 {
224   if (!api)
225     return FALSE;
226
227   DIRECTX_LOCK {
228
229     /* Add to our GList containing all of our supported APIs. */
230     /* GLists are doubly-linked lists and calling prepend() prevents it from having to traverse the entire list just to add one item. */
231     dx.supported_api_list = g_list_prepend (dx.supported_api_list, api);
232     dx.supported_api_count++;
233
234   }
235 /*success:*/
236   DIRECTX_UNLOCK return TRUE;
237 }
238
239 static DirectXAPI *
240 directx_determine_best_available_api (void)
241 {
242   if (!g_module_supported ())
243     return NULL;
244
245   {
246     GList *item;
247     GModule *lib;
248     DirectXAPI *dxlib = NULL;
249
250     DIRECTX_LOCK {
251       /* Search supported APIs (DirectX9, DirectX10, etc.) looking for the first one that works. */
252       DIRECTX_DEBUG
253           ("Searching supported DirectX APIs for the best (most recent) one available");
254       for (item = g_list_first (dx.supported_api_list); item; item = item->next) {
255         if ((dxlib = (DirectXAPI *) item->data) == NULL)
256           continue;
257
258         DIRECTX_DEBUG ("Determining support for %s", dxlib->description);
259         DIRECTX_DEBUG ("Searching for module \"%s\" with the symbol \"%s\"",
260             dxlib->module_test, dxlib->symbol_test);
261
262         /* Can we locate and open a Direct3D library (e.g. d3d9.dll or d3d10.dll)? */
263         if ((lib =
264                 g_module_open (dxlib->module_test,
265                     G_MODULE_BIND_LAZY)) != NULL) {
266           /* Look for a symbol/function (e.g. "Direct3DCreate9") in the module and if it exists, we found one! */
267           gpointer symbol;
268           if (g_module_symbol (lib, dxlib->symbol_test, &symbol)) {
269             g_module_close (lib);
270             DIRECTX_DEBUG ("Selected %s", dxlib->description);
271             goto done;
272           }
273           /* Ensure we don't have a mem leak. */
274           g_module_close (lib);
275         }
276       }
277
278     }
279   done:
280     DIRECTX_UNLOCK return dxlib;
281   }
282 }