void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) { if (!GPU_non_power_of_two_support() && (!is_power_of_2_i(x) || !is_power_of_2_i(y)) ) { InitNonPow2Tex(pix, x,y,mipmap); return; } glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { int i; ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ibuf = IMB_allocFromBuffer(pix, NULL, x, y); IMB_makemipmap(ibuf, true); for (i = 0; i < ibuf->miptot; i++) { ImBuf *mip = IMB_getmipmap(ibuf, i); glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); } IMB_freeImBuf(ibuf); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix ); } if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); }
MINLINE int power_of_2_max_i(int n) { if (is_power_of_2_i(n)) return n; while (!is_power_of_2_i(n)) n = n & (n - 1); return n * 2; }
static void split_width(int x, int n, int *splitx, int *nx) { int a, newnx, waste; /* if already power of two just use it */ if (is_power_of_2_i(x)) { splitx[0] = x; (*nx)++; return; } if (n == 1) { /* last part, we have to go larger */ splitx[0] = power_of_2_max_i(x); (*nx)++; } else { /* two or more parts to go, use smaller part */ splitx[0] = power_of_2_min_i(x); newnx = ++(*nx); split_width(x - splitx[0], n - 1, splitx + 1, &newnx); for (waste = 0, a = 0; a < n; a++) waste += splitx[a]; /* if we waste more space or use the same amount, * revert deeper splits and just use larger */ if (waste >= power_of_2_max_i(x)) { splitx[0] = power_of_2_max_i(x); memset(splitx + 1, 0, sizeof(int) * (n - 1)); } else *nx = newnx; } }
MINLINE int power_of_2_min_i(int n) { while (!is_power_of_2_i(n)) n = n & (n - 1); return n; }
int BL_Texture::GetPow2(int n) { if (!is_power_of_2_i(n)) n = power_of_2_min_i(n); return n; }
static int power_of_2_min_i(int num) { while (!is_power_of_2_i(num)) num= num&(num-1); return num; }
bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) { if (!GLEW_ARB_texture_cube_map) { spit("cubemaps not supported"); mOk = false; return mOk; } else if (!cubemap || cubemap->ima->ok==0) { mOk = false; return mOk; } ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL); if (ibuf==0) { cubemap->ima->ok = 0; mOk = false; return mOk; } mNeedsDeleted = 1; mType = GL_TEXTURE_CUBE_MAP_ARB; mTexture = 0; mUnit = unit; ActivateUnit(mUnit); BL_TextureMap::iterator mapLook = g_textureManager.find(cubemap->ima->id.name); if (mapLook != g_textureManager.end()) { if (mapLook->second.gl_texture != 0 && mapLook->second.ref_buffer == cubemap->ima) { mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); mOk = IsValid(); BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } } glGenTextures(1, (GLuint*)&mTexture); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); // track created units BL_TextureObject obj; obj.gl_texture = mTexture; obj.ref_buffer = cubemap->ima; g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)cubemap->ima->id.name, obj)); bool needs_split = false; if (!cubemap->cube[0]) { needs_split = true; spit ("Re-Generating texture buffer"); } if (needs_split) my_envmap_split_ima(cubemap, ibuf); if (!is_power_of_2_i(cubemap->cube[0]->x) || !is_power_of_2_i(cubemap->cube[0]->y)) { spit("invalid envmap size please render with CubeRes @ power of two"); my_free_envmapdata(cubemap); mOk = false; BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } #define SetCubeMapFace(face, num) \ glTexImage2D(face, 0,GL_RGBA, \ cubemap->cube[num]->x, \ cubemap->cube[num]->y, \ 0, GL_RGBA, GL_UNSIGNED_BYTE, \ cubemap->cube[num]->rect) SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); if (GLEW_VERSION_1_2) glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); if (needs_split) my_free_envmapdata(cubemap); glDisable(GL_TEXTURE_CUBE_MAP_ARB); ActivateUnit(0); mOk = IsValid(); BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; }