Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern/gpu_texture.c')
-rw-r--r--source/blender/gpu/intern/gpu_texture.c232
1 files changed, 116 insertions, 116 deletions
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 38ba8bc612f..1d870ed2fdc 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -50,7 +50,9 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_1D;
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
-} GG = {NULL, NULL, NULL};
+ /** Sampler objects used to replace internal texture parameters. */
+ GLuint samplers[GPU_SAMPLER_MAX];
+} GG = {NULL};
/* Maximum number of FBOs a texture can be attached to. */
#define GPU_TEX_MAX_FBO_ATTACHED 12
@@ -72,7 +74,7 @@ typedef enum eGPUTextureFormatFlag {
struct GPUTexture {
int w, h, d; /* width/height/depth */
int orig_w, orig_h; /* width/height (of source data), optional. */
- int number; /* number for multitexture binding */
+ int number; /* Texture unit to which this texture is bound. */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
GLenum target_base; /* same as target, (but no multisample)
@@ -81,6 +83,7 @@ struct GPUTexture {
eGPUTextureFormat format;
eGPUTextureFormatFlag format_flag;
+ eGPUSamplerState sampler_state; /* Internal Sampler state. */
int mipmaps; /* number of mipmaps */
int components; /* number of color/alpha channels */
@@ -827,12 +830,12 @@ GPUTexture *GPU_texture_create_nD(int w,
tex->h = h;
tex->d = d;
tex->samples = samples;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = 0;
+ tex->number = -1;
if (n == 2) {
if (d == 0) {
@@ -976,26 +979,13 @@ GPUTexture *GPU_texture_create_nD(int w,
if (GPU_texture_stencil(tex) || /* Does not support filtering */
GPU_texture_integer(tex) || /* Does not support filtering */
GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- if (GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
-
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- if (n > 1) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- if (n > 2) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1014,12 +1004,12 @@ GPUTexture *GPU_texture_cube_create(int w,
tex->h = w;
tex->d = d;
tex->samples = 0;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = GPU_FORMAT_CUBE;
+ tex->number = -1;
if (d == 0) {
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -1117,22 +1107,13 @@ GPUTexture *GPU_texture_cube_create(int w,
if (GPU_texture_stencil(tex) || /* Does not support filtering */
GPU_texture_integer(tex) || /* Does not support filtering */
GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
-
- if (GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
-
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1143,13 +1124,13 @@ GPUTexture *GPU_texture_cube_create(int w,
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint buffer)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->format_flag = 0;
tex->target_base = tex->target = GL_TEXTURE_BUFFER;
tex->mipmaps = 0;
+ tex->number = -1;
GLenum internalformat = gpu_format_to_gl_internalformat(tex_format);
@@ -1196,11 +1177,15 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->bindcode = bindcode;
- tex->number = -1;
tex->refcount = 1;
tex->target = textarget;
tex->target_base = textarget;
tex->samples = 0;
+ tex->sampler_state = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO;
+ if (GPU_get_mipmap()) {
+ tex->sampler_state |= (GPU_SAMPLER_MIPMAP | GPU_SAMPLER_FILTER);
+ }
+ tex->number = -1;
if (!glIsTexture(tex->bindcode)) {
GPU_print_error_debug("Blender Texture Not Loaded");
@@ -1727,16 +1712,17 @@ void GPU_invalid_tex_free(void)
}
}
-void GPU_texture_bind(GPUTexture *tex, int number)
+/* set_number is to save the the texture unit for setting texture parameters. */
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number)
{
- BLI_assert(number >= 0);
+ BLI_assert(unit >= 0);
- if (number >= GPU_max_textures()) {
+ if (unit >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
- if ((G.debug & G_DEBUG)) {
+ if (G.debug & G_DEBUG) {
for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; i++) {
if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
fprintf(stderr,
@@ -1748,16 +1734,27 @@ void GPU_texture_bind(GPUTexture *tex, int number)
}
}
- glActiveTexture(GL_TEXTURE0 + number);
+ if (set_number) {
+ tex->number = unit;
+ }
+
+ glActiveTexture(GL_TEXTURE0 + unit);
+
+ state = (state < GPU_SAMPLER_MAX) ? state : tex->sampler_state;
if (tex->bindcode != 0) {
glBindTexture(tex->target, tex->bindcode);
+ glBindSampler(unit, GG.samplers[state]);
}
else {
GPU_invalid_tex_bind(tex->target_base);
+ glBindSampler(unit, 0);
}
+}
- tex->number = number;
+void GPU_texture_bind(GPUTexture *tex, int unit)
+{
+ GPU_texture_bind_ex(tex, GPU_SAMPLER_MAX, unit, true);
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -1768,13 +1765,26 @@ void GPU_texture_unbind(GPUTexture *tex)
glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target, 0);
-
+ glBindSampler(tex->number, 0);
tex->number = -1;
}
-int GPU_texture_bound_number(GPUTexture *tex)
+void GPU_texture_unbind_all(void)
{
- return tex->number;
+ for (int i = 0; i < GPU_max_textures(); i++) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_1D, 0);
+ glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_3D, 0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ if (GPU_arb_texture_cube_map_array_is_supported()) {
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0);
+ }
+ glBindSampler(i, 0);
+ }
}
#define WARN_NOT_BOUND(_tex) \
@@ -1798,8 +1808,8 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
if (GPU_texture_depth(tex)) {
/* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789).
- * In this case we just create a complete texture with mipmaps manually without down-sampling.
- * You must initialize the texture levels using other methods like
+ * In this case we just create a complete texture with mipmaps manually without
+ * down-sampling. You must initialize the texture levels using other methods like
* GPU_framebuffer_recursive_downsample(). */
eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format);
for (int i = 1; i < levels; i++) {
@@ -1905,69 +1915,35 @@ void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
- WARN_NOT_BOUND(tex);
-
/* Could become an assertion ? (fclem) */
if (!GPU_texture_depth(tex)) {
return;
}
-
- GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE);
}
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
- BLI_assert((!use_filter && !use_mipmap) ||
+ BLI_assert(!(use_filter || use_mipmap) ||
!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
- GLenum mipmap = ((use_filter) ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR :
- (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
{
- WARN_NOT_BOUND(tex);
-
- GLenum repeat = (use_repeat) ? GL_REPEAT : (use_clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
- }
- if (tex->target_base == GL_TEXTURE_3D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
- }
-
- if (repeat == GL_CLAMP_TO_BORDER) {
- const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, black);
- }
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
+ SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER);
}
void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
@@ -1981,34 +1957,6 @@ void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE);
}
-static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter)
-{
- switch (filter) {
- case GPU_NEAREST:
- return GL_NEAREST;
- case GPU_LINEAR:
- return GL_LINEAR;
- default:
- BLI_assert(!"Unhandled filter mode");
- return GL_NEAREST;
- }
-}
-
-void GPU_texture_filters(GPUTexture *tex,
- eGPUFilterFunction min_filter,
- eGPUFilterFunction mag_filter)
-{
- WARN_NOT_BOUND(tex);
-
- /* Stencil and integer format does not support filtering. */
- BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter));
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
-}
-
void GPU_texture_free(GPUTexture *tex)
{
tex->refcount--;
@@ -2169,3 +2117,55 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
size[2] = max_ii(1, tex->d / div);
}
}
+
+/* -------------------------------------------------------------------- */
+/** \name GPU Sampler Objects
+ *
+ * Simple wrapper around opengl sampler objects.
+ * Override texture sampler state for one sampler unit only.
+ * \{ */
+
+void GPU_samplers_init(void)
+{
+ glGenSamplers(GPU_SAMPLER_MAX, GG.samplers);
+ for (int i = 0; i < GPU_SAMPLER_MAX; i++) {
+ eGPUSamplerState state = i;
+ GLenum clamp_type = (state & GPU_SAMPLER_CLAMP_BORDER) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
+ GLenum wrap_s = (state & GPU_SAMPLER_REPEAT_S) ? GL_REPEAT : clamp_type;
+ GLenum wrap_t = (state & GPU_SAMPLER_REPEAT_T) ? GL_REPEAT : clamp_type;
+ GLenum wrap_r = (state & GPU_SAMPLER_REPEAT_R) ? GL_REPEAT : clamp_type;
+ GLenum mag_filter = (state & GPU_SAMPLER_FILTER) ? GL_LINEAR : GL_NEAREST;
+ GLenum min_filter = (state & GPU_SAMPLER_FILTER) ?
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) :
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
+ GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
+ float aniso_filter = ((state & GPU_SAMPLER_MIPMAP) && (state & GPU_SAMPLER_ANISO)) ?
+ GPU_get_anisotropic() :
+ 1.0f;
+
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_S, wrap_s);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_T, wrap_t);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_R, wrap_r);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MIN_FILTER, min_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MAG_FILTER, mag_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_MODE, compare_mode);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ if (GLEW_EXT_texture_filter_anisotropic) {
+ glSamplerParameterf(GG.samplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso_filter);
+ }
+
+ /** Other states are left to default:
+ * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
+ * - GL_TEXTURE_MIN_LOD is -1000.
+ * - GL_TEXTURE_MAX_LOD is 1000.
+ * - GL_TEXTURE_LOD_BIAS is 0.0f.
+ **/
+ }
+}
+
+void GPU_samplers_free(void)
+{
+ glDeleteSamplers(GPU_SAMPLER_MAX, GG.samplers);
+}
+
+/** \} */