]> git.cworth.org Git - apitrace/blob - wrappers/gltrace_state.cpp
Fix build. Add copyright header to new files.
[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 #include <tr1/memory>
32
33 #include <gltrace.hpp>
34 #include <os_thread.hpp>
35
36 namespace gltrace {
37
38 typedef std::tr1::shared_ptr<Context> context_ptr_t;
39 static std::map<uintptr_t, context_ptr_t> context_map;
40 static os::recursive_mutex context_map_mutex;
41
42 class ThreadState {
43 public:
44     context_ptr_t current_context;
45     context_ptr_t dummy_context;     /*
46                                       * For cases when there is no current
47                                       * context, but the app still calls some
48                                       * GL function that expects one.
49                                       */
50     ThreadState() : dummy_context(new Context)
51     {
52         current_context = dummy_context;
53     }
54 };
55
56 static os::thread_specific_ptr<struct ThreadState> thread_state;
57
58 static ThreadState *get_ts(void)
59 {
60     ThreadState *ts = thread_state.get();
61
62     if (!ts) {
63         ts = new ThreadState;
64         thread_state.reset(ts);
65     }
66
67     return ts;
68 }
69
70 static void _retainContext(context_ptr_t ctx)
71 {
72     ctx->retain_count++;
73 }
74
75 void retainContext(uintptr_t context_id)
76 {
77     context_map_mutex.lock();
78     if (context_map.find(context_id) != context_map.end())
79         _retainContext(context_map[context_id]);
80     context_map_mutex.unlock();
81 }
82
83 static bool _releaseContext(context_ptr_t ctx)
84 {
85     return !(--ctx->retain_count);
86 }
87
88 /*
89  * return true if the context was destroyed, false if only its refcount
90  * got decreased. Note that even if the context was destroyed it may
91  * still live, if it's the currently selected context (by setContext).
92  */
93 bool releaseContext(uintptr_t context_id)
94 {
95     bool res;
96
97     context_map_mutex.lock();
98     /*
99      * This can potentially called (from glX) with an invalid context_id,
100      * so don't assert on it being valid.
101      */
102     if (context_map.find(context_id) != context_map.end()) {
103         res = _releaseContext(context_map[context_id]);
104         if (res)
105             context_map.erase(context_id);
106     }
107     context_map_mutex.unlock();
108
109     return res;
110 }
111
112 void createContext(uintptr_t context_id)
113 {
114     context_ptr_t ctx(new Context);
115
116     context_map_mutex.lock();
117
118     _retainContext(ctx);
119     assert(context_map.find(context_id) == context_map.end());
120     context_map[context_id] = ctx;
121
122     context_map_mutex.unlock();
123 }
124
125 /*
126  * return true if the context has been destroyed, false otherwise. See
127  * the note at releaseContext about the actual ccontext lifetime.
128  */
129 bool destroyContext(uintptr_t context_id)
130 {
131     return releaseContext(context_id);
132 }
133
134 void setContext(uintptr_t context_id)
135 {
136     ThreadState *ts = get_ts();
137     context_ptr_t ctx;
138
139     context_map_mutex.lock();
140
141     assert(context_map.find(context_id) != context_map.end());
142     ctx = context_map[context_id];
143
144     context_map_mutex.unlock();
145
146     ts->current_context = ctx;
147 }
148
149 void clearContext(void)
150 {
151     ThreadState *ts = get_ts();
152
153     ts->current_context = ts->dummy_context;
154 }
155
156 Context *getContext(void)
157 {
158     return get_ts()->current_context.get();
159 }
160
161 }