query.c 22.6 KB
Newer Older
1 2 3 4
/*
 * IWineD3DQuery implementation
 *
 * Copyright 2005 Oliver Stieber
5
 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
6
 * Copyright 2009 Henri Verbeet for CodeWeavers.
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24 25 26 27
 */


#include "config.h"
#include "wined3d_private.h"

/*
28 29 30 31
 * Occlusion Queries:
 * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf
 * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt
 */
32 33

WINE_DEFAULT_DEBUG_CHANNEL(d3d);
34
#define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
35 36 37 38

/* *******************************************
   IWineD3DQuery IUnknown parts follow
   ******************************************* */
39
static HRESULT  WINAPI IWineD3DQueryImpl_QueryInterface(IWineD3DQuery *iface, REFIID riid, LPVOID *ppobj)
40 41 42 43
{
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
    if (IsEqualGUID(riid, &IID_IUnknown)
44
        || IsEqualGUID(riid, &IID_IWineD3DBase)
45 46 47
        || IsEqualGUID(riid, &IID_IWineD3DQuery)) {
        IUnknown_AddRef(iface);
        *ppobj = This;
48
        return S_OK;
49
    }
50
    *ppobj = NULL;
51 52 53
    return E_NOINTERFACE;
}

54
static ULONG  WINAPI IWineD3DQueryImpl_AddRef(IWineD3DQuery *iface) {
55
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
56
    TRACE("(%p) : AddRef increasing from %d\n", This, This->ref);
57 58 59
    return InterlockedIncrement(&This->ref);
}

60
static ULONG  WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
61 62
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
    ULONG ref;
63
    TRACE("(%p) : Releasing from %d\n", This, This->ref);
64 65
    ref = InterlockedDecrement(&This->ref);
    if (ref == 0) {
66 67 68 69
        /* Queries are specific to the GL context that created them. Not
         * deleting the query will obviously leak it, but that's still better
         * than potentially deleting a different query with the same id in this
         * context, and (still) leaking the actual query. */
70 71
        if (This->type == WINED3DQUERYTYPE_EVENT)
        {
72
            struct wined3d_event_query *query = This->extendedData;
73

74
            if (query->context) context_free_event_query(query);
75
        }
76
        else if (This->type == WINED3DQUERYTYPE_OCCLUSION)
77
        {
78
            struct wined3d_occlusion_query *query = This->extendedData;
79

80
            if (query->context) context_free_occlusion_query(query);
81 82
        }

83
        HeapFree(GetProcessHeap(), 0, This->extendedData);
84 85 86 87 88 89 90 91
        HeapFree(GetProcessHeap(), 0, This);
    }
    return ref;
}

/* *******************************************
   IWineD3DQuery IWineD3DQuery parts follow
   ******************************************* */
92
static HRESULT  WINAPI IWineD3DQueryImpl_GetParent(IWineD3DQuery *iface, IUnknown** parent){
93 94 95 96 97
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;

    *parent= (IUnknown*) parent;
    IUnknown_AddRef(*parent);
    TRACE("(%p) : returning %p\n", This, *parent);
98
    return WINED3D_OK;
99 100
}

101
static HRESULT  WINAPI IWineD3DQueryImpl_GetDevice(IWineD3DQuery* iface, IWineD3DDevice **pDevice){
102 103 104 105
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
    IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
    *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
    TRACE("(%p) returning %p\n", This, *pDevice);
106
    return WINED3D_OK;
107 108 109
}


110
static HRESULT  WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags){
111
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
112
    HRESULT res = S_OK;
113

114
    TRACE("(%p) : type %#x, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, This->type, pData, dwSize, dwGetDataFlags);
115

116 117 118 119 120
    switch (This->type){

    case WINED3DQUERYTYPE_VCACHE:
    {

121
        WINED3DDEVINFO_VCACHE *data = pData;
122
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VCACHE\n", This);
123
        if(pData == NULL || dwSize == 0) break;
124
        data->Pattern     = WINEMAKEFOURCC('C','A','C','H');
125 126 127 128 129 130 131 132
        data->OptMethod   = 0; /*0 get longest strips, 1 optimize vertex cache*/
        data->CacheSize   = 0; /*cache size, only required if OptMethod == 1*/
        data->MagicNumber = 0; /*only required if OptMethod == 1 (used internally)*/

    }
    break;
    case WINED3DQUERYTYPE_RESOURCEMANAGER:
    {
133
        WINED3DDEVINFO_RESOURCEMANAGER *data = pData;
134
        int i;
135
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_RESOURCEMANAGER\n", This);
136
        if(pData == NULL || dwSize == 0) break;
137
        for(i = 0; i < WINED3DRTYPECOUNT; i++){
138
            /*I'm setting the default values to 1 so as to reduce the risk of a div/0 in the caller*/
139
            /*  isTextureResident could be used to get some of this information  */
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
            data->stats[i].bThrashing            = FALSE;
            data->stats[i].ApproxBytesDownloaded = 1;
            data->stats[i].NumEvicts             = 1;
            data->stats[i].NumVidCreates         = 1;
            data->stats[i].LastPri               = 1;
            data->stats[i].NumUsed               = 1;
            data->stats[i].NumUsedInVidMem       = 1;
            data->stats[i].WorkingSet            = 1;
            data->stats[i].WorkingSetBytes       = 1;
            data->stats[i].TotalManaged          = 1;
            data->stats[i].TotalBytes            = 1;
        }

    }
    break;
    case WINED3DQUERYTYPE_VERTEXSTATS:
    {
157
        WINED3DDEVINFO_VERTEXSTATS *data = pData;
158
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXSTATS\n", This);
159
        if(pData == NULL || dwSize == 0) break;
160 161 162 163 164 165 166 167
        data->NumRenderedTriangles      = 1;
        data->NumExtraClippingTriangles = 1;

    }
    break;
    case WINED3DQUERYTYPE_TIMESTAMP:
    {
        UINT64* data = pData;
168
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMP\n", This);
169
        if(pData == NULL || dwSize == 0) break;
170 171 172 173 174 175
        *data = 1; /*Don't know what this is supposed to be*/
    }
    break;
    case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
    {
        BOOL* data = pData;
176
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPDISJOINT\n", This);
177
        if(pData == NULL || dwSize == 0) break;
178 179 180 181 182 183
        *data = FALSE; /*Don't know what this is supposed to be*/
    }
    break;
    case WINED3DQUERYTYPE_TIMESTAMPFREQ:
    {
        UINT64* data = pData;
184
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPFREQ\n", This);
185
        if(pData == NULL || dwSize == 0) break;
186 187 188 189 190
        *data = 1; /*Don't know what this is supposed to be*/
    }
    break;
    case WINED3DQUERYTYPE_PIPELINETIMINGS:
    {
191
        WINED3DDEVINFO_PIPELINETIMINGS *data = pData;
192
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIPELINETIMINGS\n", This);
193
        if(pData == NULL || dwSize == 0) break;
194 195 196 197 198 199 200 201 202

        data->VertexProcessingTimePercent    =   1.0f;
        data->PixelProcessingTimePercent     =   1.0f;
        data->OtherGPUProcessingTimePercent  =  97.0f;
        data->GPUIdleTimePercent             =   1.0f;
    }
    break;
    case WINED3DQUERYTYPE_INTERFACETIMINGS:
    {
203
        WINED3DDEVINFO_INTERFACETIMINGS *data = pData;
204
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_INTERFACETIMINGS\n", This);
205

206
        if(pData == NULL || dwSize == 0) break;
207 208 209 210 211 212 213 214 215 216
        data->WaitingForGPUToUseApplicationResourceTimePercent =   1.0f;
        data->WaitingForGPUToAcceptMoreCommandsTimePercent     =   1.0f;
        data->WaitingForGPUToStayWithinLatencyTimePercent      =   1.0f;
        data->WaitingForGPUExclusiveResourceTimePercent        =   1.0f;
        data->WaitingForGPUOtherTimePercent                    =  96.0f;
    }

    break;
    case WINED3DQUERYTYPE_VERTEXTIMINGS:
    {
217
        WINED3DDEVINFO_STAGETIMINGS *data = pData;
218 219
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXTIMINGS\n", This);

220
        if(pData == NULL || dwSize == 0) break;
221 222 223 224 225 226 227
        data->MemoryProcessingPercent      = 50.0f;
        data->ComputationProcessingPercent = 50.0f;

    }
    break;
    case WINED3DQUERYTYPE_PIXELTIMINGS:
    {
228
        WINED3DDEVINFO_STAGETIMINGS *data = pData;
229 230
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIXELTIMINGS\n", This);

231
        if(pData == NULL || dwSize == 0) break;
232 233 234 235 236 237
        data->MemoryProcessingPercent      = 50.0f;
        data->ComputationProcessingPercent = 50.0f;
    }
    break;
    case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
    {
238
        WINED3DDEVINFO_BANDWIDTHTIMINGS *data = pData;
239 240
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_BANDWIDTHTIMINGS\n", This);

241
        if(pData == NULL || dwSize == 0) break;
242 243 244 245 246 247 248 249 250
        data->MaxBandwidthUtilized                =  1.0f;
        data->FrontEndUploadMemoryUtilizedPercent =  1.0f;
        data->VertexRateUtilizedPercent           =  1.0f;
        data->TriangleSetupRateUtilizedPercent    =  1.0f;
        data->FillRateUtilizedPercent             = 97.0f;
    }
    break;
    case WINED3DQUERYTYPE_CACHEUTILIZATION:
    {
251
        WINED3DDEVINFO_CACHEUTILIZATION *data = pData;
252
        FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_CACHEUTILIZATION\n", This);
253

254
        if(pData == NULL || dwSize == 0) break;
255 256 257 258 259 260 261 262 263 264 265 266
        data->TextureCacheHitRate             = 1.0f;
        data->PostTransformVertexCacheHitRate = 1.0f;
    }


    break;
    default:
        FIXME("(%p) Unhandled query type %d\n",This , This->type);

    };

    /*dwGetDataFlags = 0 || D3DGETDATA_FLUSH
267
    D3DGETDATA_FLUSH may return WINED3DERR_DEVICELOST if the device is lost
268
    */
269
    return res; /* S_OK if the query data is available*/
270 271
}

272 273
static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
274
    struct wined3d_occlusion_query *query = This->extendedData;
275 276
    IWineD3DDeviceImpl *device = This->wineD3DDevice;
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
277
    struct wined3d_context *context;
278
    DWORD* data = pData;
279 280
    GLuint available;
    GLuint samples;
281
    HRESULT res;
282

283 284
    TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);

285 286
    if (!query->context) This->state = QUERY_CREATED;

287 288
    if (This->state == QUERY_CREATED)
    {
289 290 291
        /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
        TRACE("Query wasn't yet started, returning S_OK\n");
        if(data) *data = 0;
292 293 294 295 296
        return S_OK;
    }

    if (This->state == QUERY_BUILDING)
    {
297 298
        /* Msdn says this returns an error, but our tests show that S_FALSE is returned */
        TRACE("Query is building, returning S_FALSE\n");
299
        return S_FALSE;
300
    }
301

302
    if (!gl_info->supported[ARB_OCCLUSION_QUERY])
303 304
    {
        WARN("(%p) : Occlusion queries not supported. Returning 1.\n", This);
305
        *data = 1;
306 307 308
        return S_OK;
    }

309
    if (query->context->tid != GetCurrentThreadId())
310
    {
311
        FIXME("%p Wrong thread, returning 1.\n", This);
312 313 314 315
        *data = 1;
        return S_OK;
    }

316
    context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
317

318 319
    ENTER_GL();

320
    GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
321
    checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
322 323 324 325 326 327
    TRACE("(%p) : available %d.\n", This, available);

    if (available)
    {
        if (data)
        {
328
            GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_ARB, &samples));
329
            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
330 331 332
            TRACE("(%p) : Returning %d samples.\n", This, samples);
            *data = samples;
        }
333 334
        res = S_OK;
    }
335 336 337 338 339 340 341
    else
    {
        res = S_FALSE;
    }

    LEAVE_GL();

342 343
    context_release(context);

344 345 346
    return res;
}

347 348
static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
349
    struct wined3d_event_query *query = This->extendedData;
350 351
    struct wined3d_context *context;
    BOOL *data = pData;
352

353 354
    TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);

355
    if (!pData || !dwSize) return S_OK;
356

357 358 359 360 361 362 363 364
    if (!query->context)
    {
        ERR("Query not started, returning TRUE.\n");
        *data = TRUE;

        return S_OK;
    }

365
    if (query->context->tid != GetCurrentThreadId())
366
    {
367
        /* See comment in IWineD3DQuery::Issue, event query codeblock */
368
        FIXME("Wrong thread, reporting GPU idle.\n");
369
        *data = TRUE;
370 371 372 373

        return S_OK;
    }

374
    context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
375 376 377

    ENTER_GL();

378
    if (context->gl_info->supported[APPLE_FENCE])
379
    {
380
        *data = GL_EXTCALL(glTestFenceAPPLE(query->id));
381
        checkGLcall("glTestFenceAPPLE");
382
    }
383
    else if (context->gl_info->supported[NV_FENCE])
384
    {
385
        *data = GL_EXTCALL(glTestFenceNV(query->id));
386
        checkGLcall("glTestFenceNV");
387 388 389
    }
    else
    {
390 391 392 393
        WARN("(%p): reporting GPU idle\n", This);
        *data = TRUE;
    }

394 395
    LEAVE_GL();

396 397
    context_release(context);

398 399
    return S_OK;
}
400

401
static DWORD  WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){
402 403
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
    int dataSize = 0;
404
    TRACE("(%p) : type %#x\n", This, This->type);
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
    switch(This->type){
    case WINED3DQUERYTYPE_VCACHE:
        dataSize = sizeof(WINED3DDEVINFO_VCACHE);
        break;
    case WINED3DQUERYTYPE_RESOURCEMANAGER:
        dataSize = sizeof(WINED3DDEVINFO_RESOURCEMANAGER);
        break;
    case WINED3DQUERYTYPE_VERTEXSTATS:
        dataSize = sizeof(WINED3DDEVINFO_VERTEXSTATS);
        break;
    case WINED3DQUERYTYPE_EVENT:
        dataSize = sizeof(BOOL);
        break;
    case WINED3DQUERYTYPE_TIMESTAMP:
        dataSize = sizeof(UINT64);
        break;
    case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
        dataSize = sizeof(BOOL);
        break;
    case WINED3DQUERYTYPE_TIMESTAMPFREQ:
        dataSize = sizeof(UINT64);
        break;
    case WINED3DQUERYTYPE_PIPELINETIMINGS:
        dataSize = sizeof(WINED3DDEVINFO_PIPELINETIMINGS);
        break;
    case WINED3DQUERYTYPE_INTERFACETIMINGS:
        dataSize = sizeof(WINED3DDEVINFO_INTERFACETIMINGS);
        break;
    case WINED3DQUERYTYPE_VERTEXTIMINGS:
        dataSize = sizeof(WINED3DDEVINFO_STAGETIMINGS);
        break;
    case WINED3DQUERYTYPE_PIXELTIMINGS:
        dataSize = sizeof(WINED3DDEVINFO_STAGETIMINGS);
        break;
    case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
        dataSize = sizeof(WINED3DQUERYTYPE_BANDWIDTHTIMINGS);
        break;
    case WINED3DQUERYTYPE_CACHEUTILIZATION:
        dataSize = sizeof(WINED3DDEVINFO_CACHEUTILIZATION);
        break;
    default:
       FIXME("(%p) Unhandled query type %d\n",This , This->type);
       dataSize = 0;
    }
    return dataSize;
}

452 453 454 455 456
static DWORD  WINAPI IWineD3DEventQueryImpl_GetDataSize(IWineD3DQuery* iface){
    TRACE("(%p) : type D3DQUERY_EVENT\n", iface);

    return sizeof(BOOL);
}
457

458 459 460 461 462 463
static DWORD  WINAPI IWineD3DOcclusionQueryImpl_GetDataSize(IWineD3DQuery* iface){
    TRACE("(%p) : type D3DQUERY_OCCLUSION\n", iface);

    return sizeof(DWORD);
}

464
static WINED3DQUERYTYPE  WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){
465 466 467 468 469
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
    return This->type;
}


470 471 472 473
static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags) {
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;

    TRACE("(%p) : dwIssueFlags %#x, type D3DQUERY_EVENT\n", This, dwIssueFlags);
474 475
    if (dwIssueFlags & WINED3DISSUE_END)
    {
476
        struct wined3d_event_query *query = This->extendedData;
477
        struct wined3d_context *context;
478

479
        if (query->context)
480
        {
481
            if (query->context->tid != GetCurrentThreadId())
482
            {
483
                context_free_event_query(query);
484
                context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
485
                context_alloc_event_query(context, query);
486
            }
487
            else
488
            {
489
                context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
490
            }
491 492 493
        }
        else
        {
494
            context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
495 496 497 498
            context_alloc_event_query(context, query);
        }

        ENTER_GL();
499

500
        if (context->gl_info->supported[APPLE_FENCE])
501 502 503 504
        {
            GL_EXTCALL(glSetFenceAPPLE(query->id));
            checkGLcall("glSetFenceAPPLE");
        }
505
        else if (context->gl_info->supported[NV_FENCE])
506 507 508
        {
            GL_EXTCALL(glSetFenceNV(query->id, GL_ALL_COMPLETED_NV));
            checkGLcall("glSetFenceNV");
509
        }
510 511

        LEAVE_GL();
512 513

        context_release(context);
514 515 516
    }
    else if(dwIssueFlags & WINED3DISSUE_BEGIN)
    {
517 518 519 520 521 522 523 524 525 526 527 528 529
        /* Started implicitly at device creation */
        ERR("Event query issued with START flag - what to do?\n");
    }

    if(dwIssueFlags & WINED3DISSUE_BEGIN) {
        This->state = QUERY_BUILDING;
    } else {
        This->state = QUERY_SIGNALLED;
    }

    return WINED3D_OK;
}

530
static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags) {
531
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
532 533
    IWineD3DDeviceImpl *device = This->wineD3DDevice;
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
534

535
    if (gl_info->supported[ARB_OCCLUSION_QUERY])
536
    {
537
        struct wined3d_occlusion_query *query = This->extendedData;
538
        struct wined3d_context *context;
539

540 541
        /* This is allowed according to msdn and our tests. Reset the query and restart */
        if (dwIssueFlags & WINED3DISSUE_BEGIN)
542
        {
543 544 545 546 547
            if (This->state == QUERY_BUILDING)
            {
                if (query->context->tid != GetCurrentThreadId())
                {
                    FIXME("Wrong thread, can't restart query.\n");
548

549
                    context_free_occlusion_query(query);
550
                    context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
551 552 553 554
                    context_alloc_occlusion_query(context, query);
                }
                else
                {
555
                    context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
556 557

                    ENTER_GL();
558 559
                    GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
                    checkGLcall("glEndQuery()");
560
                    LEAVE_GL();
561 562
                }
            }
563 564 565
            else
            {
                if (query->context) context_free_occlusion_query(query);
566
                context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
567 568 569 570 571 572 573
                context_alloc_occlusion_query(context, query);
            }

            ENTER_GL();
            GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query->id));
            checkGLcall("glBeginQuery()");
            LEAVE_GL();
574 575

            context_release(context);
576 577 578 579 580 581 582 583 584 585 586 587 588 589
        }
        if (dwIssueFlags & WINED3DISSUE_END) {
            /* Msdn says _END on a non-building occlusion query returns an error, but
             * our tests show that it returns OK. But OpenGL doesn't like it, so avoid
             * generating an error
             */
            if (This->state == QUERY_BUILDING)
            {
                if (query->context->tid != GetCurrentThreadId())
                {
                    FIXME("Wrong thread, can't end query.\n");
                }
                else
                {
590
                    context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
591 592

                    ENTER_GL();
593 594
                    GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
                    checkGLcall("glEndQuery()");
595
                    LEAVE_GL();
596 597

                    context_release(context);
598 599
                }
            }
600 601 602 603
        }
    } else {
        FIXME("(%p) : Occlusion queries not supported\n", This);
    }
604

605 606 607 608
    if(dwIssueFlags & WINED3DISSUE_BEGIN) {
        This->state = QUERY_BUILDING;
    } else {
        This->state = QUERY_SIGNALLED;
609
    }
610 611 612 613 614 615 616 617 618 619
    return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
}

static HRESULT  WINAPI IWineD3DQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags){
    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;

    TRACE("(%p) : dwIssueFlags %#x, type %#x\n", This, dwIssueFlags, This->type);

    /* The fixme is printed when the app asks for the resulting data */
    WARN("(%p) : Unhandled query type %#x\n", This, This->type);
620

621 622 623 624 625 626
    if(dwIssueFlags & WINED3DISSUE_BEGIN) {
        This->state = QUERY_BUILDING;
    } else {
        This->state = QUERY_SIGNALLED;
    }

627
    return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
628 629 630 631 632 633 634
}


/**********************************************************
 * IWineD3DQuery VTbl follows
 **********************************************************/

635
const IWineD3DQueryVtbl IWineD3DQuery_Vtbl =
636 637 638 639 640 641 642 643 644 645 646 647 648
{
    /*** IUnknown methods ***/
    IWineD3DQueryImpl_QueryInterface,
    IWineD3DQueryImpl_AddRef,
    IWineD3DQueryImpl_Release,
     /*** IWineD3Dquery methods ***/
    IWineD3DQueryImpl_GetParent,
    IWineD3DQueryImpl_GetDevice,
    IWineD3DQueryImpl_GetData,
    IWineD3DQueryImpl_GetDataSize,
    IWineD3DQueryImpl_GetType,
    IWineD3DQueryImpl_Issue
};
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663

const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl =
{
    /*** IUnknown methods ***/
    IWineD3DQueryImpl_QueryInterface,
    IWineD3DQueryImpl_AddRef,
    IWineD3DQueryImpl_Release,
    /*** IWineD3Dquery methods ***/
    IWineD3DQueryImpl_GetParent,
    IWineD3DQueryImpl_GetDevice,
    IWineD3DEventQueryImpl_GetData,
    IWineD3DEventQueryImpl_GetDataSize,
    IWineD3DQueryImpl_GetType,
    IWineD3DEventQueryImpl_Issue
};
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678

const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl =
{
    /*** IUnknown methods ***/
    IWineD3DQueryImpl_QueryInterface,
    IWineD3DQueryImpl_AddRef,
    IWineD3DQueryImpl_Release,
    /*** IWineD3Dquery methods ***/
    IWineD3DQueryImpl_GetParent,
    IWineD3DQueryImpl_GetDevice,
    IWineD3DOcclusionQueryImpl_GetData,
    IWineD3DOcclusionQueryImpl_GetDataSize,
    IWineD3DQueryImpl_GetType,
    IWineD3DOcclusionQueryImpl_Issue
};