]> git.cworth.org Git - apitrace/blob - wrappers/gltrace_state.cpp
gltrace: Prevent use of uninitialised variable.
[apitrace] / wrappers / gltrace_state.cpp
1 /*********************************************************************
2  *
3  * Copyright 2012 Intel Corporation
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use, copy,
10  * modify, merge, publish, distribute, sublicense, and/or sell copies
11  * of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  *
26  *********************************************************************/
27
28 #include <assert.h>
29
30 #include <map>
31 #if defined(_MSC_VER)
32 #include <memory>
33 #else
34 #include <tr1/memory>
35 #endif
36
37 #include <gltrace.hpp>
38 #include <os_thread.hpp>
39
40 namespace gltrace {
41
42 typedef std::tr1::shared_ptr<Context> context_ptr_t;
43 static std::map<uintptr_t, context_ptr_t> context_map;
44 static os::recursive_mutex context_map_mutex;
45
46 class ThreadState {
47 public:
48     context_ptr_t current_context;
49     context_ptr_t dummy_context;     /*
50                                       * For cases when there is no current
51                                       * context, but the app still calls some
52                                       * GL function that expects one.
53                                       */
54     ThreadState() : dummy_context(new Context)
55     {
56         current_context = dummy_context;
57     }
58 };
59
60 static thread_specific ThreadState *thread_state;
61
62 static ThreadState *get_ts(void)
63 {
64     ThreadState *ts = thread_state;
65     if (!ts) {
66         thread_state = ts = new ThreadState;
67     }
68
69     return ts;
70 }
71
72 static void _retainContext(context_ptr_t ctx)
73 {
74     ctx->retain_count++;
75 }
76
77 void retainContext(uintptr_t context_id)
78 {
79     context_map_mutex.lock();
80     if (context_map.find(context_id) != context_map.end())
81         _retainContext(context_map[context_id]);
82     context_map_mutex.unlock();
83 }
84
85 static bool _releaseContext(context_ptr_t ctx)
86 {
87     return !(--ctx->retain_count);
88 }
89
90 /*
91  * return true if the context was destroyed, false if only its refcount
92  * got decreased. Note that even if the context was destroyed it may
93  * still live, if it's the currently selected context (by setContext).
94  */
95 bool releaseContext(uintptr_t context_id)
96 {
97     bool res = false;
98
99     context_map_mutex.lock();
100     /*
101      * This can potentially called (from glX) with an invalid context_id,
102      * so don't assert on it being valid.
103      */
104     if (context_map.find(context_id) != context_map.end()) {
105         res = _releaseContext(context_map[context_id]);
106         if (res)
107             context_map.erase(context_id);
108     }
109     context_map_mutex.unlock();
110
111     return res;
112 }
113
114 void createContext(uintptr_t context_id)
115 {
116     // wglCreateContextAttribsARB causes internal calls to wglCreateContext to be
117     // traced, causing context to be defined twice.
118     if (context_map.find(context_id) != context_map.end()) {
119         return;
120     }
121
122     context_ptr_t ctx(new Context);
123
124     context_map_mutex.lock();
125
126     _retainContext(ctx);
127     context_map[context_id] = ctx;
128
129     context_map_mutex.unlock();
130 }
131
132 void setContext(uintptr_t context_id)
133 {
134     ThreadState *ts = get_ts();
135     context_ptr_t ctx;
136
137     context_map_mutex.lock();
138
139     assert(context_map.find(context_id) != context_map.end());
140     ctx = context_map[context_id];
141
142     context_map_mutex.unlock();
143
144     ts->current_context = ctx;
145 }
146
147 void clearContext(void)
148 {
149     ThreadState *ts = get_ts();
150
151     ts->current_context = ts->dummy_context;
152 }
153
154 Context *getContext(void)
155 {
156     return get_ts()->current_context.get();
157 }
158
159 }