Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_texture.c
| Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | struct GPUTexture { | ||||
| GLenum target; /* GL_TEXTURE_* */ | GLenum target; /* GL_TEXTURE_* */ | ||||
| GLenum target_base; /* same as target, (but no multisample) | GLenum target_base; /* same as target, (but no multisample) | ||||
| * use it for unbinding */ | * use it for unbinding */ | ||||
| GLuint bindcode; /* opengl identifier for texture */ | GLuint bindcode; /* opengl identifier for texture */ | ||||
| eGPUTextureFormat format; | eGPUTextureFormat format; | ||||
| eGPUTextureFormatFlag format_flag; | eGPUTextureFormatFlag format_flag; | ||||
| uint bytesize; /* number of byte for one pixel */ | int mipmaps; /* number of mipmaps */ | ||||
| int components; /* number of color/alpha channels */ | int components; /* number of color/alpha channels */ | ||||
| int samples; /* number of samples for multisamples textures. 0 if not multisample target */ | int samples; /* number of samples for multisamples textures. 0 if not multisample target */ | ||||
| int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED]; | int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED]; | ||||
| GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED]; | GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED]; | ||||
| }; | }; | ||||
| static uint gpu_get_bytesize(eGPUTextureFormat data_type); | |||||
| /* ------ Memory Management ------- */ | /* ------ Memory Management ------- */ | ||||
| /* Records every texture allocation / free | /* Records every texture allocation / free | ||||
| * to estimate the Texture Pool Memory consumption */ | * to estimate the Texture Pool Memory consumption */ | ||||
| static uint memory_usage; | static uint memory_usage; | ||||
| static uint gpu_texture_memory_footprint_compute(GPUTexture *tex) | static uint gpu_texture_memory_footprint_compute(GPUTexture *tex) | ||||
| { | { | ||||
| int samp = max_ii(tex->samples, 1); | uint memsize; | ||||
| const uint bytesize = gpu_get_bytesize(tex->format); | |||||
| const int samp = max_ii(tex->samples, 1); | |||||
| switch (tex->target_base) { | switch (tex->target_base) { | ||||
| case GL_TEXTURE_1D: | case GL_TEXTURE_1D: | ||||
| return tex->bytesize * tex->w * samp; | case GL_TEXTURE_BUFFER: | ||||
| memsize = bytesize * tex->w * samp; | |||||
| break; | |||||
| case GL_TEXTURE_1D_ARRAY: | case GL_TEXTURE_1D_ARRAY: | ||||
| case GL_TEXTURE_2D: | case GL_TEXTURE_2D: | ||||
| return tex->bytesize * tex->w * tex->h * samp; | memsize = bytesize * tex->w * tex->h * samp; | ||||
| break; | |||||
| case GL_TEXTURE_2D_ARRAY: | case GL_TEXTURE_2D_ARRAY: | ||||
| case GL_TEXTURE_3D: | case GL_TEXTURE_3D: | ||||
| return tex->bytesize * tex->w * tex->h * tex->d * samp; | memsize = bytesize * tex->w * tex->h * tex->d * samp; | ||||
| break; | |||||
| case GL_TEXTURE_CUBE_MAP: | case GL_TEXTURE_CUBE_MAP: | ||||
| return tex->bytesize * 6 * tex->w * tex->h * samp; | memsize = bytesize * 6 * tex->w * tex->h * samp; | ||||
| break; | |||||
| case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: | case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: | ||||
| return tex->bytesize * 6 * tex->w * tex->h * tex->d * samp; | memsize = bytesize * 6 * tex->w * tex->h * tex->d * samp; | ||||
| break; | |||||
| default: | default: | ||||
| BLI_assert(0); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (tex->mipmaps != 0) { | |||||
| /* Just to get an idea of the memory used here is computed | |||||
| * as if the maximum number of mipmaps was generated. */ | |||||
| memsize += memsize / 3; | |||||
| } | |||||
| return memsize; | |||||
| } | } | ||||
| static void gpu_texture_memory_footprint_add(GPUTexture *tex) | static void gpu_texture_memory_footprint_add(GPUTexture *tex) | ||||
| { | { | ||||
| memory_usage += gpu_texture_memory_footprint_compute(tex); | memory_usage += gpu_texture_memory_footprint_compute(tex); | ||||
| } | } | ||||
| static void gpu_texture_memory_footprint_remove(GPUTexture *tex) | static void gpu_texture_memory_footprint_remove(GPUTexture *tex) | ||||
| ▲ Show 20 Lines • Show All 232 Lines • ▼ Show 20 Lines | switch (data_type) { | ||||
| case GPU_RGBA32F: | case GPU_RGBA32F: | ||||
| return 32; | return 32; | ||||
| case GPU_RG32F: | case GPU_RG32F: | ||||
| case GPU_RGBA16F: | case GPU_RGBA16F: | ||||
| case GPU_RGBA16: | case GPU_RGBA16: | ||||
| return 16; | return 16; | ||||
| case GPU_RGB16F: | case GPU_RGB16F: | ||||
| return 12; | return 12; | ||||
| case GPU_DEPTH32F_STENCIL8: | case GPU_DEPTH32F_STENCIL8: /* 32-bit depth, 8 bits stencil, and 24 unused bits. */ | ||||
fclem: typo: bits * | |||||
| return 8; | return 8; | ||||
| case GPU_RG16F: | case GPU_RG16F: | ||||
| case GPU_RG16I: | case GPU_RG16I: | ||||
| case GPU_RG16UI: | case GPU_RG16UI: | ||||
| case GPU_RG16: | case GPU_RG16: | ||||
| case GPU_DEPTH24_STENCIL8: | case GPU_DEPTH24_STENCIL8: | ||||
| case GPU_DEPTH_COMPONENT32F: | case GPU_DEPTH_COMPONENT32F: | ||||
| case GPU_RGBA8UI: | case GPU_RGBA8UI: | ||||
| Show All 17 Lines | switch (data_type) { | ||||
| case GPU_R8UI: | case GPU_R8UI: | ||||
| return 1; | return 1; | ||||
| default: | default: | ||||
| BLI_assert(!"Texture format incorrect or unsupported\n"); | BLI_assert(!"Texture format incorrect or unsupported\n"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| static GLenum gpu_get_gl_internalformat(eGPUTextureFormat format) | static GLenum gpu_format_to_gl_internalformat(eGPUTextureFormat format) | ||||
Done Inline Actionschange function name to gpu_format_to_gl_internalformat fclem: change function name to `gpu_format_to_gl_internalformat` | |||||
| { | { | ||||
| /* You can add any of the available type to this list | /* You can add any of the available type to this list | ||||
Done Inline ActionsI don't really like this. Keep the switch case and duplicate for gl_internalformat_to_gpu_format. fclem: I don't really like this. Keep the switch case and duplicate for… | |||||
| * For available types see GPU_texture.h */ | * For available types see GPU_texture.h */ | ||||
| switch (format) { | switch (format) { | ||||
| /* Formats texture & renderbuffer */ | /* Formats texture & renderbuffer */ | ||||
| case GPU_RGBA8UI: | |||||
| return GL_RGBA8UI; | |||||
| case GPU_RGBA8I: | |||||
| return GL_RGBA8I; | |||||
| case GPU_RGBA8: | |||||
| return GL_RGBA8; | |||||
| case GPU_RGBA32UI: | |||||
| return GL_RGBA32UI; | |||||
| case GPU_RGBA32I: | |||||
| return GL_RGBA32I; | |||||
| case GPU_RGBA32F: | case GPU_RGBA32F: | ||||
| return GL_RGBA32F; | return GL_RGBA32F; | ||||
| case GPU_RGBA16UI: | |||||
| return GL_RGBA16UI; | |||||
| case GPU_RGBA16I: | |||||
| return GL_RGBA16I; | |||||
| case GPU_RGBA16F: | case GPU_RGBA16F: | ||||
| return GL_RGBA16F; | return GL_RGBA16F; | ||||
| case GPU_RGBA16: | case GPU_RGBA16: | ||||
| return GL_RGBA16; | return GL_RGBA16; | ||||
| case GPU_RG8UI: | |||||
| return GL_RG8UI; | |||||
| case GPU_RG8I: | |||||
| return GL_RG8I; | |||||
| case GPU_RG8: | |||||
| return GL_RG8; | |||||
| case GPU_RG32UI: | |||||
| return GL_RG32UI; | |||||
| case GPU_RG32I: | |||||
| return GL_RG32I; | |||||
| case GPU_RG32F: | case GPU_RG32F: | ||||
| return GL_RG32F; | return GL_RG32F; | ||||
| case GPU_RGB16F: | case GPU_RG16UI: | ||||
| return GL_RGB16F; | return GL_RG16UI; | ||||
| case GPU_RG16F: | |||||
| return GL_RG16F; | |||||
| case GPU_RG16I: | case GPU_RG16I: | ||||
| return GL_RG16I; | return GL_RG16I; | ||||
| case GPU_RG16F: | |||||
| return GL_RGBA32F; | |||||
| case GPU_RG16: | case GPU_RG16: | ||||
| return GL_RG16; | return GL_RG16; | ||||
| case GPU_RGBA8: | case GPU_R8UI: | ||||
| return GL_RGBA8; | return GL_R8UI; | ||||
| case GPU_RGBA8UI: | case GPU_R8I: | ||||
| return GL_RGBA8UI; | GL_R8I; | ||||
| case GPU_SRGB8_A8: | case GPU_R8: | ||||
| return GL_SRGB8_ALPHA8; | return GL_R8; | ||||
| case GPU_R32F: | |||||
| return GL_R32F; | |||||
| case GPU_R32UI: | case GPU_R32UI: | ||||
| return GL_R32UI; | return GL_R32UI; | ||||
| case GPU_R32I: | case GPU_R32I: | ||||
| return GL_R32I; | return GL_R32I; | ||||
| case GPU_R16F: | case GPU_R32F: | ||||
| return GL_R16F; | return GL_R32F; | ||||
| case GPU_R16I: | |||||
| return GL_R16I; | |||||
| case GPU_R16UI: | case GPU_R16UI: | ||||
| return GL_R16UI; | return GL_R16UI; | ||||
| case GPU_RG8: | case GPU_R16I: | ||||
| return GL_RG8; | return GL_R16I; | ||||
| case GPU_RG16UI: | case GPU_R16F: | ||||
| return GL_RG16UI; | return GL_R16F; | ||||
| case GPU_R16: | case GPU_R16: | ||||
| return GL_R16; | return GL_R16; | ||||
| case GPU_R8: | |||||
| return GL_R8; | |||||
| case GPU_R8UI: | |||||
| return GL_R8UI; | |||||
| /* Special formats texture & renderbuffer */ | /* Special formats texture & renderbuffer */ | ||||
| case GPU_R11F_G11F_B10F: | case GPU_R11F_G11F_B10F: | ||||
| return GL_R11F_G11F_B10F; | return GL_R11F_G11F_B10F; | ||||
| case GPU_DEPTH24_STENCIL8: | |||||
| return GL_DEPTH24_STENCIL8; | |||||
| case GPU_DEPTH32F_STENCIL8: | case GPU_DEPTH32F_STENCIL8: | ||||
| return GL_DEPTH32F_STENCIL8; | return GL_DEPTH32F_STENCIL8; | ||||
| case GPU_DEPTH24_STENCIL8: | |||||
| return GL_DEPTH24_STENCIL8; | |||||
| case GPU_SRGB8_A8: | |||||
| return GL_SRGB8_ALPHA8; | |||||
| /* Texture only format */ | /* Texture only format */ | ||||
| /* ** Add Format here */ | case GPU_RGB16F: | ||||
| return GL_RGB16F; | |||||
| /* Special formats texture only */ | /* Special formats texture only */ | ||||
| /* ** Add Format here */ | /* ** Add Format here */ | ||||
| /* Depth Formats */ | /* Depth Formats */ | ||||
| case GPU_DEPTH_COMPONENT32F: | case GPU_DEPTH_COMPONENT32F: | ||||
| return GL_DEPTH_COMPONENT32F; | return GL_DEPTH_COMPONENT32F; | ||||
| case GPU_DEPTH_COMPONENT24: | case GPU_DEPTH_COMPONENT24: | ||||
| return GL_DEPTH_COMPONENT24; | return GL_DEPTH_COMPONENT24; | ||||
| case GPU_DEPTH_COMPONENT16: | case GPU_DEPTH_COMPONENT16: | ||||
| return GL_DEPTH_COMPONENT16; | return GL_DEPTH_COMPONENT16; | ||||
| default: | default: | ||||
| BLI_assert(!"Texture format incorrect or unsupported\n"); | BLI_assert(!"Texture format incorrect or unsupported\n"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| static eGPUTextureFormat gl_internalformat_to_gpu_format(const GLenum glformat) | |||||
| { | |||||
Done Inline Actionschange function name to gl_internalformat_to_gpu_format fclem: change function name to `gl_internalformat_to_gpu_format` | |||||
| /* You can add any of the available type to this list | |||||
| * For available types see GPU_texture.h */ | |||||
| switch (glformat) { | |||||
| /* Formats texture & renderbuffer */ | |||||
| case GL_RGBA8UI: | |||||
| return GPU_RGBA8UI; | |||||
| case GL_RGBA8I: | |||||
| return GPU_RGBA8I; | |||||
| case GL_RGBA8: | |||||
| return GPU_RGBA8; | |||||
| case GL_RGBA32UI: | |||||
| return GPU_RGBA32UI; | |||||
| case GL_RGBA32I: | |||||
| return GPU_RGBA32I; | |||||
| case GL_RGBA32F: | |||||
| return GPU_RGBA32F; | |||||
| case GL_RGBA16UI: | |||||
| return GPU_RGBA16UI; | |||||
| case GL_RGBA16I: | |||||
| return GPU_RGBA16I; | |||||
| case GL_RGBA16F: | |||||
| return GPU_RGBA16F; | |||||
| case GL_RGBA16: | |||||
| return GPU_RGBA16; | |||||
| case GL_RG8UI: | |||||
| return GPU_RG8UI; | |||||
| case GL_RG8I: | |||||
| return GPU_RG8I; | |||||
| case GL_RG8: | |||||
| return GPU_RG8; | |||||
| case GL_RG32UI: | |||||
| return GPU_RG32UI; | |||||
| case GL_RG32I: | |||||
| return GPU_RG32I; | |||||
| case GL_RG32F: | |||||
| return GPU_RG32F; | |||||
| case GL_RG16UI: | |||||
| return GPU_RG16UI; | |||||
| case GL_RG16I: | |||||
| return GPU_RG16I; | |||||
| case GL_RG16F: | |||||
| return GPU_RGBA32F; | |||||
| case GL_RG16: | |||||
| return GPU_RG16; | |||||
| case GL_R8UI: | |||||
| return GPU_R8UI; | |||||
| case GL_R8I: | |||||
| GPU_R8I; | |||||
| case GL_R8: | |||||
| return GPU_R8; | |||||
| case GL_R32UI: | |||||
| return GPU_R32UI; | |||||
| case GL_R32I: | |||||
| return GPU_R32I; | |||||
| case GL_R32F: | |||||
| return GPU_R32F; | |||||
| case GL_R16UI: | |||||
| return GPU_R16UI; | |||||
| case GL_R16I: | |||||
| return GPU_R16I; | |||||
| case GL_R16F: | |||||
| return GPU_R16F; | |||||
| case GL_R16: | |||||
| return GPU_R16; | |||||
| /* Special formats texture & renderbuffer */ | |||||
| case GL_R11F_G11F_B10F: | |||||
| return GPU_R11F_G11F_B10F; | |||||
| case GL_DEPTH32F_STENCIL8: | |||||
| return GPU_DEPTH32F_STENCIL8; | |||||
| case GL_DEPTH24_STENCIL8: | |||||
| return GPU_DEPTH24_STENCIL8; | |||||
| case GL_SRGB8_ALPHA8: | |||||
| return GPU_SRGB8_A8; | |||||
| /* Texture only format */ | |||||
| case GL_RGB16F: | |||||
| return GPU_RGB16F; | |||||
| /* Special formats texture only */ | |||||
| /* ** Add Format here */ | |||||
| /* Depth Formats */ | |||||
| case GL_DEPTH_COMPONENT32F: | |||||
| return GPU_DEPTH_COMPONENT32F; | |||||
| case GL_DEPTH_COMPONENT24: | |||||
| return GPU_DEPTH_COMPONENT24; | |||||
| case GL_DEPTH_COMPONENT16: | |||||
| return GPU_DEPTH_COMPONENT16; | |||||
| default: | |||||
| BLI_assert(!"Internal format incorrect or unsupported\n"); | |||||
| return -1; | |||||
| } | |||||
| } | |||||
| static GLenum gpu_get_gl_datatype(eGPUDataFormat format) | static GLenum gpu_get_gl_datatype(eGPUDataFormat format) | ||||
| { | { | ||||
| switch (format) { | switch (format) { | ||||
| case GPU_DATA_FLOAT: | case GPU_DATA_FLOAT: | ||||
| return GL_FLOAT; | return GL_FLOAT; | ||||
| case GPU_DATA_INT: | case GPU_DATA_INT: | ||||
| return GL_INT; | return GL_INT; | ||||
| case GPU_DATA_UNSIGNED_INT: | case GPU_DATA_UNSIGNED_INT: | ||||
| ▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | GPUTexture *GPU_texture_create_nD(int w, | ||||
| tex->w = w; | tex->w = w; | ||||
| tex->h = h; | tex->h = h; | ||||
| tex->d = d; | tex->d = d; | ||||
| tex->samples = samples; | tex->samples = samples; | ||||
| tex->number = -1; | tex->number = -1; | ||||
| tex->refcount = 1; | tex->refcount = 1; | ||||
| tex->format = tex_format; | tex->format = tex_format; | ||||
| tex->components = gpu_get_component_count(tex_format); | tex->components = gpu_get_component_count(tex_format); | ||||
| tex->bytesize = gpu_get_bytesize(tex_format); | tex->mipmaps = 0; | ||||
| tex->format_flag = 0; | tex->format_flag = 0; | ||||
| if (n == 2) { | if (n == 2) { | ||||
| if (d == 0) { | if (d == 0) { | ||||
| tex->target_base = tex->target = GL_TEXTURE_2D; | tex->target_base = tex->target = GL_TEXTURE_2D; | ||||
| } | } | ||||
| else { | else { | ||||
| tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY; | tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY; | ||||
| Show All 19 Lines | GPUTexture *GPU_texture_create_nD(int w, | ||||
| } | } | ||||
| gpu_validate_data_format(tex_format, gpu_data_format); | gpu_validate_data_format(tex_format, gpu_data_format); | ||||
| if (samples && n == 2 && d == 0) { | if (samples && n == 2 && d == 0) { | ||||
| tex->target = GL_TEXTURE_2D_MULTISAMPLE; | tex->target = GL_TEXTURE_2D_MULTISAMPLE; | ||||
| } | } | ||||
| GLenum internalformat = gpu_get_gl_internalformat(tex_format); | GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); | ||||
| GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); | GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); | ||||
| GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | ||||
| /* Generate Texture object */ | /* Generate Texture object */ | ||||
| tex->bindcode = GPU_tex_alloc(); | tex->bindcode = GPU_tex_alloc(); | ||||
| if (!tex->bindcode) { | if (!tex->bindcode) { | ||||
| if (err_out) { | if (err_out) { | ||||
| ▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | GPUTexture *GPU_texture_cube_create(int w, | ||||
| tex->w = w; | tex->w = w; | ||||
| tex->h = w; | tex->h = w; | ||||
| tex->d = d; | tex->d = d; | ||||
| tex->samples = 0; | tex->samples = 0; | ||||
| tex->number = -1; | tex->number = -1; | ||||
| tex->refcount = 1; | tex->refcount = 1; | ||||
| tex->format = tex_format; | tex->format = tex_format; | ||||
| tex->components = gpu_get_component_count(tex_format); | tex->components = gpu_get_component_count(tex_format); | ||||
| tex->bytesize = gpu_get_bytesize(tex_format); | tex->mipmaps = 0; | ||||
| tex->format_flag = GPU_FORMAT_CUBE; | tex->format_flag = GPU_FORMAT_CUBE; | ||||
| if (d == 0) { | if (d == 0) { | ||||
| tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP; | tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP; | ||||
| } | } | ||||
| else { | else { | ||||
| tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY_ARB; | tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY_ARB; | ||||
| tex->format_flag |= GPU_FORMAT_ARRAY; | tex->format_flag |= GPU_FORMAT_ARRAY; | ||||
| if (!GPU_arb_texture_cube_map_array_is_supported()) { | if (!GPU_arb_texture_cube_map_array_is_supported()) { | ||||
| fprintf(stderr, "ERROR: Attempt to create a cubemap array without hardware support!\n"); | fprintf(stderr, "ERROR: Attempt to create a cubemap array without hardware support!\n"); | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| GPU_texture_free(tex); | GPU_texture_free(tex); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (d > GPU_max_texture_layers() / 6) { | if (d > GPU_max_texture_layers() / 6) { | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| GPU_texture_free(tex); | GPU_texture_free(tex); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| GLenum internalformat = gpu_get_gl_internalformat(tex_format); | GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); | ||||
| GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); | GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); | ||||
| GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | ||||
| /* Generate Texture object */ | /* Generate Texture object */ | ||||
| tex->bindcode = GPU_tex_alloc(); | tex->bindcode = GPU_tex_alloc(); | ||||
| if (!tex->bindcode) { | if (!tex->bindcode) { | ||||
| if (err_out) { | if (err_out) { | ||||
| ▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); | GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); | ||||
| tex->number = -1; | tex->number = -1; | ||||
| tex->refcount = 1; | tex->refcount = 1; | ||||
| tex->format = tex_format; | tex->format = tex_format; | ||||
| tex->components = gpu_get_component_count(tex_format); | tex->components = gpu_get_component_count(tex_format); | ||||
| tex->format_flag = 0; | tex->format_flag = 0; | ||||
| tex->target_base = tex->target = GL_TEXTURE_BUFFER; | tex->target_base = tex->target = GL_TEXTURE_BUFFER; | ||||
| tex->bytesize = gpu_get_bytesize(tex_format); | tex->mipmaps = 0; | ||||
| GLenum internalformat = gpu_get_gl_internalformat(tex_format); | GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); | ||||
| gpu_get_gl_dataformat(tex_format, &tex->format_flag); | gpu_get_gl_dataformat(tex_format, &tex->format_flag); | ||||
| if (!(ELEM(tex_format, GPU_R8, GPU_R16) || ELEM(tex_format, GPU_R16F, GPU_R32F) || | if (!(ELEM(tex_format, GPU_R8, GPU_R16) || ELEM(tex_format, GPU_R16F, GPU_R32F) || | ||||
| ELEM(tex_format, GPU_R8I, GPU_R16I, GPU_R32I) || | ELEM(tex_format, GPU_R8I, GPU_R16I, GPU_R32I) || | ||||
| ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_R32UI) || ELEM(tex_format, GPU_RG8, GPU_RG16) || | ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_R32UI) || ELEM(tex_format, GPU_RG8, GPU_RG16) || | ||||
| ELEM(tex_format, GPU_RG16F, GPU_RG32F) || | ELEM(tex_format, GPU_RG16F, GPU_RG32F) || | ||||
| ELEM(tex_format, GPU_RG8I, GPU_RG16I, GPU_RG32I) || | ELEM(tex_format, GPU_RG8I, GPU_RG16I, GPU_RG32I) || | ||||
| Show All 16 Lines | if (!tex->bindcode) { | ||||
| GPU_texture_free(tex); | GPU_texture_free(tex); | ||||
| BLI_assert( | BLI_assert( | ||||
| 0 && "glGenTextures failed: Are you sure a valid OGL context is active on this thread?\n"); | 0 && "glGenTextures failed: Are you sure a valid OGL context is active on this thread?\n"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| glBindTexture(tex->target, tex->bindcode); | glBindTexture(tex->target, tex->bindcode); | ||||
| glTexBuffer(tex->target, internalformat, buffer); | glTexBuffer(tex->target, internalformat, buffer); | ||||
| glGetTexLevelParameteriv(tex->target, 0, GL_TEXTURE_WIDTH, &tex->w); | |||||
| glBindTexture(tex->target, 0); | glBindTexture(tex->target, 0); | ||||
| gpu_texture_memory_footprint_add(tex); | |||||
| return tex; | return tex; | ||||
| } | } | ||||
| GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode) | GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode) | ||||
| { | { | ||||
| GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); | GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); | ||||
| tex->bindcode = bindcode; | tex->bindcode = bindcode; | ||||
| tex->number = -1; | tex->number = -1; | ||||
| tex->refcount = 1; | tex->refcount = 1; | ||||
| tex->target = textarget; | tex->target = textarget; | ||||
| tex->target_base = textarget; | tex->target_base = textarget; | ||||
| tex->format = -1; | |||||
| tex->components = -1; | |||||
| tex->samples = 0; | tex->samples = 0; | ||||
| if (!glIsTexture(tex->bindcode)) { | if (!glIsTexture(tex->bindcode)) { | ||||
| GPU_print_error_debug("Blender Texture Not Loaded"); | GPU_print_error_debug("Blender Texture Not Loaded"); | ||||
| } | } | ||||
| else { | else { | ||||
| GLint w, h; | GLint w, h; | ||||
| GLenum gettarget, gl_format; | |||||
| GLenum gettarget = textarget; | gettarget = (textarget == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : textarget; | ||||
| if (textarget == GL_TEXTURE_CUBE_MAP) { | |||||
| gettarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; | |||||
| } | |||||
| glBindTexture(textarget, tex->bindcode); | glBindTexture(textarget, tex->bindcode); | ||||
| glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w); | glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w); | ||||
| glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); | glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); | ||||
| glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &gl_format); | |||||
| tex->w = w; | tex->w = w; | ||||
| tex->h = h; | tex->h = h; | ||||
| tex->format = gl_internalformat_to_gpu_format(gl_format); | |||||
| tex->components = gpu_get_component_count(tex->format); | |||||
| glBindTexture(textarget, 0); | glBindTexture(textarget, 0); | ||||
| /* Depending on how this bindcode was obtained, the memory used here could | |||||
| * already have been computed. | |||||
| * But that is not the case currently. */ | |||||
| gpu_texture_memory_footprint_add(tex); | |||||
| } | } | ||||
| return tex; | return tex; | ||||
| } | } | ||||
| GPUTexture *GPU_texture_create_1d(int w, | GPUTexture *GPU_texture_create_1d(int w, | ||||
| eGPUTextureFormat tex_format, | eGPUTextureFormat tex_format, | ||||
| const float *pixels, | const float *pixels, | ||||
| ▲ Show 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | |||||
| void GPU_texture_add_mipmap(GPUTexture *tex, | void GPU_texture_add_mipmap(GPUTexture *tex, | ||||
| eGPUDataFormat gpu_data_format, | eGPUDataFormat gpu_data_format, | ||||
| int miplvl, | int miplvl, | ||||
| const void *pixels) | const void *pixels) | ||||
| { | { | ||||
| BLI_assert((int)tex->format > -1); | BLI_assert((int)tex->format > -1); | ||||
| BLI_assert(tex->components > -1); | BLI_assert(tex->components > -1); | ||||
| BLI_assert(miplvl > tex->mipmaps); | |||||
Done Inline ActionsPrefer testing miplvl > tex->mipmaps. fclem: Prefer testing miplvl > tex->mipmaps. | |||||
| gpu_validate_data_format(tex->format, gpu_data_format); | gpu_validate_data_format(tex->format, gpu_data_format); | ||||
| GLenum internalformat = gpu_get_gl_internalformat(tex->format); | GLenum internalformat = gpu_format_to_gl_internalformat(tex->format); | ||||
| GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); | GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); | ||||
| GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | ||||
| glBindTexture(tex->target, tex->bindcode); | glBindTexture(tex->target, tex->bindcode); | ||||
| int size[3]; | int size[3]; | ||||
| GPU_texture_get_mipmap_size(tex, miplvl, size); | GPU_texture_get_mipmap_size(tex, miplvl, size); | ||||
| Show All 29 Lines | case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: | ||||
| pixels); | pixels); | ||||
| break; | break; | ||||
| case GL_TEXTURE_2D_MULTISAMPLE: | case GL_TEXTURE_2D_MULTISAMPLE: | ||||
| /* Multisample textures cannot have mipmaps. */ | /* Multisample textures cannot have mipmaps. */ | ||||
| default: | default: | ||||
| BLI_assert(!"tex->target mode not supported"); | BLI_assert(!"tex->target mode not supported"); | ||||
| } | } | ||||
| tex->mipmaps = miplvl; | |||||
| glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, miplvl); | glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, miplvl); | ||||
| glBindTexture(tex->target, 0); | glBindTexture(tex->target, 0); | ||||
| } | } | ||||
| void GPU_texture_update_sub(GPUTexture *tex, | void GPU_texture_update_sub(GPUTexture *tex, | ||||
| eGPUDataFormat gpu_data_format, | eGPUDataFormat gpu_data_format, | ||||
| const void *pixels, | const void *pixels, | ||||
| int offset_x, | int offset_x, | ||||
| int offset_y, | int offset_y, | ||||
| int offset_z, | int offset_z, | ||||
| int width, | int width, | ||||
| int height, | int height, | ||||
| int depth) | int depth) | ||||
| { | { | ||||
| BLI_assert((int)tex->format > -1); | BLI_assert((int)tex->format > -1); | ||||
| BLI_assert(tex->components > -1); | BLI_assert(tex->components > -1); | ||||
| const uint bytesize = gpu_get_bytesize(tex->format); | |||||
| GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); | GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); | ||||
| GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | ||||
| GLint alignment; | GLint alignment; | ||||
| /* The default pack size for textures is 4, which won't work for byte based textures */ | /* The default pack size for textures is 4, which won't work for byte based textures */ | ||||
| if (tex->bytesize == 1) { | if (bytesize == 1) { | ||||
| glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); | glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); | ||||
| glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
| } | } | ||||
| glBindTexture(tex->target, tex->bindcode); | glBindTexture(tex->target, tex->bindcode); | ||||
| switch (tex->target) { | switch (tex->target) { | ||||
| case GL_TEXTURE_1D: | case GL_TEXTURE_1D: | ||||
| glTexSubImage1D(tex->target, 0, offset_x, width, data_format, data_type, pixels); | glTexSubImage1D(tex->target, 0, offset_x, width, data_format, data_type, pixels); | ||||
| Show All 17 Lines | case GL_TEXTURE_2D_ARRAY: | ||||
| data_format, | data_format, | ||||
| data_type, | data_type, | ||||
| pixels); | pixels); | ||||
| break; | break; | ||||
| default: | default: | ||||
| BLI_assert(!"tex->target mode not supported"); | BLI_assert(!"tex->target mode not supported"); | ||||
| } | } | ||||
| if (tex->bytesize == 1) { | if (bytesize == 1) { | ||||
| glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); | glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); | ||||
| } | } | ||||
| glBindTexture(tex->target, 0); | glBindTexture(tex->target, 0); | ||||
| } | } | ||||
| void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl) | void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl) | ||||
| { | { | ||||
| BLI_assert(miplvl <= tex->mipmaps); | |||||
Done Inline ActionsPrefer testing miplvl <= tex->mipmaps fclem: Prefer testing miplvl <= tex->mipmaps | |||||
| int size[3] = {0, 0, 0}; | int size[3] = {0, 0, 0}; | ||||
| GPU_texture_get_mipmap_size(tex, miplvl, size); | GPU_texture_get_mipmap_size(tex, miplvl, size); | ||||
| gpu_validate_data_format(tex->format, gpu_data_format); | gpu_validate_data_format(tex->format, gpu_data_format); | ||||
| size_t samples_count = max_ii(1, tex->samples); | size_t samples_count = max_ii(1, tex->samples); | ||||
| samples_count *= size[0]; | samples_count *= size[0]; | ||||
| samples_count *= max_ii(1, size[1]); | samples_count *= max_ii(1, size[1]); | ||||
| Show All 36 Lines | if (GLEW_ARB_clear_texture) { | ||||
| GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); | GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); | ||||
| GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | GLenum data_type = gpu_get_gl_datatype(gpu_data_format); | ||||
| glClearTexImage(tex->bindcode, 0, data_format, data_type, color); | glClearTexImage(tex->bindcode, 0, data_format, data_type, color); | ||||
| } | } | ||||
| else { | else { | ||||
| size_t buffer_len = gpu_texture_memory_footprint_compute(tex); | size_t buffer_len = gpu_texture_memory_footprint_compute(tex); | ||||
| unsigned char *pixels = MEM_mallocN(buffer_len, __func__); | unsigned char *pixels = MEM_mallocN(buffer_len, __func__); | ||||
| if (color) { | if (color) { | ||||
| size_t bytesize = tex->bytesize; | const size_t bytesize = (size_t)gpu_get_bytesize(tex->format); | ||||
Done Inline Actionswhy uint? fclem: why uint? | |||||
| for (size_t byte = 0; byte < buffer_len; byte += bytesize) { | for (size_t byte = 0; byte < buffer_len; byte += bytesize) { | ||||
| memcpy(&pixels[byte], color, bytesize); | memcpy(&pixels[byte], color, bytesize); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| memset(pixels, 0, buffer_len); | memset(pixels, 0, buffer_len); | ||||
| } | } | ||||
| GPU_texture_update(tex, gpu_data_format, pixels); | GPU_texture_update(tex, gpu_data_format, pixels); | ||||
| ▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | #define WARN_NOT_BOUND(_tex) \ | ||||
| } \ | } \ | ||||
| } \ | } \ | ||||
| ((void)0) | ((void)0) | ||||
| void GPU_texture_generate_mipmap(GPUTexture *tex) | void GPU_texture_generate_mipmap(GPUTexture *tex) | ||||
| { | { | ||||
| WARN_NOT_BOUND(tex); | WARN_NOT_BOUND(tex); | ||||
| gpu_texture_memory_footprint_remove(tex); | |||||
| int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); | |||||
| glActiveTexture(GL_TEXTURE0 + tex->number); | glActiveTexture(GL_TEXTURE0 + tex->number); | ||||
| if (GPU_texture_depth(tex)) { | if (GPU_texture_depth(tex)) { | ||||
| /* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789). | /* 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. | * 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 | * You must initialize the texture levels using other methods like | ||||
| * GPU_framebuffer_recursive_downsample(). */ | * GPU_framebuffer_recursive_downsample(). */ | ||||
| int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); | |||||
| eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format); | eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format); | ||||
| for (int i = 1; i < levels; i++) { | for (int i = 1; i < levels; i++) { | ||||
| GPU_texture_add_mipmap(tex, data_format, i, NULL); | GPU_texture_add_mipmap(tex, data_format, i, NULL); | ||||
| } | } | ||||
| glBindTexture(tex->target, tex->bindcode); | glBindTexture(tex->target, tex->bindcode); | ||||
| } | } | ||||
| else { | else { | ||||
| glGenerateMipmap(tex->target_base); | glGenerateMipmap(tex->target_base); | ||||
| } | } | ||||
| tex->mipmaps = levels; | |||||
| gpu_texture_memory_footprint_add(tex); | |||||
| } | } | ||||
| void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare) | void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare) | ||||
| { | { | ||||
| WARN_NOT_BOUND(tex); | WARN_NOT_BOUND(tex); | ||||
| /* Could become an assertion ? (fclem) */ | /* Could become an assertion ? (fclem) */ | ||||
| if (!GPU_texture_depth(tex)) { | if (!GPU_texture_depth(tex)) { | ||||
| ▲ Show 20 Lines • Show All 252 Lines • Show Last 20 Lines | |||||
typo: bits *