2 * Copyright 2012, 2015 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/port.h"
23 #include "wined3d_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
27 ULONG CDECL
wined3d_sampler_incref(struct wined3d_sampler
*sampler
)
29 ULONG refcount
= InterlockedIncrement(&sampler
->refcount
);
31 TRACE("%p increasing refcount to %u.\n", sampler
, refcount
);
36 static void wined3d_sampler_destroy_object(void *object
)
38 struct wined3d_sampler
*sampler
= object
;
39 const struct wined3d_gl_info
*gl_info
;
40 struct wined3d_context
*context
;
44 context
= context_acquire(sampler
->device
, NULL
, 0);
45 gl_info
= context
->gl_info
;
46 GL_EXTCALL(glDeleteSamplers(1, &sampler
->name
));
47 context_release(context
);
50 HeapFree(GetProcessHeap(), 0, sampler
);
53 ULONG CDECL
wined3d_sampler_decref(struct wined3d_sampler
*sampler
)
55 ULONG refcount
= InterlockedDecrement(&sampler
->refcount
);
57 TRACE("%p decreasing refcount to %u.\n", sampler
, refcount
);
61 sampler
->parent_ops
->wined3d_object_destroyed(sampler
->parent
);
62 wined3d_cs_destroy_object(sampler
->device
->cs
, wined3d_sampler_destroy_object
, sampler
);
68 void * CDECL
wined3d_sampler_get_parent(const struct wined3d_sampler
*sampler
)
70 TRACE("sampler %p.\n", sampler
);
72 return sampler
->parent
;
75 static void wined3d_sampler_cs_init(void *object
)
77 struct wined3d_sampler
*sampler
= object
;
78 const struct wined3d_sampler_desc
*desc
;
79 const struct wined3d_gl_info
*gl_info
;
80 struct wined3d_context
*context
;
82 context
= context_acquire(sampler
->device
, NULL
, 0);
83 gl_info
= context
->gl_info
;
85 desc
= &sampler
->desc
;
86 GL_EXTCALL(glGenSamplers(1, &sampler
->name
));
87 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_WRAP_S
,
88 gl_info
->wrap_lookup
[desc
->address_u
- WINED3D_TADDRESS_WRAP
]));
89 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_WRAP_T
,
90 gl_info
->wrap_lookup
[desc
->address_v
- WINED3D_TADDRESS_WRAP
]));
91 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_WRAP_R
,
92 gl_info
->wrap_lookup
[desc
->address_w
- WINED3D_TADDRESS_WRAP
]));
93 GL_EXTCALL(glSamplerParameterfv(sampler
->name
, GL_TEXTURE_BORDER_COLOR
, &desc
->border_color
[0]));
94 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_MAG_FILTER
,
95 wined3d_gl_mag_filter(desc
->mag_filter
)));
96 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_MIN_FILTER
,
97 wined3d_gl_min_mip_filter(desc
->min_filter
, desc
->mip_filter
)));
98 GL_EXTCALL(glSamplerParameterf(sampler
->name
, GL_TEXTURE_LOD_BIAS
, desc
->lod_bias
));
99 GL_EXTCALL(glSamplerParameterf(sampler
->name
, GL_TEXTURE_MIN_LOD
, desc
->min_lod
));
100 GL_EXTCALL(glSamplerParameterf(sampler
->name
, GL_TEXTURE_MAX_LOD
, desc
->max_lod
));
101 if (gl_info
->supported
[ARB_TEXTURE_FILTER_ANISOTROPIC
])
102 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_MAX_ANISOTROPY
, desc
->max_anisotropy
));
104 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_COMPARE_MODE
, GL_COMPARE_R_TO_TEXTURE
));
105 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_COMPARE_FUNC
,
106 wined3d_gl_compare_func(desc
->comparison_func
)));
107 if ((context
->d3d_info
->wined3d_creation_flags
& WINED3D_SRGB_READ_WRITE_CONTROL
)
108 && gl_info
->supported
[EXT_TEXTURE_SRGB_DECODE
] && !desc
->srgb_decode
)
109 GL_EXTCALL(glSamplerParameteri(sampler
->name
, GL_TEXTURE_SRGB_DECODE_EXT
, GL_SKIP_DECODE_EXT
));
110 checkGLcall("sampler creation");
112 TRACE("Created sampler %u.\n", sampler
->name
);
114 context_release(context
);
117 static void wined3d_sampler_init(struct wined3d_sampler
*sampler
, struct wined3d_device
*device
,
118 const struct wined3d_sampler_desc
*desc
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
120 sampler
->refcount
= 1;
121 sampler
->device
= device
;
122 sampler
->parent
= parent
;
123 sampler
->parent_ops
= parent_ops
;
124 sampler
->desc
= *desc
;
126 if (device
->adapter
->gl_info
.supported
[ARB_SAMPLER_OBJECTS
])
127 wined3d_cs_init_object(device
->cs
, wined3d_sampler_cs_init
, sampler
);
130 HRESULT CDECL
wined3d_sampler_create(struct wined3d_device
*device
, const struct wined3d_sampler_desc
*desc
,
131 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_sampler
**sampler
)
133 struct wined3d_sampler
*object
;
135 TRACE("device %p, desc %p, parent %p, sampler %p.\n", device
, desc
, parent
, sampler
);
137 if (desc
->address_u
< WINED3D_TADDRESS_WRAP
|| desc
->address_u
> WINED3D_TADDRESS_MIRROR_ONCE
138 || desc
->address_v
< WINED3D_TADDRESS_WRAP
|| desc
->address_v
> WINED3D_TADDRESS_MIRROR_ONCE
139 || desc
->address_w
< WINED3D_TADDRESS_WRAP
|| desc
->address_w
> WINED3D_TADDRESS_MIRROR_ONCE
)
140 return WINED3DERR_INVALIDCALL
;
142 if (desc
->mag_filter
< WINED3D_TEXF_POINT
|| desc
->mag_filter
> WINED3D_TEXF_LINEAR
143 || desc
->min_filter
< WINED3D_TEXF_POINT
|| desc
->min_filter
> WINED3D_TEXF_LINEAR
144 || desc
->mip_filter
> WINED3D_TEXF_LINEAR
)
145 return WINED3DERR_INVALIDCALL
;
147 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
148 return E_OUTOFMEMORY
;
150 wined3d_sampler_init(object
, device
, desc
, parent
, parent_ops
);
152 TRACE("Created sampler %p.\n", object
);
158 static void texture_apply_base_level(struct wined3d_texture
*texture
,
159 const struct wined3d_sampler_desc
*desc
, const struct wined3d_gl_info
*gl_info
)
161 struct gl_texture
*gl_tex
;
162 unsigned int base_level
;
164 if (texture
->flags
& WINED3D_TEXTURE_COND_NP2
)
166 else if (desc
->mip_filter
== WINED3D_TEXF_NONE
)
167 base_level
= texture
->lod
;
169 base_level
= min(max(desc
->mip_base_level
, texture
->lod
), texture
->level_count
- 1);
171 gl_tex
= wined3d_texture_get_gl_texture(texture
, texture
->flags
& WINED3D_TEXTURE_IS_SRGB
);
172 if (base_level
!= gl_tex
->base_level
)
174 /* Note that WINED3D_SAMP_MAX_MIP_LEVEL specifies the largest mipmap
175 * (default 0), while GL_TEXTURE_MAX_LEVEL specifies the smallest
176 * mipmap used (default 1000). So WINED3D_SAMP_MAX_MIP_LEVEL
177 * corresponds to GL_TEXTURE_BASE_LEVEL. */
178 gl_info
->gl_ops
.gl
.p_glTexParameteri(texture
->target
, GL_TEXTURE_BASE_LEVEL
, base_level
);
179 gl_tex
->base_level
= base_level
;
183 /* This function relies on the correct texture being bound and loaded. */
184 void wined3d_sampler_bind(struct wined3d_sampler
*sampler
, unsigned int unit
,
185 struct wined3d_texture
*texture
, const struct wined3d_context
*context
)
187 const struct wined3d_gl_info
*gl_info
= context
->gl_info
;
189 if (gl_info
->supported
[ARB_SAMPLER_OBJECTS
])
191 GL_EXTCALL(glBindSampler(unit
, sampler
->name
));
192 checkGLcall("bind sampler");
196 wined3d_texture_apply_sampler_desc(texture
, &sampler
->desc
, context
);
200 ERR("Could not apply sampler state.\n");
204 texture_apply_base_level(texture
, &sampler
->desc
, gl_info
);