Commit c6232e1d authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Create GL sampler objects for wined3d sampler objects.

parent 5231113f
......@@ -657,7 +657,7 @@ HRESULT d3d10_sampler_state_init(struct d3d10_sampler_state *state, struct d3d10
wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d10core(desc->ComparisonFunc);
wined3d_desc.srgb_decode = FALSE;
if (FAILED(hr = wined3d_sampler_create(&wined3d_desc, state, &state->wined3d_sampler)))
if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc, state, &state->wined3d_sampler)))
{
WARN("Failed to create wined3d sampler, hr %#x.\n", hr);
return hr;
......
......@@ -1920,6 +1920,8 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
context_invalidate_state(context, STATE_SAMPLER(sampler));
}
}
if (gl_info->supported[ARB_SAMPLER_OBJECTS])
GL_EXTCALL(glBindSampler(0, 0));
context_active_texture(context, gl_info, 0);
sampler = context->rev_tex_unit_map[0];
......
......@@ -479,6 +479,13 @@ ULONG CDECL wined3d_device_incref(struct wined3d_device *device)
return refcount;
}
static void device_leftover_sampler(struct wine_rb_entry *entry, void *context)
{
struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
ERR("Leftover sampler %p.\n", sampler);
}
ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
{
ULONG refcount = InterlockedDecrement(&device->ref);
......@@ -522,6 +529,8 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
DestroyCursor(device->hardwareCursor);
device->hardwareCursor = 0;
wine_rb_destroy(&device->samplers, device_leftover_sampler, NULL);
wined3d_decref(device->wined3d);
device->wined3d = NULL;
HeapFree(GetProcessHeap(), 0, device);
......@@ -1020,6 +1029,14 @@ err_out:
return hr;
}
static void device_free_sampler(struct wine_rb_entry *entry, void *context)
{
struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
struct wined3d_device *device = context;
wine_rb_remove(&device->samplers, &sampler->desc);
}
HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
{
struct wined3d_resource *resource, *cursor;
......@@ -1054,6 +1071,8 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
resource->resource_ops->resource_unload(resource);
}
wine_rb_for_each_entry(&device->samplers, device_free_sampler, device);
/* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
* private data, it might contain opengl pointers
*/
......@@ -4658,6 +4677,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
swapchain_update_render_to_fbo(swapchain);
swapchain_update_draw_bindings(swapchain);
wine_rb_for_each_entry(&device->samplers, device_free_sampler, device);
if (reset_state && device->d3d_initialized)
hr = create_primary_opengl_context(device, swapchain);
......@@ -4850,6 +4871,21 @@ struct wined3d_surface * CDECL wined3d_device_get_surface_from_dc(const struct w
return NULL;
}
static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry *entry)
{
const struct wined3d_sampler *sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
return memcmp(&sampler->desc, key, sizeof(sampler->desc));
}
static const struct wine_rb_functions wined3d_sampler_rb_functions =
{
wined3d_rb_alloc,
wined3d_rb_realloc,
wined3d_rb_free,
wined3d_sampler_compare,
};
HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
UINT adapter_idx, enum wined3d_device_type device_type, HWND focus_window, DWORD flags,
BYTE surface_alignment, struct wined3d_device_parent *device_parent)
......@@ -4881,12 +4917,19 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
fragment_pipeline = adapter->fragment_pipe;
if (wine_rb_init(&device->samplers, &wined3d_sampler_rb_functions) == -1)
{
ERR("Failed to initialize sampler rbtree.\n");
return E_OUTOFMEMORY;
}
if (vertex_pipeline->vp_states && fragment_pipeline->states
&& FAILED(hr = compile_state_table(device->StateTable, device->multistate_funcs,
&adapter->gl_info, &adapter->d3d_info, vertex_pipeline,
fragment_pipeline, misc_state_template)))
{
ERR("Failed to compile state table, hr %#x.\n", hr);
wine_rb_destroy(&device->samplers, NULL, NULL);
wined3d_decref(device->wined3d);
return hr;
}
......@@ -4916,6 +4959,7 @@ err:
{
HeapFree(GetProcessHeap(), 0, device->multistate_funcs[i]);
}
wine_rb_destroy(&device->samplers, NULL, NULL);
wined3d_decref(device->wined3d);
return hr;
}
......
......@@ -135,6 +135,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
{"GL_ARB_point_parameters", ARB_POINT_PARAMETERS },
{"GL_ARB_point_sprite", ARB_POINT_SPRITE },
{"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX },
{"GL_ARB_sampler_objects", ARB_SAMPLER_OBJECTS },
{"GL_ARB_shader_bit_encoding", ARB_SHADER_BIT_ENCODING },
{"GL_ARB_shader_objects", ARB_SHADER_OBJECTS },
{"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD },
......@@ -2517,6 +2518,21 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
USE_GL_FUNC(glPointParameterfvARB)
/* GL_ARB_provoking_vertex */
USE_GL_FUNC(glProvokingVertex)
/* GL_ARB_sampler_objects */
USE_GL_FUNC(glGenSamplers)
USE_GL_FUNC(glDeleteSamplers)
USE_GL_FUNC(glIsSampler)
USE_GL_FUNC(glBindSampler)
USE_GL_FUNC(glSamplerParameteri)
USE_GL_FUNC(glSamplerParameterf)
USE_GL_FUNC(glSamplerParameteriv)
USE_GL_FUNC(glSamplerParameterfv)
USE_GL_FUNC(glSamplerParameterIiv)
USE_GL_FUNC(glSamplerParameterIuiv)
USE_GL_FUNC(glGetSamplerParameteriv)
USE_GL_FUNC(glGetSamplerParameterfv)
USE_GL_FUNC(glGetSamplerParameterIiv)
USE_GL_FUNC(glGetSamplerParameterIuiv)
/* GL_ARB_shader_objects */
USE_GL_FUNC(glAttachObjectARB)
USE_GL_FUNC(glBindAttribLocationARB)
......
......@@ -6604,7 +6604,7 @@ static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct s
if (gl_info->supported[EXT_GPU_SHADER4] && gl_info->supported[ARB_SHADER_BIT_ENCODING]
&& gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50)
&& gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] && gl_info->supported[ARB_DRAW_INSTANCED]
&& gl_info->supported[ARB_TEXTURE_RG])
&& gl_info->supported[ARB_TEXTURE_RG] && gl_info->supported[ARB_SAMPLER_OBJECTS])
shader_model = 4;
/* ARB_shader_texture_lod or EXT_gpu_shader4 is required for the SM3
* texldd and texldl instructions. */
......
......@@ -36,11 +36,20 @@ ULONG CDECL wined3d_sampler_incref(struct wined3d_sampler *sampler)
ULONG CDECL wined3d_sampler_decref(struct wined3d_sampler *sampler)
{
ULONG refcount = InterlockedDecrement(&sampler->refcount);
const struct wined3d_gl_info *gl_info;
struct wined3d_context *context;
TRACE("%p decreasing refcount to %u.\n", sampler, refcount);
if (!refcount)
{
context = context_acquire(sampler->device, NULL);
gl_info = context->gl_info;
GL_EXTCALL(glDeleteSamplers(1, &sampler->name));
context_release(context);
HeapFree(GetProcessHeap(), 0, sampler);
}
return refcount;
}
......@@ -52,25 +61,74 @@ void * CDECL wined3d_sampler_get_parent(const struct wined3d_sampler *sampler)
return sampler->parent;
}
static void wined3d_sampler_init(struct wined3d_sampler *sampler,
static void wined3d_sampler_init(struct wined3d_sampler *sampler, struct wined3d_device *device,
const struct wined3d_sampler_desc *desc, void *parent)
{
const struct wined3d_gl_info *gl_info;
struct wined3d_context *context;
sampler->refcount = 1;
sampler->device = device;
sampler->parent = parent;
sampler->desc = *desc;
context = context_acquire(device, NULL);
gl_info = context->gl_info;
GL_EXTCALL(glGenSamplers(1, &sampler->name));
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_WRAP_S,
gl_info->wrap_lookup[desc->address_u - WINED3D_TADDRESS_WRAP]));
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_WRAP_T,
gl_info->wrap_lookup[desc->address_v - WINED3D_TADDRESS_WRAP]));
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_WRAP_R,
gl_info->wrap_lookup[desc->address_w - WINED3D_TADDRESS_WRAP]));
GL_EXTCALL(glSamplerParameterfv(sampler->name, GL_TEXTURE_BORDER_COLOR, &desc->border_color[0]));
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_MAG_FILTER,
wined3d_gl_mag_filter(desc->mag_filter)));
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_MIN_FILTER,
wined3d_gl_min_mip_filter(desc->min_filter, desc->mip_filter)));
GL_EXTCALL(glSamplerParameterf(sampler->name, GL_TEXTURE_LOD_BIAS, desc->lod_bias));
GL_EXTCALL(glSamplerParameterf(sampler->name, GL_TEXTURE_MIN_LOD, desc->min_lod));
GL_EXTCALL(glSamplerParameterf(sampler->name, GL_TEXTURE_MAX_LOD, desc->max_lod));
if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_MAX_ANISOTROPY_EXT, desc->max_anisotropy));
if (desc->compare)
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE));
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_COMPARE_FUNC,
wined3d_gl_compare_func(desc->comparison_func)));
if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE] && !desc->srgb_decode)
GL_EXTCALL(glSamplerParameteri(sampler->name, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT));
checkGLcall("sampler creation");
TRACE("Created sampler %u.\n", sampler->name);
context_release(context);
}
HRESULT CDECL wined3d_sampler_create(const struct wined3d_sampler_desc *desc,
HRESULT CDECL wined3d_sampler_create(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
void *parent, struct wined3d_sampler **sampler)
{
struct wined3d_sampler *object;
TRACE("desc %p, parent %p, sampler %p.\n", desc, parent, sampler);
TRACE("device %p, desc %p, parent %p, sampler %p.\n", device, desc, parent, sampler);
if (!device->adapter->gl_info.supported[ARB_SAMPLER_OBJECTS])
return WINED3DERR_INVALIDCALL;
if (desc->address_u < WINED3D_TADDRESS_WRAP || desc->address_u > WINED3D_TADDRESS_MIRROR_ONCE
|| desc->address_v < WINED3D_TADDRESS_WRAP || desc->address_v > WINED3D_TADDRESS_MIRROR_ONCE
|| desc->address_w < WINED3D_TADDRESS_WRAP || desc->address_w > WINED3D_TADDRESS_MIRROR_ONCE)
return WINED3DERR_INVALIDCALL;
if (desc->mag_filter < WINED3D_TEXF_POINT || desc->mag_filter > WINED3D_TEXF_LINEAR
|| desc->min_filter < WINED3D_TEXF_POINT || desc->min_filter > WINED3D_TEXF_LINEAR
|| desc->mip_filter > WINED3D_TEXF_LINEAR)
return WINED3DERR_INVALIDCALL;
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return E_OUTOFMEMORY;
wined3d_sampler_init(object, desc, parent);
wined3d_sampler_init(object, device, desc, parent);
TRACE("Created sampler %p.\n", object);
*sampler = object;
......
......@@ -234,7 +234,7 @@ static void state_zwritenable(struct wined3d_context *context, const struct wine
}
}
static GLenum gl_compare_func(enum wined3d_cmp_func f)
GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f)
{
switch (f)
{
......@@ -262,7 +262,7 @@ static GLenum gl_compare_func(enum wined3d_cmp_func f)
static void state_zfunc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
GLenum depth_func = gl_compare_func(state->render_states[WINED3D_RS_ZFUNC]);
GLenum depth_func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ZFUNC]);
const struct wined3d_gl_info *gl_info = context->gl_info;
if (!depth_func) return;
......@@ -566,7 +566,7 @@ static void state_alpha(struct wined3d_context *context, const struct wined3d_st
else
{
ref = ((float)state->render_states[WINED3D_RS_ALPHAREF]) / 255.0f;
glParm = gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
glParm = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
}
if (glParm)
{
......@@ -835,9 +835,9 @@ static void state_stencil(struct wined3d_context *context, const struct wined3d_
onesided_enable = state->render_states[WINED3D_RS_STENCILENABLE];
twosided_enable = state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE];
if (!(func = gl_compare_func(state->render_states[WINED3D_RS_STENCILFUNC])))
if (!(func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_STENCILFUNC])))
func = GL_ALWAYS;
if (!(func_ccw = gl_compare_func(state->render_states[WINED3D_RS_CCW_STENCILFUNC])))
if (!(func_ccw = wined3d_gl_compare_func(state->render_states[WINED3D_RS_CCW_STENCILFUNC])))
func_ccw = GL_ALWAYS;
ref = state->render_states[WINED3D_RS_STENCILREF];
mask = state->render_states[WINED3D_RS_STENCILMASK];
......@@ -3709,8 +3709,42 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state
unsigned int base_level;
wined3d_sampler_desc_from_sampler_states(&desc, gl_info, sampler_states, texture);
wined3d_texture_bind(texture, context, srgb);
wined3d_texture_apply_sampler_desc(texture, &desc, gl_info);
if (!gl_info->supported[ARB_SAMPLER_OBJECTS])
{
wined3d_texture_apply_sampler_desc(texture, &desc, gl_info);
}
else
{
struct wined3d_device *device = context->swapchain->device;
struct wined3d_sampler *sampler;
struct wine_rb_entry *entry;
if ((entry = wine_rb_get(&device->samplers, &desc)))
{
sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
}
else
{
if (FAILED(wined3d_sampler_create(device, &desc, NULL, &sampler)))
{
ERR("Failed to create sampler.\n");
sampler = NULL;
}
else
{
if (wine_rb_put(&device->samplers, &desc, &sampler->entry) == -1)
ERR("Failed to insert sampler.\n");
}
}
if (sampler)
{
GL_EXTCALL(glBindSampler(sampler_idx, sampler->name));
checkGLcall("glBindSampler");
}
}
if (texture->flags & WINED3D_TEXTURE_COND_NP2)
base_level = 0;
......
......@@ -194,7 +194,7 @@
@ cdecl wined3d_rendertarget_view_incref(ptr)
@ cdecl wined3d_rendertarget_view_set_parent(ptr ptr)
@ cdecl wined3d_sampler_create(ptr ptr ptr)
@ cdecl wined3d_sampler_create(ptr ptr ptr ptr)
@ cdecl wined3d_sampler_decref(ptr)
@ cdecl wined3d_sampler_get_parent(ptr)
@ cdecl wined3d_sampler_incref(ptr)
......
......@@ -71,6 +71,7 @@ enum wined3d_gl_extension
ARB_POINT_PARAMETERS,
ARB_POINT_SPRITE,
ARB_PROVOKING_VERTEX,
ARB_SAMPLER_OBJECTS,
ARB_SHADER_BIT_ENCODING,
ARB_SHADER_OBJECTS,
ARB_SHADER_TEXTURE_LOD,
......
......@@ -1994,6 +1994,7 @@ struct wined3d_device
struct list resources; /* a linked list to track resources created by the device */
struct list shaders; /* a linked list to track shaders (pixel and vertex) */
struct wine_rb_tree samplers;
/* Render Target Support */
struct wined3d_fb_state fb;
......@@ -2388,9 +2389,12 @@ void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) D
struct wined3d_sampler
{
struct wine_rb_entry entry;
LONG refcount;
struct wined3d_device *device;
void *parent;
struct wined3d_sampler_desc desc;
GLuint name;
};
struct wined3d_vertex_declaration_element
......
......@@ -2452,7 +2452,7 @@ void * __cdecl wined3d_rendertarget_view_get_sub_resource_parent(const struct wi
ULONG __cdecl wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view);
void __cdecl wined3d_rendertarget_view_set_parent(struct wined3d_rendertarget_view *view, void *parent);
HRESULT __cdecl wined3d_sampler_create(const struct wined3d_sampler_desc *desc,
HRESULT __cdecl wined3d_sampler_create(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
void *parent, struct wined3d_sampler **sampler);
ULONG __cdecl wined3d_sampler_decref(struct wined3d_sampler *sampler);
void * __cdecl wined3d_sampler_get_parent(const struct wined3d_sampler *sampler);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment