mirror of
https://github.com/reactos/wine.git
synced 2025-02-28 16:56:24 +00:00
wined3d: Manage occlusion queries in the context.
This commit is contained in:
parent
6a1aa9b166
commit
4ab7af6575
@ -451,6 +451,63 @@ static void context_apply_fbo_state(struct WineD3DContext *context)
|
||||
context_check_fbo_status(context);
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
void context_alloc_occlusion_query(struct WineD3DContext *context, struct wined3d_occlusion_query *query)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
|
||||
if (context->free_occlusion_query_count)
|
||||
{
|
||||
query->id = context->free_occlusion_queries[--context->free_occlusion_query_count];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
|
||||
{
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glGenQueriesARB(1, &query->id));
|
||||
checkGLcall("glGenQueriesARB");
|
||||
LEAVE_GL();
|
||||
|
||||
TRACE("Allocated occlusion query %u in context %p.\n", query->id, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Occlusion queries not supported, not allocating query id.\n");
|
||||
query->id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
query->context = context;
|
||||
list_add_head(&context->occlusion_queries, &query->entry);
|
||||
}
|
||||
|
||||
void context_free_occlusion_query(struct wined3d_occlusion_query *query)
|
||||
{
|
||||
struct WineD3DContext *context = query->context;
|
||||
|
||||
list_remove(&query->entry);
|
||||
query->context = NULL;
|
||||
|
||||
if (context->free_occlusion_query_count >= context->free_occlusion_query_size - 1)
|
||||
{
|
||||
UINT new_size = context->free_occlusion_query_size << 1;
|
||||
GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_occlusion_queries,
|
||||
new_size * sizeof(*context->free_occlusion_queries));
|
||||
|
||||
if (!new_data)
|
||||
{
|
||||
ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context);
|
||||
return;
|
||||
}
|
||||
|
||||
context->free_occlusion_query_size = new_size;
|
||||
context->free_occlusion_queries = new_data;
|
||||
}
|
||||
|
||||
context->free_occlusion_queries[context->free_occlusion_query_count++] = query->id;
|
||||
}
|
||||
|
||||
void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type)
|
||||
{
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
@ -504,6 +561,7 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource
|
||||
static void context_destroy_gl_resources(struct WineD3DContext *context)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
struct wined3d_occlusion_query *occlusion_query;
|
||||
struct fbo_entry *entry, *entry2;
|
||||
BOOL has_glctx;
|
||||
|
||||
@ -512,6 +570,12 @@ static void context_destroy_gl_resources(struct WineD3DContext *context)
|
||||
|
||||
ENTER_GL();
|
||||
|
||||
LIST_FOR_EACH_ENTRY(occlusion_query, &context->occlusion_queries, struct wined3d_occlusion_query, entry)
|
||||
{
|
||||
if (has_glctx && GL_SUPPORT(ARB_OCCLUSION_QUERY)) GL_EXTCALL(glDeleteQueriesARB(1, &occlusion_query->id));
|
||||
occlusion_query->context = NULL;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) {
|
||||
if (!has_glctx) entry->id = 0;
|
||||
context_destroy_fbo_entry(context, entry);
|
||||
@ -532,10 +596,16 @@ static void context_destroy_gl_resources(struct WineD3DContext *context)
|
||||
{
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &context->dummy_arbfp_prog));
|
||||
}
|
||||
|
||||
GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
|
||||
|
||||
checkGLcall("context cleanup");
|
||||
}
|
||||
|
||||
LEAVE_GL();
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries);
|
||||
|
||||
if (!pwglMakeCurrent(NULL, NULL))
|
||||
{
|
||||
ERR("Failed to disable GL context.\n");
|
||||
@ -1092,6 +1162,13 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||
sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF));
|
||||
}
|
||||
|
||||
ret->free_occlusion_query_size = 4;
|
||||
ret->free_occlusion_queries = HeapAlloc(GetProcessHeap(), 0,
|
||||
ret->free_occlusion_query_size * sizeof(*ret->free_occlusion_queries));
|
||||
if (!ret->free_occlusion_queries) goto out;
|
||||
|
||||
list_init(&ret->occlusion_queries);
|
||||
|
||||
TRACE("Successfully created new context %p\n", ret);
|
||||
|
||||
list_init(&ret->fbo_list);
|
||||
@ -1187,6 +1264,13 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
|
||||
return ret;
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
|
||||
HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty);
|
||||
HeapFree(GetProcessHeap(), 0, ret->vshader_const_dirty);
|
||||
HeapFree(GetProcessHeap(), 0, ret);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1191,18 +1191,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE
|
||||
/* allocated the 'extended' data based on the type of query requested */
|
||||
switch(Type){
|
||||
case WINED3DQUERYTYPE_OCCLUSION:
|
||||
object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
|
||||
((WineQueryOcclusionData *)(object->extendedData))->ctx = This->activeContext;
|
||||
object->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query));
|
||||
((struct wined3d_occlusion_query *)object->extendedData)->context = NULL;
|
||||
break;
|
||||
|
||||
if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
|
||||
TRACE("(%p) Allocating data for an occlusion query\n", This);
|
||||
|
||||
ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD);
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
|
||||
LEAVE_GL();
|
||||
break;
|
||||
}
|
||||
case WINED3DQUERYTYPE_EVENT:
|
||||
object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
|
||||
((WineQueryEventData *)(object->extendedData))->ctx = This->activeContext;
|
||||
|
@ -94,25 +94,11 @@ static ULONG WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
|
||||
LEAVE_GL();
|
||||
}
|
||||
}
|
||||
else if (This->type == WINED3DQUERYTYPE_OCCLUSION && GL_SUPPORT(ARB_OCCLUSION_QUERY))
|
||||
else if (This->type == WINED3DQUERYTYPE_OCCLUSION)
|
||||
{
|
||||
WineQueryOcclusionData *query_data = (WineQueryOcclusionData *)This->extendedData;
|
||||
struct wined3d_occlusion_query *query = This->extendedData;
|
||||
|
||||
if (query_data->ctx->tid != GetCurrentThreadId())
|
||||
{
|
||||
FIXME("Query was created in a different thread, skipping deletion.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivateContext(This->wineD3DDevice, query_data->ctx->surface, CTXUSAGE_RESOURCELOAD);
|
||||
|
||||
ENTER_GL();
|
||||
|
||||
GL_EXTCALL(glDeleteQueriesARB(1, &query_data->queryId));
|
||||
checkGLcall("glDeleteQueriesARB");
|
||||
|
||||
LEAVE_GL();
|
||||
}
|
||||
if (query->context) context_free_occlusion_query(query);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->extendedData);
|
||||
@ -306,7 +292,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa
|
||||
|
||||
static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
|
||||
IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
|
||||
WineQueryOcclusionData *query_data = (WineQueryOcclusionData *)This->extendedData;
|
||||
struct wined3d_occlusion_query *query = This->extendedData;
|
||||
DWORD* data = pData;
|
||||
GLuint available;
|
||||
GLuint samples;
|
||||
@ -314,6 +300,8 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface,
|
||||
|
||||
TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
|
||||
|
||||
if (!query->context) This->state = QUERY_CREATED;
|
||||
|
||||
if (This->state == QUERY_CREATED)
|
||||
{
|
||||
/* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
|
||||
@ -336,18 +324,18 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (query_data->ctx->tid != GetCurrentThreadId())
|
||||
if (query->context->tid != GetCurrentThreadId())
|
||||
{
|
||||
FIXME("%p Wrong thread, returning 1.\n", This);
|
||||
*data = 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ActivateContext(This->wineD3DDevice, query_data->ctx->surface, CTXUSAGE_RESOURCELOAD);
|
||||
ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
|
||||
|
||||
ENTER_GL();
|
||||
|
||||
GL_EXTCALL(glGetQueryObjectuivARB(query_data->queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
|
||||
GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
|
||||
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
|
||||
TRACE("(%p) : available %d.\n", This, available);
|
||||
|
||||
@ -355,7 +343,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface,
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
GL_EXTCALL(glGetQueryObjectuivARB(query_data->queryId, GL_QUERY_RESULT_ARB, &samples));
|
||||
GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_ARB, &samples));
|
||||
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
|
||||
TRACE("(%p) : Returning %d samples.\n", This, samples);
|
||||
*data = samples;
|
||||
@ -541,39 +529,66 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D
|
||||
|
||||
if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
|
||||
{
|
||||
WineQueryOcclusionData *query_data = (WineQueryOcclusionData *)This->extendedData;
|
||||
struct wined3d_occlusion_query *query = This->extendedData;
|
||||
struct WineD3DContext *context;
|
||||
|
||||
if (query_data->ctx->tid != GetCurrentThreadId())
|
||||
/* This is allowed according to msdn and our tests. Reset the query and restart */
|
||||
if (dwIssueFlags & WINED3DISSUE_BEGIN)
|
||||
{
|
||||
FIXME("Not the owning context, can't start query.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivateContext(This->wineD3DDevice, query_data->ctx->surface, CTXUSAGE_RESOURCELOAD);
|
||||
if (This->state == QUERY_BUILDING)
|
||||
{
|
||||
if (query->context->tid != GetCurrentThreadId())
|
||||
{
|
||||
FIXME("Wrong thread, can't restart query.\n");
|
||||
|
||||
context_free_occlusion_query(query);
|
||||
context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
|
||||
context_alloc_occlusion_query(context, query);
|
||||
}
|
||||
else
|
||||
{
|
||||
ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
|
||||
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
|
||||
checkGLcall("glEndQuery()");
|
||||
LEAVE_GL();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (query->context) context_free_occlusion_query(query);
|
||||
context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
|
||||
context_alloc_occlusion_query(context, query);
|
||||
}
|
||||
|
||||
ENTER_GL();
|
||||
/* This is allowed according to msdn and our tests. Reset the query and restart */
|
||||
if (dwIssueFlags & WINED3DISSUE_BEGIN) {
|
||||
if(This->state == QUERY_BUILDING) {
|
||||
GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
|
||||
checkGLcall("glEndQuery()");
|
||||
}
|
||||
|
||||
GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query_data->queryId));
|
||||
checkGLcall("glBeginQuery()");
|
||||
}
|
||||
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) {
|
||||
GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
|
||||
checkGLcall("glEndQuery()");
|
||||
}
|
||||
}
|
||||
GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query->id));
|
||||
checkGLcall("glBeginQuery()");
|
||||
LEAVE_GL();
|
||||
}
|
||||
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
|
||||
{
|
||||
ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
|
||||
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
|
||||
checkGLcall("glEndQuery()");
|
||||
LEAVE_GL();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FIXME("(%p) : Occlusion queries not supported\n", This);
|
||||
}
|
||||
|
@ -1188,6 +1188,13 @@ enum fogsource {
|
||||
|
||||
#define WINED3D_MAX_FBO_ENTRIES 64
|
||||
|
||||
struct wined3d_occlusion_query
|
||||
{
|
||||
struct list entry;
|
||||
GLuint id;
|
||||
struct WineD3DContext *context;
|
||||
};
|
||||
|
||||
/* The new context manager that should deal with onscreen and offscreen rendering */
|
||||
struct WineD3DContext
|
||||
{
|
||||
@ -1248,6 +1255,12 @@ struct WineD3DContext
|
||||
GLuint fbo_read_binding;
|
||||
GLuint fbo_draw_binding;
|
||||
|
||||
/* Queries */
|
||||
GLuint *free_occlusion_queries;
|
||||
UINT free_occlusion_query_size;
|
||||
UINT free_occlusion_query_count;
|
||||
struct list occlusion_queries;
|
||||
|
||||
/* Extension emulation */
|
||||
GLint gl_fog_source;
|
||||
GLfloat fog_coord_value;
|
||||
@ -1265,12 +1278,14 @@ typedef enum ContextUsage {
|
||||
struct WineD3DContext *ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, enum ContextUsage usage);
|
||||
WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms);
|
||||
void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context);
|
||||
void context_alloc_occlusion_query(struct WineD3DContext *context, struct wined3d_occlusion_query *query);
|
||||
void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type);
|
||||
void context_bind_fbo(struct WineD3DContext *context, GLenum target, GLuint *fbo);
|
||||
void context_attach_depth_stencil_fbo(struct WineD3DContext *context,
|
||||
GLenum fbo_target, IWineD3DSurface *depth_stencil, BOOL use_render_buffer);
|
||||
void context_attach_surface_fbo(const struct WineD3DContext *context,
|
||||
GLenum fbo_target, DWORD idx, IWineD3DSurface *surface);
|
||||
void context_free_occlusion_query(struct wined3d_occlusion_query *query);
|
||||
struct WineD3DContext *context_get_current(void);
|
||||
DWORD context_get_tls_idx(void);
|
||||
BOOL context_set_current(struct WineD3DContext *ctx);
|
||||
@ -2350,11 +2365,6 @@ extern const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl;
|
||||
extern const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl;
|
||||
|
||||
/* Datastructures for IWineD3DQueryImpl.extendedData */
|
||||
typedef struct WineQueryOcclusionData {
|
||||
GLuint queryId;
|
||||
WineD3DContext *ctx;
|
||||
} WineQueryOcclusionData;
|
||||
|
||||
typedef struct WineQueryEventData {
|
||||
GLuint fenceId;
|
||||
WineD3DContext *ctx;
|
||||
|
Loading…
x
Reference in New Issue
Block a user