Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / common / debug.cpp
1 //
2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // debug.cpp: Debugging utilities.
8
9 #include "common/debug.h"
10 #include "common/platform.h"
11 #include "common/angleutils.h"
12
13 #include <stdarg.h>
14 #include <vector>
15 #include <fstream>
16 #include <cstdio>
17
18 namespace gl
19 {
20 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
21 // Wraps the D3D9/D3D11 debug annotation functions.
22 class DebugAnnotationWrapper
23 {
24   public:
25     DebugAnnotationWrapper() { };
26     virtual ~DebugAnnotationWrapper() { };
27     virtual void beginEvent(const std::wstring &eventName) = 0;
28     virtual void endEvent() = 0;
29     virtual void setMarker(const std::wstring &markerName) = 0;
30     virtual bool getStatus() = 0;
31 };
32
33 #if defined(ANGLE_ENABLE_D3D9)
34 class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
35 {
36   public:
37     void beginEvent(const std::wstring &eventName)
38     {
39         D3DPERF_BeginEvent(0, eventName.c_str());
40     }
41
42     void endEvent()
43     {
44         D3DPERF_EndEvent();
45     }
46
47     void setMarker(const std::wstring &markerName)
48     {
49         D3DPERF_SetMarker(0, markerName.c_str());
50     }
51
52     bool getStatus()
53     {
54         return !!D3DPERF_GetStatus();
55     }
56 };
57 #endif // ANGLE_ENABLE_D3D9
58
59 #if defined(ANGLE_ENABLE_D3D11)
60 class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
61 {
62   public:
63
64     D3D11DebugAnnotationWrapper()
65       : mInitialized(false),
66         mD3d11Module(NULL),
67         mUserDefinedAnnotation(NULL)
68     {
69         // D3D11 devices can't be created during DllMain.
70         // We defer device creation until the object is actually used.
71     }
72
73     ~D3D11DebugAnnotationWrapper()
74     {
75         if (mInitialized)
76         {
77             SafeRelease(mUserDefinedAnnotation);
78             FreeLibrary(mD3d11Module);
79         }
80     }
81
82     virtual void beginEvent(const std::wstring &eventName)
83     {
84         initializeDevice();
85
86         mUserDefinedAnnotation->BeginEvent(eventName.c_str());
87     }
88
89     virtual void endEvent()
90     {
91         initializeDevice();
92
93         mUserDefinedAnnotation->EndEvent();
94     }
95
96     virtual void setMarker(const std::wstring &markerName)
97     {
98         initializeDevice();
99
100         mUserDefinedAnnotation->SetMarker(markerName.c_str());
101     }
102
103     virtual bool getStatus()
104     {
105         // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
106
107 #if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
108         // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
109         // This should only be called in DEBUG mode.
110         // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
111         IDXGraphicsAnalysis* graphicsAnalysis;
112         DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
113         bool underCapture = (graphicsAnalysis != NULL);
114         SafeRelease(graphicsAnalysis);
115         return underCapture;
116 #endif
117
118         // Otherwise, we have to return true here.
119         return true;
120     }
121
122   protected:
123
124     void initializeDevice()
125     {
126         if (!mInitialized)
127         {
128 #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
129             mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
130             ASSERT(mD3d11Module);
131
132             PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
133             ASSERT(D3D11CreateDevice != NULL);
134 #endif // !ANGLE_ENABLE_WINDOWS_STORE
135
136             ID3D11Device* device = NULL;
137             ID3D11DeviceContext* context = NULL;
138
139             HRESULT hr = E_FAIL;
140
141             // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
142             hr =  D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context);
143             ASSERT(SUCCEEDED(hr));
144
145             hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
146             ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
147
148             SafeRelease(device);
149             SafeRelease(context);
150
151             mInitialized = true;
152         }
153     }
154
155     bool mInitialized;
156     HMODULE mD3d11Module;
157     ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
158 };
159 #endif // ANGLE_ENABLE_D3D11
160
161 static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL;
162
163 void InitializeDebugAnnotations()
164 {
165 #if defined(ANGLE_ENABLE_D3D9)
166     g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper();
167 #elif defined(ANGLE_ENABLE_D3D11)
168     // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer.
169     // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations.
170     // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext.
171     // This doesn't have to be the same DeviceContext that the renderer uses, though.
172     g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper();
173 #endif
174 }
175
176 void UninitializeDebugAnnotations()
177 {
178     if (g_DebugAnnotationWrapper != NULL)
179     {
180         SafeDelete(g_DebugAnnotationWrapper);
181     }
182 }
183
184 #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
185
186 enum DebugTraceOutputType
187 {
188    DebugTraceOutputTypeNone,
189    DebugTraceOutputTypeSetMarker,
190    DebugTraceOutputTypeBeginEvent
191 };
192
193 static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
194 {
195 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
196     static std::vector<char> buffer(512);
197
198     if (perfActive())
199     {
200         size_t len = FormatStringIntoVector(format, vararg, buffer);
201         std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
202
203         switch (outputType)
204         {
205             case DebugTraceOutputTypeNone:
206                 break;
207             case DebugTraceOutputTypeBeginEvent:
208                 g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
209                 break;
210             case DebugTraceOutputTypeSetMarker:
211                 g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
212                 break;
213         }
214     }
215 #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
216
217 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
218 #if defined(NDEBUG)
219     if (traceInDebugOnly)
220     {
221         return;
222     }
223 #endif // NDEBUG
224     std::string formattedMessage = FormatString(format, vararg);
225
226     static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
227     if (file)
228     {
229         file.write(formattedMessage.c_str(), formattedMessage.length());
230         file.flush();
231     }
232
233 #if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
234     OutputDebugStringA(formattedMessage.c_str());
235 #endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
236
237 #endif // ANGLE_ENABLE_DEBUG_TRACE
238 }
239
240 void trace(bool traceInDebugOnly, const char *format, ...)
241 {
242     va_list vararg;
243     va_start(vararg, format);
244 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
245     output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
246 #else
247     output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
248 #endif
249     va_end(vararg);
250 }
251
252 bool perfActive()
253 {
254 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
255     static bool active = g_DebugAnnotationWrapper->getStatus();
256     return active;
257 #else
258     return false;
259 #endif
260 }
261
262 ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
263 {
264 #if !defined(ANGLE_ENABLE_DEBUG_TRACE)
265     if (!perfActive())
266     {
267         return;
268     }
269 #endif // !ANGLE_ENABLE_DEBUG_TRACE
270     va_list vararg;
271     va_start(vararg, format);
272 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
273     output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
274 #else
275     output(true, DebugTraceOutputTypeNone, format, vararg);
276 #endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
277     va_end(vararg);
278 }
279
280 ScopedPerfEventHelper::~ScopedPerfEventHelper()
281 {
282 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
283     if (perfActive())
284     {
285         g_DebugAnnotationWrapper->endEvent();
286     }
287 #endif
288 }
289 }