Home | History | Annotate | Download | only in renderer
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl.
      9 
     10 #include "libGLESv2/renderer/Fence11.h"
     11 #include "libGLESv2/main.h"
     12 #include "libGLESv2/renderer/Renderer11.h"
     13 
     14 namespace rx
     15 {
     16 
     17 Fence11::Fence11(rx::Renderer11 *renderer)
     18 {
     19     mRenderer = renderer;
     20     mQuery = NULL;
     21 }
     22 
     23 Fence11::~Fence11()
     24 {
     25     if (mQuery)
     26     {
     27         mQuery->Release();
     28         mQuery = NULL;
     29     }
     30 }
     31 
     32 GLboolean Fence11::isFence()
     33 {
     34     // GL_NV_fence spec:
     35     // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
     36     return mQuery != NULL;
     37 }
     38 
     39 void Fence11::setFence(GLenum condition)
     40 {
     41     if (!mQuery)
     42     {
     43         D3D11_QUERY_DESC queryDesc;
     44         queryDesc.Query = D3D11_QUERY_EVENT;
     45         queryDesc.MiscFlags = 0;
     46 
     47         if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
     48         {
     49             return gl::error(GL_OUT_OF_MEMORY);
     50         }
     51     }
     52 
     53     mRenderer->getDeviceContext()->End(mQuery);
     54 
     55     setCondition(condition);
     56     setStatus(GL_FALSE);
     57 }
     58 
     59 GLboolean Fence11::testFence()
     60 {
     61     if (mQuery == NULL)
     62     {
     63         return gl::error(GL_INVALID_OPERATION, GL_TRUE);
     64     }
     65 
     66     HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0);
     67 
     68     if (mRenderer->isDeviceLost())
     69     {
     70        return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
     71     }
     72 
     73     ASSERT(result == S_OK || result == S_FALSE);
     74     setStatus(result == S_OK);
     75     return getStatus();
     76 }
     77 
     78 void Fence11::finishFence()
     79 {
     80     if (mQuery == NULL)
     81     {
     82         return gl::error(GL_INVALID_OPERATION);
     83     }
     84 
     85     while (!testFence())
     86     {
     87         Sleep(0);
     88     }
     89 }
     90 
     91 void Fence11::getFenceiv(GLenum pname, GLint *params)
     92 {
     93     if (mQuery == NULL)
     94     {
     95         return gl::error(GL_INVALID_OPERATION);
     96     }
     97 
     98     switch (pname)
     99     {
    100       case GL_FENCE_STATUS_NV:
    101         {
    102             // GL_NV_fence spec:
    103             // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
    104             // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
    105             if (getStatus())
    106             {
    107                 params[0] = GL_TRUE;
    108                 return;
    109             }
    110 
    111             HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
    112 
    113             if (mRenderer->isDeviceLost())
    114             {
    115                 params[0] = GL_TRUE;
    116                 return gl::error(GL_OUT_OF_MEMORY);
    117             }
    118 
    119             ASSERT(result == S_OK || result == S_FALSE);
    120             setStatus(result == S_OK);
    121             params[0] = getStatus();
    122 
    123             break;
    124         }
    125       case GL_FENCE_CONDITION_NV:
    126         params[0] = getCondition();
    127         break;
    128       default:
    129         return gl::error(GL_INVALID_ENUM);
    130         break;
    131     }
    132 }
    133 
    134 }
    135