X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;ds=sidebyside;f=wrappers%2Fgltrace_state.cpp;h=a8476b04c1bb247b9fb1131eb2c81852f7723896;hb=b79fe3d2e482c492248d96da992f8fabcd9fe8cd;hp=6b73d7a8d068498647dd27e41414b5e0a0689eef;hpb=e90cac47697d2c26ac3a6d5292de101519b46f95;p=apitrace diff --git a/wrappers/gltrace_state.cpp b/wrappers/gltrace_state.cpp index 6b73d7a..a8476b0 100644 --- a/wrappers/gltrace_state.cpp +++ b/wrappers/gltrace_state.cpp @@ -1,10 +1,183 @@ +/********************************************************************* + * + * Copyright 2012 Intel Corporation + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + *********************************************************************/ + +#include + +#include +#if defined(_MSC_VER) +#include +#else +#include +#endif + +#include +#include #include -gltrace::Context * -gltrace::getContext(void) +namespace gltrace { + +typedef std::tr1::shared_ptr context_ptr_t; +static std::map context_map; +static os::recursive_mutex context_map_mutex; + +class ThreadState { +public: + context_ptr_t current_context; + context_ptr_t dummy_context; /* + * For cases when there is no current + * context, but the app still calls some + * GL function that expects one. + */ + ThreadState() : dummy_context(new Context) + { + current_context = dummy_context; + } +}; + +static OS_THREAD_SPECIFIC_PTR(ThreadState) thread_state; + +static ThreadState *get_ts(void) +{ + ThreadState *ts = thread_state; + if (!ts) { + thread_state = ts = new ThreadState; + } + + return ts; +} + +static void _retainContext(context_ptr_t ctx) +{ + ctx->retain_count++; +} + +void retainContext(uintptr_t context_id) +{ + context_map_mutex.lock(); + if (context_map.find(context_id) != context_map.end()) + _retainContext(context_map[context_id]); + context_map_mutex.unlock(); +} + +static bool _releaseContext(context_ptr_t ctx) +{ + return !(--ctx->retain_count); +} + +/* + * return true if the context was destroyed, false if only its refcount + * got decreased. Note that even if the context was destroyed it may + * still live, if it's the currently selected context (by setContext). + */ +bool releaseContext(uintptr_t context_id) +{ + bool res = false; + + context_map_mutex.lock(); + /* + * This can potentially called (from glX) with an invalid context_id, + * so don't assert on it being valid. + */ + if (context_map.find(context_id) != context_map.end()) { + res = _releaseContext(context_map[context_id]); + if (res) + context_map.erase(context_id); + } + context_map_mutex.unlock(); + + return res; +} + +void createContext(uintptr_t context_id) { - // TODO return the context set by other APIs (GLX, EGL, and etc.) - static gltrace::Context _ctx = { gltrace::PROFILE_COMPAT, false, false, false }; - return &_ctx; + // wglCreateContextAttribsARB causes internal calls to wglCreateContext to be + // traced, causing context to be defined twice. + if (context_map.find(context_id) != context_map.end()) { + return; + } + + context_ptr_t ctx(new Context); + + context_map_mutex.lock(); + + _retainContext(ctx); + context_map[context_id] = ctx; + + context_map_mutex.unlock(); } +void setContext(uintptr_t context_id) +{ + ThreadState *ts = get_ts(); + context_ptr_t ctx; + + context_map_mutex.lock(); + + assert(context_map.find(context_id) != context_map.end()); + ctx = context_map[context_id]; + + context_map_mutex.unlock(); + + ts->current_context = ctx; + + if (!ctx->bound) { + ctx->bound = true; + + /* + * The default viewport and scissor state is set when a context is + * first made current, with values matching the bound drawable. Many + * applications never thouch the default state ever again. + * + * Since we currently don't trace window sizes, and rely on viewport + * calls to deduct, emit fake calls here so that viewport/scissor state + * can be deducated. + * + * FIXME: don't call the real functions here -- just emit the fake + * calls. + */ + GLint viewport[4] = {0, 0, 0, 0}; + GLint scissor_box[4] = {0, 0, 0, 0}; + _glGetIntegerv(GL_VIEWPORT, viewport); + _glGetIntegerv(GL_SCISSOR_BOX, scissor_box); + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]); + } +} + +void clearContext(void) +{ + ThreadState *ts = get_ts(); + + ts->current_context = ts->dummy_context; +} + +Context *getContext(void) +{ + return get_ts()->current_context.get(); +} + +}