void GFXGLAppleFence::block() { if(!mIssued) return; glFinishFenceAPPLE(mHandle); }
enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query, const struct wined3d_device *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; TRACE("(%p)\n", query); if (!query->context) { TRACE("Query not started\n"); return WINED3D_EVENT_QUERY_NOT_STARTED; } gl_info = query->context->gl_info; if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC]) { /* A glFinish does not reliably wait for draws in other contexts. The caller has * to find its own way to cope with the thread switch */ WARN("Event query finished from wrong thread\n"); return WINED3D_EVENT_QUERY_WRONG_THREAD; } context = context_acquire(device, query->context->current_rt); if (gl_info->supported[ARB_SYNC]) { /* Apple seems to be into arbitrary limits, and timeouts larger than * 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't * really care and can live with waiting a few μs less. (OS X 10.7.4). */ GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff)); checkGLcall("glClientWaitSync"); switch (gl_ret) { case GL_ALREADY_SIGNALED: case GL_CONDITION_SATISFIED: ret = WINED3D_EVENT_QUERY_OK; break; /* We don't expect a timeout for a ~584 year wait */ default: ERR("glClientWaitSync returned %#x.\n", gl_ret); ret = WINED3D_EVENT_QUERY_ERROR; } } else if (context->gl_info->supported[APPLE_FENCE]) { GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); checkGLcall("glFinishFenceAPPLE"); ret = WINED3D_EVENT_QUERY_OK; } else if (context->gl_info->supported[NV_FENCE]) { GL_EXTCALL(glFinishFenceNV(query->object.id)); checkGLcall("glFinishFenceNV"); ret = WINED3D_EVENT_QUERY_OK; } else { ERR("Event query created without GL support\n"); ret = WINED3D_EVENT_QUERY_ERROR; } context_release(context); return ret; }
enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; enum wined3d_event_query_result ret; TRACE("(%p)\n", query); if (!query->context) { TRACE("Query not started\n"); return WINED3D_EVENT_QUERY_NOT_STARTED; } gl_info = query->context->gl_info; if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC]) { /* A glFinish does not reliably wait for draws in other contexts. The caller has * to find its own way to cope with the thread switch */ WARN("Event query finished from wrong thread\n"); return WINED3D_EVENT_QUERY_WRONG_THREAD; } context = context_acquire(device, query->context->current_rt); ENTER_GL(); if (gl_info->supported[ARB_SYNC]) { GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, ~(GLuint64)0)); checkGLcall("glClientWaitSync"); switch (gl_ret) { case GL_ALREADY_SIGNALED: case GL_CONDITION_SATISFIED: ret = WINED3D_EVENT_QUERY_OK; break; /* We don't expect a timeout for a ~584 year wait */ default: ERR("glClientWaitSync returned %#x.\n", gl_ret); ret = WINED3D_EVENT_QUERY_ERROR; } } else if (context->gl_info->supported[APPLE_FENCE]) { GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); checkGLcall("glFinishFenceAPPLE"); ret = WINED3D_EVENT_QUERY_OK; } else if (context->gl_info->supported[NV_FENCE]) { GL_EXTCALL(glFinishFenceNV(query->object.id)); checkGLcall("glFinishFenceNV"); ret = WINED3D_EVENT_QUERY_OK; } else { ERR("Event query created without GL support\n"); ret = WINED3D_EVENT_QUERY_ERROR; } LEAVE_GL(); context_release(context); return ret; }
void CGLMQuery::Complete( uint *result ) { m_ctx->MakeCurrent(); uint resultval = 0; GLint available = 0; bool bogus_available = false; // blocking call if not done Assert(m_started); Assert(m_stopped); switch(m_params.m_type) { case EOcclusion: { if (m_nullQuery) { m_done = true; resultval = 0; // we did say "null queries..." } else { // accept that the query is going to drain pipe in 10.6.4 and prior. // check the error on the spot. glGetQueryObjectivARB(m_name, GL_QUERY_RESULT_AVAILABLE_ARB, &available ); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::Complete saw %s error (%d) from glGetQueryObjectivARB GL_QUERY_RESULT_AVAILABLE_ARB name=%d", decodedStr, errorcode, m_name ); resultval=0; } else { if (!available) { // this does happen with some very modest frequency. if (!m_ctx->Caps().m_hasPerfPackage1) { glFlush(); // ISTR some deadlock cases on pre-SLGU drivers if you didn't do this to kick the queue along.. } } glGetQueryObjectuivARB( m_name, GL_QUERY_RESULT_ARB, &resultval); errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::Complete saw %s error (%d) from glGetQueryObjectivARB GL_QUERY_RESULT_ARB name=%d", decodedStr, errorcode, m_name ); resultval=0; } else { // resultval is legit } } m_done = true; } } break; case EFence: { if(!m_done) { glFinishFenceAPPLE( m_name ); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::Complete saw %s error (%d) from glFinishFenceAPPLE (EFence) name=%d", decodedStr, errorcode, m_name ); } m_done = true; // for clarity or if they try to Complete twice } } break; } Assert( m_done ); // reset state for re-use - i.e. you have to call Complete if you want to re-use the object m_started = m_stopped = m_done = false; if (result) // caller may pass NULL if not interested in result, for example to clear a fence { *result = resultval; } }
bool CGLMQuery::IsDone( void ) { m_ctx->MakeCurrent(); Assert(m_started); Assert(m_stopped); if(!m_done) // you can ask more than once, but we only check until it comes back as done. { // on occlusion: glGetQueryObjectivARB - large cost on pre SLGU, cheap after // on fence: glTestFenceAPPLE on the fence switch(m_params.m_type) { case EOcclusion: // just test the fence that was set after the query begin { if (m_nullQuery) { // do almost nothing.. but claim work is complete m_done = true; } else { // prepare to pay a big price on drivers prior to 10.6.4+SLGU GLint available = 0; glGetQueryObjectivARB(m_name, GL_QUERY_RESULT_AVAILABLE_ARB, &available ); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::IsDone saw %s error (%d) from glGetQueryObjectivARB(a2) name=%d", decodedStr, errorcode, m_name ); } m_done = (available != 0); } } break; case EFence: { m_done = glTestFenceAPPLE( m_name ); GLenum errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::IsDone saw %s error (%d) from glTestFenceAPPLE(b) name=%d", decodedStr, errorcode, m_name ); } if (m_done) { glFinishFenceAPPLE( m_name ); // no set fence goes un-finished errorcode = GetQueryError(); if (errorcode) { const char *decodedStr = GLMDecode( eGL_ERROR, errorcode ); printf( "\nCGLMQuery::IsDone saw %s error (%d) from glFinishFenceAPPLE(b) name=%d", decodedStr, errorcode, m_name ); } } } break; } } return m_done; }