static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256]) { GPUTexture *tex; GLenum type, format, internalformat; void *pixels = NULL; if (depth && !GLEW_ARB_depth_texture) return NULL; tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; tex->number = -1; tex->refcount = 1; tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; tex->depth = depth; glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { if (err_out) { BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d", (int)glGetError()); } else { fprintf(stderr, "GPUTexture: texture create failed: %d\n", (int)glGetError()); } GPU_texture_free(tex); return NULL; } if (!GPU_non_power_of_two_support()) { tex->w = power_of_2_max_i(tex->w); tex->h = power_of_2_max_i(tex->h); } tex->number = 0; glBindTexture(tex->target, tex->bindcode); if (depth) { type = GL_UNSIGNED_BYTE; format = GL_DEPTH_COMPONENT; internalformat = GL_DEPTH_COMPONENT; } else { type = GL_UNSIGNED_BYTE; format = GL_RGBA; internalformat = GL_RGBA8; if (fpixels) pixels = GPU_texture_convert_pixels(w*h, fpixels); } if (tex->target == GL_TEXTURE_1D) { glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL); if (fpixels) { glTexSubImage1D(tex->target, 0, 0, w, format, type, pixels ? pixels : fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, 1); } } else { glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, type, NULL); if (fpixels) { glTexSubImage2D(tex->target, 0, 0, 0, w, h, format, type, pixels ? pixels : fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); if (tex->h > h) GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); } } if (pixels) MEM_freeN(pixels); if (depth) { glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); } else { glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (tex->target != GL_TEXTURE_1D) { /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */ GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER; glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode); glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode); #if 0 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); #endif } else glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return tex; }
static GPUTexture *GPU_texture_create_nD( int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components, int samples, char err_out[256]) { GLenum type, format, internalformat; void *pixels = NULL; if (samples) { CLAMP_MAX(samples, GPU_max_color_texture_samples()); } GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; tex->number = -1; tex->refcount = 1; 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->depth = depth; tex->fb_attachment = -1; glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { if (err_out) { BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d", (int)glGetError()); } else { fprintf(stderr, "GPUTexture: texture create failed: %d\n", (int)glGetError()); } GPU_texture_free(tex); return NULL; } if (!GPU_full_non_power_of_two_support()) { tex->w = power_of_2_max_i(tex->w); tex->h = power_of_2_max_i(tex->h); } tex->number = 0; glBindTexture(tex->target, tex->bindcode); if (depth) { type = GL_UNSIGNED_BYTE; format = GL_DEPTH_COMPONENT; internalformat = GL_DEPTH_COMPONENT; } else { type = GL_FLOAT; if (components == 4) { format = GL_RGBA; switch (hdr_type) { case GPU_HDR_NONE: internalformat = GL_RGBA8; break; /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ case GPU_HDR_HALF_FLOAT: internalformat = GL_RGBA16F_ARB; break; case GPU_HDR_FULL_FLOAT: internalformat = GL_RGBA32F_ARB; break; default: break; } } else if (components == 2) { /* these formats rely on ARB_texture_rg or OpenGL 3.0 */ format = GL_RG; switch (hdr_type) { case GPU_HDR_NONE: internalformat = GL_RG8; break; case GPU_HDR_HALF_FLOAT: internalformat = GL_RG16F; break; case GPU_HDR_FULL_FLOAT: internalformat = GL_RG32F; break; default: break; } } if (fpixels && hdr_type == GPU_HDR_NONE) { type = GL_UNSIGNED_BYTE; pixels = GPU_texture_convert_pixels(w * h, fpixels); } } if (tex->target == GL_TEXTURE_1D) { glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL); if (fpixels) { glTexSubImage1D(tex->target, 0, 0, w, format, type, pixels ? pixels : fpixels); if (tex->w > w) { GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1); } } } else { if (samples) { glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); } else { glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, type, NULL); } if (fpixels) { glTexSubImage2D(tex->target, 0, 0, 0, w, h, format, type, pixels ? pixels : fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h); if (tex->h > h) GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h); } } if (pixels) MEM_freeN(pixels); if (depth) { 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_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); } else { glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (tex->target_base != GL_TEXTURE_1D) { glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return tex; }