Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_texture.c
| Context not available. | |||||
| GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ | GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ | ||||
| GPUTexture *invalid_tex_2D; | GPUTexture *invalid_tex_2D; | ||||
| GPUTexture *invalid_tex_3D; | GPUTexture *invalid_tex_3D; | ||||
| } GG = {NULL, NULL, NULL}; | GPUTexture *depth_tex; | ||||
| } GG = {NULL, NULL, NULL, NULL}; | |||||
| /* GPUTexture */ | /* GPUTexture */ | ||||
| Context not available. | |||||
| } | } | ||||
| static GPUTexture *GPU_texture_create_nD( | static GPUTexture *GPU_texture_create_nD( | ||||
| int w, int h, int n, const float *fpixels, int depth, | int w, int h, int n, const float *fpixels, int mode, | ||||
| GPUHDRType hdr_type, int components, int samples, | GPUHDRType hdr_type, int components, int samples, | ||||
| char err_out[256]) | char err_out[256]) | ||||
| { | { | ||||
| Context not available. | |||||
| tex->refcount = 1; | tex->refcount = 1; | ||||
| tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); | tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); | ||||
| tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D; | tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D; | ||||
| tex->depth = depth; | tex->depth = (mode & GPU_TEXTURE_DEPTH); | ||||
| tex->fb_attachment = -1; | tex->fb_attachment = -1; | ||||
| glGenTextures(1, &tex->bindcode); | glGenTextures(1, &tex->bindcode); | ||||
| Context not available. | |||||
| tex->number = 0; | tex->number = 0; | ||||
| glBindTexture(tex->target, tex->bindcode); | glBindTexture(tex->target, tex->bindcode); | ||||
| if (depth) { | if (tex->depth) { | ||||
| type = GL_UNSIGNED_BYTE; | type = GL_UNSIGNED_BYTE; | ||||
| format = GL_DEPTH_COMPONENT; | format = GL_DEPTH_COMPONENT; | ||||
| internalformat = GL_DEPTH_COMPONENT; | internalformat = GL_DEPTH_COMPONENT; | ||||
| Context not available. | |||||
| if (pixels) | if (pixels) | ||||
| MEM_freeN(pixels); | MEM_freeN(pixels); | ||||
| if (depth) { | if (tex->depth) { | ||||
| glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
| glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
| glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); | if (mode & GPU_TEXTURE_DEPTH_COMPARE) { | ||||
| glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); | glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); | ||||
| glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); | |||||
| } | |||||
| glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); | glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); | ||||
| } | } | ||||
| else { | else { | ||||
| Context not available. | |||||
| return tex; | return tex; | ||||
| } | } | ||||
| GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels) | GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels) | ||||
| { | { | ||||
| GLenum type, format, internalformat; | GLenum type, format, internalformat; | ||||
| Context not available. | |||||
| GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256]) | GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out); | GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, GPU_TEXTURE_MODE_NONE, GPU_HDR_NONE, 4, 0, err_out); | ||||
| if (tex) | if (tex) | ||||
| GPU_texture_unbind(tex); | GPU_texture_unbind(tex); | ||||
| Context not available. | |||||
| GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256]) | GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out); | GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, GPU_TEXTURE_MODE_NONE, hdr, 4, 0, err_out); | ||||
| if (tex) | if (tex) | ||||
| GPU_texture_unbind(tex); | GPU_texture_unbind(tex); | ||||
| Context not available. | |||||
| GPUTexture *GPU_texture_create_2D_multisample( | GPUTexture *GPU_texture_create_2D_multisample( | ||||
| int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256]) | int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out); | GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, GPU_TEXTURE_MODE_NONE, hdr, 4, samples, err_out); | ||||
| if (tex) | if (tex) | ||||
| GPU_texture_unbind(tex); | GPU_texture_unbind(tex); | ||||
| Context not available. | |||||
| return tex; | return tex; | ||||
| } | } | ||||
| GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]) | GPUTexture *GPU_texture_create_depth(int w, int h, bool compare, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out); | const int mode = GPU_TEXTURE_DEPTH | (compare ? GPU_TEXTURE_DEPTH_COMPARE : 0); | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, mode, GPU_HDR_NONE, 1, 0, err_out); | |||||
| if (tex) | if (tex) | ||||
| GPU_texture_unbind(tex); | GPU_texture_unbind(tex); | ||||
| return tex; | return tex; | ||||
| } | } | ||||
| GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]) | GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, bool compare, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out); | const int mode = GPU_TEXTURE_DEPTH | (compare ? GPU_TEXTURE_DEPTH_COMPARE : 0); | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, mode, GPU_HDR_NONE, 1, samples, err_out); | |||||
| if (tex) | if (tex) | ||||
| GPU_texture_unbind(tex); | GPU_texture_unbind(tex); | ||||
| Context not available. | |||||
| */ | */ | ||||
| GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]) | GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out); | GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, GPU_TEXTURE_MODE_NONE, GPU_HDR_FULL_FLOAT, 2, 0, err_out); | ||||
| if (tex) { | if (tex) { | ||||
| /* Now we tweak some of the settings */ | /* Now we tweak some of the settings */ | ||||
| Context not available. | |||||
| GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]) | GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out); | GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, GPU_TEXTURE_MODE_NONE, GPU_HDR_HALF_FLOAT, 2, 0, err_out); | ||||
| if (tex) { | if (tex) { | ||||
| /* Now we tweak some of the settings */ | /* Now we tweak some of the settings */ | ||||
| Context not available. | |||||
| GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]) | GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]) | ||||
| { | { | ||||
| GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out); | GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, GPU_TEXTURE_MODE_NONE, GPU_HDR_HALF_FLOAT, 2, 0, err_out); | ||||
| if (tex) { | if (tex) { | ||||
| /* Now we tweak some of the settings */ | /* Now we tweak some of the settings */ | ||||
| Context not available. | |||||
| return tex; | return tex; | ||||
| } | } | ||||
| GPUTexture **GPU_texture_global_depth_ptr(void) | |||||
| { | |||||
| return &GG.depth_tex; | |||||
| } | |||||
| void GPU_texture_set_global_depth(GPUTexture *depthtex) | |||||
| { | |||||
| if (depthtex) { | |||||
| GG.depth_tex = depthtex; | |||||
| } | |||||
| else { | |||||
| GG.depth_tex = GG.invalid_tex_2D; | |||||
| } | |||||
| } | |||||
| void GPU_invalid_tex_init(void) | void GPU_invalid_tex_init(void) | ||||
| { | { | ||||
| const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; | const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; | ||||
| GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL); | GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL); | ||||
| GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL); | GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL); | ||||
| GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color); | GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color); | ||||
| GG.depth_tex = GG.invalid_tex_2D; | |||||
| } | } | ||||
| void GPU_invalid_tex_bind(int mode) | void GPU_invalid_tex_bind(int mode) | ||||
| Context not available. | |||||
| return tex->number; | return tex->number; | ||||
| } | } | ||||
| void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter) | void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter, bool mipmap) | ||||
| { | { | ||||
| if (tex->number >= GPU_max_textures()) { | if (tex->number >= GPU_max_textures()) { | ||||
| fprintf(stderr, "Not enough texture slots.\n"); | fprintf(stderr, "Not enough texture slots.\n"); | ||||
| Context not available. | |||||
| GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number); | GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number); | ||||
| if (tex->number != 0) glActiveTexture(arbnumber); | if (tex->number != 0) glActiveTexture(arbnumber); | ||||
| int target = tex->target; | |||||
| if (tex->depth) { | if (tex->depth) { | ||||
| if (compare) | if (compare) | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); | glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); | ||||
| else | else | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); | glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_NONE); | ||||
| } | } | ||||
| if (use_filter) { | if (use_filter) { | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | if (mipmap) { | ||||
| glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | |||||
| } | |||||
| else { | |||||
| glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||||
| } | |||||
| } | } | ||||
| else { | else { | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
| } | } | ||||
| if (tex->number != 0) glActiveTexture(GL_TEXTURE0); | if (tex->number != 0) glActiveTexture(GL_TEXTURE0); | ||||
| GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind"); | GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind"); | ||||
| } | } | ||||
| void GPU_texture_generate_mipmap(GPUTexture *tex) | |||||
| { | |||||
| if (tex->number >= GPU_max_textures()) { | |||||
| fprintf(stderr, "Not enough texture slots.\n"); | |||||
| return; | |||||
| } | |||||
| if (tex->number == -1) { | |||||
| return; | |||||
| } | |||||
| GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind"); | |||||
| GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number); | |||||
| if (tex->number != 0) { | |||||
| glActiveTexture(arbnumber); | |||||
| } | |||||
| glGenerateMipmap(tex->target); | |||||
| if (tex->number != 0) { | |||||
| glActiveTexture(GL_TEXTURE0); | |||||
| } | |||||
| GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind"); | |||||
| } | |||||
| void GPU_texture_free(GPUTexture *tex) | void GPU_texture_free(GPUTexture *tex) | ||||
| { | { | ||||
| tex->refcount--; | tex->refcount--; | ||||
| Context not available. | |||||
| tex->refcount++; | tex->refcount++; | ||||
| } | } | ||||
| int GPU_texture_ref_count(GPUTexture *tex) | |||||
| { | |||||
| return tex->refcount; | |||||
| } | |||||
| int GPU_texture_target(const GPUTexture *tex) | int GPU_texture_target(const GPUTexture *tex) | ||||
| { | { | ||||
| return tex->target; | return tex->target; | ||||
| Context not available. | |||||
| return tex->bindcode; | return tex->bindcode; | ||||
| } | } | ||||
| void GPU_texture_set_opengl_bindcode(GPUTexture *tex, int bindcode) | |||||
| { | |||||
| tex->bindcode = bindcode; | |||||
| } | |||||
| GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex) | GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex) | ||||
| { | { | ||||
| return tex->fb; | return tex->fb; | ||||
| Context not available. | |||||