1 /*********************************************************************
3 * Copyright 2012 Intel Corporation
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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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
26 *********************************************************************/
37 #include <os_thread.hpp>
39 #include <gltrace.hpp>
43 typedef std::tr1::shared_ptr<Context> context_ptr_t;
44 static std::map<uintptr_t, context_ptr_t> context_map;
45 static os::recursive_mutex context_map_mutex;
49 context_ptr_t current_context;
50 context_ptr_t dummy_context; /*
51 * For cases when there is no current
52 * context, but the app still calls some
53 * GL function that expects one.
55 ThreadState() : dummy_context(new Context)
57 current_context = dummy_context;
61 static OS_THREAD_SPECIFIC_PTR(ThreadState) thread_state;
63 static ThreadState *get_ts(void)
65 ThreadState *ts = thread_state;
67 thread_state = ts = new ThreadState;
73 static void _retainContext(context_ptr_t ctx)
78 void retainContext(uintptr_t context_id)
80 context_map_mutex.lock();
81 if (context_map.find(context_id) != context_map.end())
82 _retainContext(context_map[context_id]);
83 context_map_mutex.unlock();
86 static bool _releaseContext(context_ptr_t ctx)
88 return !(--ctx->retain_count);
92 * return true if the context was destroyed, false if only its refcount
93 * got decreased. Note that even if the context was destroyed it may
94 * still live, if it's the currently selected context (by setContext).
96 bool releaseContext(uintptr_t context_id)
100 context_map_mutex.lock();
102 * This can potentially called (from glX) with an invalid context_id,
103 * so don't assert on it being valid.
105 if (context_map.find(context_id) != context_map.end()) {
106 res = _releaseContext(context_map[context_id]);
108 context_map.erase(context_id);
110 context_map_mutex.unlock();
115 void createContext(uintptr_t context_id)
117 // wglCreateContextAttribsARB causes internal calls to wglCreateContext to be
118 // traced, causing context to be defined twice.
119 if (context_map.find(context_id) != context_map.end()) {
123 context_ptr_t ctx(new Context);
125 context_map_mutex.lock();
128 context_map[context_id] = ctx;
130 context_map_mutex.unlock();
133 void setContext(uintptr_t context_id)
135 ThreadState *ts = get_ts();
138 context_map_mutex.lock();
140 assert(context_map.find(context_id) != context_map.end());
141 ctx = context_map[context_id];
143 context_map_mutex.unlock();
145 ts->current_context = ctx;
151 * The default viewport and scissor state is set when a context is
152 * first made current, with values matching the bound drawable. Many
153 * applications never thouch the default state ever again.
155 * Since we currently don't trace window sizes, and rely on viewport
156 * calls to deduct, emit fake calls here so that viewport/scissor state
159 * FIXME: don't call the real functions here -- just emit the fake
162 GLint viewport[4] = {0, 0, 0, 0};
163 GLint scissor_box[4] = {0, 0, 0, 0};
164 _glGetIntegerv(GL_VIEWPORT, viewport);
165 _glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
166 glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
167 glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
171 void clearContext(void)
173 ThreadState *ts = get_ts();
175 ts->current_context = ts->dummy_context;
178 Context *getContext(void)
180 return get_ts()->current_context.get();