inline void VL_glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) { if (glCompressedTexImage3D) glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); else VL_UNSUPPORTED_FUNC(); }
void Texture3D::init(int w, int h, int d, TextureInternalFormat tf, TextureFormat f, PixelType t, const Parameters ¶ms, const Buffer::Parameters &s, const Buffer &pixels) { Texture::init(tf, params); this->w = w; this->h = h; this->d = d; bindToTextureUnit(); pixels.bind(GL_PIXEL_UNPACK_BUFFER); if (isCompressed() && s.compressedSize() > 0) { glCompressedTexImage3D(GL_TEXTURE_3D, 0, getTextureInternalFormat(internalFormat), w, h, d, 0, s.compressedSize(), pixels.data(0)); } else { s.set(); glTexImage3D(GL_TEXTURE_3D, 0, getTextureInternalFormat(internalFormat), w, h, d, 0, getTextureFormat(f), getPixelType(t), pixels.data(0)); s.unset(); } pixels.unbind(GL_PIXEL_UNPACK_BUFFER); generateMipMap(); if (FrameBuffer::getError() != 0) { throw exception(); } }
bool initTexture() { gli::texture2D Texture(gli::load_dds((getDataDirectory() + TEXTURE_DIFFUSE).c_str())); glGenTextures(1, &TextureName); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, TextureName); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(Texture.levels() - 1)); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_SWIZZLE_R, GL_RED); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_SWIZZLE_G, GL_GREEN); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_SWIZZLE_B, GL_BLUE); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); for(std::size_t Level = 0; Level < Texture.levels(); ++Level) { glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, GLint(Level), GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GLsizei(Texture[Level].dimensions().x), GLsizei(Texture[Level].dimensions().y), GLsizei(1), 0, GLsizei(Texture[Level].size()), Texture[Level].data()); } return this->checkError("initTexture"); }
void APIENTRY FWGLExtension::initCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) { spCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3D)FW_GETGLPROC("glCompressedTexImage3D"); if(!spCompressedTexImage3D) reportError("glCompressedTexImage3D"); glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); }
EXTERN_C_ENTER JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL13_nglCompressedTexImage3D(JNIEnv *__env, jclass clazz, jint target, jint level, jint internalformat, jint width, jint height, jint depth, jint border, jint imageSize, jlong dataAddress, jlong __functionAddress) { const GLvoid *data = (const GLvoid *)(intptr_t)dataAddress; glCompressedTexImage3DPROC glCompressedTexImage3D = (glCompressedTexImage3DPROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); }
void QOpenGLTextureHelper::qt_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits) { GLint oldTexture; glGetIntegerv(bindingTarget, &oldTexture); glBindTexture(target, texture); glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, bits); glBindTexture(target, oldTexture); }
void RenderDevice::uploadTextureData( uint32 texObj, int slice, int mipLevel, const void *pixels ) { const RDITexture &tex = _textures.getRef( texObj ); TextureFormats::List format = tex.format; glActiveTexture( GL_TEXTURE15 ); glBindTexture( tex.type, tex.glObj ); int inputFormat = GL_BGRA, inputType = GL_UNSIGNED_BYTE; bool compressed = (format == TextureFormats::DXT1) || (format == TextureFormats::DXT3) || (format == TextureFormats::DXT5); switch( format ) { case TextureFormats::RGBA16F: inputFormat = GL_RGBA; inputType = GL_FLOAT; break; case TextureFormats::RGBA32F: inputFormat = GL_RGBA; inputType = GL_FLOAT; break; case TextureFormats::DEPTH: inputFormat = GL_DEPTH_COMPONENT; inputType = GL_FLOAT; }; // Calculate size of next mipmap using "floor" convention int width = std::max( tex.width >> mipLevel, 1 ), height = std::max( tex.height >> mipLevel, 1 ); if( tex.type == TextureTypes::Tex2D || tex.type == TextureTypes::TexCube ) { int target = (tex.type == TextureTypes::Tex2D) ? GL_TEXTURE_2D : (GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice); if( compressed ) glCompressedTexImage2D( target, mipLevel, tex.glFmt, width, height, 0, calcTextureSize( format, width, height, 1 ), pixels ); else glTexImage2D( target, mipLevel, tex.glFmt, width, height, 0, inputFormat, inputType, pixels ); } else if( tex.type == TextureTypes::Tex3D ) { int depth = std::max( tex.depth >> mipLevel, 1 ); if( compressed ) glCompressedTexImage3D( GL_TEXTURE_3D, mipLevel, tex.glFmt, width, height, depth, 0, calcTextureSize( format, width, height, depth ), pixels ); else glTexImage3D( GL_TEXTURE_3D, mipLevel, tex.glFmt, width, height, depth, 0, inputFormat, inputType, pixels ); }
PIGLIT_GL_TEST_CONFIG_END static bool test_getsubimage(GLenum target, GLsizei width, GLsizei height, GLsizei numSlices, GLenum intFormat) { const GLint bufSize = width * height * 4 * sizeof(GLubyte); GLubyte *texData; GLubyte *refData = malloc(6 * bufSize); /* 6 for cubemaps */ GLubyte *testData = malloc(6 * bufSize); /* 6 for cubemaps */ GLuint tex; int i, slice, compressedSize, compSize; int blockWidth, blockHeight, blockSize; bool pass = true; const int level = 0; int x0, y0, x1, y1, w0, h0, w1, h1; printf("Testing %s %s %d x %d\n", piglit_get_gl_enum_name(target), piglit_get_gl_enum_name(intFormat), width, height); /* For all S3TC formats */ blockWidth = blockHeight = 4; if (intFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || intFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { blockSize = 8; } else { assert(intFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT || intFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); blockSize = 16; } /* Size must be multiple of block dims */ assert(width % blockWidth == 0); assert(height % blockHeight == 0); compressedSize = (width / blockWidth) * (height / blockHeight) * blockSize; if (0) { printf("byte per block row: %d\n", (width / blockWidth) * blockSize); printf("compressed image size = %d\n", compressedSize); } /* initial texture data */ texData = malloc(compressedSize); for (i = 0; i < compressedSize; i++) { texData[i] = (i+10) & 0xff; } glGenTextures(1, &tex); glBindTexture(target, tex); /* Define texture image */ if (target == GL_TEXTURE_CUBE_MAP) { for (slice = 0; slice < 6; slice++) { glCompressedTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice, level, intFormat, width, height, 0, compressedSize, texData); } glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); assert(numSlices == 6); } else if (target == GL_TEXTURE_CUBE_MAP_ARRAY) { assert(numSlices % 6 == 0); glCompressedTexImage3D(target, level, intFormat, width, height, numSlices, 0, compressedSize * numSlices, NULL); for (slice = 0; slice < numSlices; slice++) { glCompressedTexSubImage3D(target, level, 0, 0, slice, width, height, 1, intFormat, compressedSize, texData); } glGetTexLevelParameteriv(target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); compSize /= numSlices; } else if (target == GL_TEXTURE_2D_ARRAY) { glCompressedTexImage3D(target, level, intFormat, width, height, numSlices, 0, compressedSize * numSlices, NULL); for (slice = 0; slice < numSlices; slice++) { glCompressedTexSubImage3D(target, level, 0, 0, slice, width, height, 1, intFormat, compressedSize, texData); } glGetTexLevelParameteriv(target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); compSize /= numSlices; } else { assert(target == GL_TEXTURE_2D); glCompressedTexImage2D(target, level, intFormat, width, height, 0, compressedSize, texData); glGetTexLevelParameteriv(target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compSize); assert(numSlices == 1); } assert(compSize == compressedSize); /* Should be no GL errors */ if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } refData = calloc(1, numSlices * compressedSize); testData = calloc(1, numSlices * compressedSize); /* compute pos/size of sub-regions */ x0 = 0; y0 = 0; x1 = width / 4; /* quarter width */ y1 = height / 2; /* half height */ /* Position must be multiple of block dims */ assert(x1 % blockWidth == 0); assert(y1 % blockHeight == 0); w0 = x1 - x0; w1 = width - x1; h0 = y1 - y0; h1 = height - y1; /* Sizes must be multiple of block dims */ assert(w0 % blockWidth == 0); assert(w1 % blockWidth == 0); assert(h0 % blockHeight == 0); assert(h1 % blockHeight == 0); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ROW_LENGTH, width); glPixelStorei(GL_PACK_IMAGE_HEIGHT, height); glPixelStorei(GL_PACK_COMPRESSED_BLOCK_WIDTH, blockWidth); glPixelStorei(GL_PACK_COMPRESSED_BLOCK_HEIGHT, blockHeight); glPixelStorei(GL_PACK_COMPRESSED_BLOCK_SIZE, blockSize); /* Should be no GL errors */ if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } /* * Get whole compressed image (the reference) */ if (target == GL_TEXTURE_CUBE_MAP) { for (slice = 0; slice < 6; slice++) { glGetCompressedTexImage( GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice, level, refData + slice * compressedSize); } } else { glGetCompressedTexImage(target, level, refData); } if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } /* * Now get four sub-regions which should be equivalent * to the whole reference image. */ /* lower-left */ glPixelStorei(GL_PACK_SKIP_PIXELS, x0); glPixelStorei(GL_PACK_SKIP_ROWS, y0); glGetCompressedTextureSubImage(tex, level, x0, y0, 0, w0, h0, numSlices, numSlices * compressedSize, testData); /* lower-right */ glPixelStorei(GL_PACK_SKIP_PIXELS, x1); glPixelStorei(GL_PACK_SKIP_ROWS, y0); glGetCompressedTextureSubImage(tex, level, x1, y0, 0, w1, h0, numSlices, numSlices * compressedSize, testData); /* upper-left */ glPixelStorei(GL_PACK_SKIP_PIXELS, x0); glPixelStorei(GL_PACK_SKIP_ROWS, y1); glGetCompressedTextureSubImage(tex, level, x0, y1, 0, w0, h1, numSlices, numSlices * compressedSize, testData); /* upper-right */ glPixelStorei(GL_PACK_SKIP_PIXELS, x1); glPixelStorei(GL_PACK_SKIP_ROWS, y1); glGetCompressedTextureSubImage(tex, level, x1, y1, 0, w1, h1, numSlices, numSlices * compressedSize, testData); /* defaults */ glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); /* Should be no GL errors */ if (!piglit_check_gl_error(GL_NO_ERROR)) { pass = false; } /* now compare the images */ for (slice = 0; slice < numSlices; slice++) { int sliceStart = slice * compressedSize; if (memcmp(refData + sliceStart, testData + sliceStart, compressedSize)) { int i; for (i = 0; i < compressedSize; i++) { if (refData[sliceStart + i] != testData[sliceStart + i]) { printf("fail in slice/face %d at offset %d\n", slice, i); printf("expected %d, found %d\n", refData[sliceStart + i], testData[sliceStart + i]); break; } } printf("Failure for %s %s\n", piglit_get_gl_enum_name(target), piglit_get_gl_enum_name(intFormat)); pass = false; } } free(texData); free(refData); free(testData); glDeleteTextures(1, &tex); return pass; }
bool Texture2DArray::SetData(unsigned layer, unsigned level, int x, int y, int width, int height, const void* data) { URHO3D_PROFILE(SetTextureData); if (!object_.name_ || !graphics_) { URHO3D_LOGERROR("Texture array not created, can not set data"); return false; } if (!data) { URHO3D_LOGERROR("Null source for setting data"); return false; } if (layer >= layers_) { URHO3D_LOGERROR("Illegal layer for setting data"); return false; } if (level >= levels_) { URHO3D_LOGERROR("Illegal mip level for setting data"); return false; } if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture array data assignment while device is lost"); dataPending_ = true; return true; } if (IsCompressed()) { x &= ~3; y &= ~3; } int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); if (x < 0 || x + width > levelWidth || y < 0 || y + height > levelHeight || width <= 0 || height <= 0) { URHO3D_LOGERROR("Illegal dimensions for setting data"); return false; } graphics_->SetTextureForUpdate(this); #ifndef GL_ES_VERSION_2_0 bool wholeLevel = x == 0 && y == 0 && width == levelWidth && height == levelHeight && layer == 0; unsigned format = GetSRGB() ? GetSRGBFormat(format_) : format_; if (!IsCompressed()) { if (wholeLevel) glTexImage3D(target_, level, format, width, height, layers_, 0, GetExternalFormat(format_), GetDataType(format_), 0); glTexSubImage3D(target_, level, x, y, layer, width, height, 1, GetExternalFormat(format_), GetDataType(format_), data); } else { if (wholeLevel) glCompressedTexImage3D(target_, level, format, width, height, layers_, 0, GetDataSize(width, height, layers_), 0); glCompressedTexSubImage3D(target_, level, x, y, layer, width, height, 1, format, GetDataSize(width, height), data); } #endif graphics_->SetTexture(0, 0); return true; }
void OGLESTextureCube::CreateHWResource(ElementInitData const * init_data) { uint32_t texel_size = NumFormatBytes(format_); GLint glinternalFormat; GLenum glformat; GLenum gltype; OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_); glBindTexture(target_type_, texture_); for (uint32_t array_index = 0; array_index < array_size_; ++ array_index) { for (int face = 0; face < 6; ++ face) { for (uint32_t level = 0; level < num_mip_maps_; ++ level) { uint32_t const s = this->Width(level); if (IsCompressedFormat(format_)) { uint32_t const block_size = NumFormatBytes(format_) * 4; GLsizei const image_size = ((s + 3) / 4) * ((s + 3) / 4) * block_size; void* ptr; if (nullptr == init_data) { tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size, 0); ptr = nullptr; } else { tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size); std::memcpy(&tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0], init_data[(array_index * 6 + face) * num_mip_maps_ + level].data, image_size); ptr = &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0]; } if (array_size_ > 1) { if (0 == array_index) { glCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat, s, s, array_size_, 0, image_size * array_size_, nullptr); } if (init_data != nullptr) { glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, 0, 0, array_index, s, s, 1, glformat, image_size, init_data[(array_index * 6 + face) * num_mip_maps_ + level].data); } } else { glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat, s, s, 0, image_size, ptr); } } else { GLsizei const image_size = s * s * texel_size; void* ptr; if (nullptr == init_data) { tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size, 0); ptr = nullptr; } else { tex_data_[(array_index * 6 + face) * num_mip_maps_ + level].resize(image_size); std::memcpy(&tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0], init_data[face * num_mip_maps_ + level].data, image_size); ptr = &tex_data_[(array_index * 6 + face) * num_mip_maps_ + level][0]; } if (array_size_ > 1) { if (0 == array_index) { glTexImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat, s, s, array_size_, 0, glformat, gltype, nullptr); } if (init_data != nullptr) { glTexSubImage3D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, 0, 0, array_index, s, s, 1, glformat, gltype, init_data[array_index * num_mip_maps_ + level].data); } } else { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, glinternalFormat, s, s, 0, glformat, gltype, ptr); } } } } } hw_res_ready_ = true; }
void GLES2Texture::_createGLTexResource() { if(!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_NON_POWER_OF_2_TEXTURES) || (Root::getSingleton().getRenderSystem()->getCapabilities()->getNonPOW2TexturesLimited() && mNumRequestedMipmaps > 0)) { // Convert to nearest power-of-two size if required mWidth = GLES2PixelUtil::optionalPO2(mWidth); mHeight = GLES2PixelUtil::optionalPO2(mHeight); mDepth = GLES2PixelUtil::optionalPO2(mDepth); } // Adjust format if required mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage); GLenum texTarget = getGLES2TextureTarget(); // Check requested number of mipmaps size_t maxMips = GLES2PixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat); if(PixelUtil::isCompressed(mFormat) && (mNumMipmaps == 0)) mNumRequestedMipmaps = 0; mNumMipmaps = mNumRequestedMipmaps; if (mNumMipmaps > maxMips) mNumMipmaps = maxMips; // Generate texture name OGRE_CHECK_GL_ERROR(glGenTextures(1, &mTextureID)); // Set texture type mGLSupport.getStateCacheManager()->bindGLTexture(texTarget, mTextureID); // If we can do automip generation and the user desires this, do so mMipmapsHardwareGenerated = Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP) && !PixelUtil::isCompressed(mFormat); if(!Bitwise::isPO2(mWidth) || !Bitwise::isPO2(mHeight)) mMipmapsHardwareGenerated = false; // glGenerateMipmap require all mip levels to be prepared. So override how many this texture has. if((mUsage & TU_AUTOMIPMAP) && mMipmapsHardwareGenerated && mNumRequestedMipmaps) mNumMipmaps = maxMips; if(getGLES2SupportRef()->checkExtension("GL_APPLE_texture_max_level") || gleswIsSupported(3, 0)) mGLSupport.getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MAX_LEVEL_APPLE, mNumRequestedMipmaps ? mNumMipmaps + 1 : 0); // Set some misc default parameters, these can of course be changed later mGLSupport.getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, ((mUsage & TU_AUTOMIPMAP) && mNumRequestedMipmaps) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST); mGLSupport.getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); mGLSupport.getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); mGLSupport.getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set up texture swizzling #if OGRE_NO_GLES3_SUPPORT == 0 if(gleswIsSupported(3, 0)) { OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_GREEN)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_BLUE)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ALPHA)); if(mFormat == PF_L8 || mFormat == PF_L16) { OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_RED)); } } #endif // Allocate internal buffer so that glTexSubImageXD can be used // Internal format GLenum format = GLES2PixelUtil::getGLOriginFormat(mFormat); GLenum internalformat = GLES2PixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma); uint32 width = mWidth; uint32 height = mHeight; uint32 depth = mDepth; if (PixelUtil::isCompressed(mFormat)) { // Compressed formats GLsizei size = static_cast<GLsizei>(PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat)); // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not // accept a 0 pointer like normal glTexImageXD // Run through this process for every mipmap to pregenerate mipmap pyramid uint8* tmpdata = new uint8[size]; memset(tmpdata, 0, size); for (GLint mip = 0; mip <= mNumMipmaps; mip++) { #if OGRE_DEBUG_MODE LogManager::getSingleton().logMessage("GLES2Texture::create - Mip: " + StringConverter::toString(mip) + " Width: " + StringConverter::toString(width) + " Height: " + StringConverter::toString(height) + " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex) + " Format: " + StringConverter::toString(format, 0, ' ', std::ios::hex) ); #endif size = static_cast<GLsizei>(PixelUtil::getMemorySize(width, height, depth, mFormat)); switch(mTextureType) { case TEX_TYPE_1D: case TEX_TYPE_2D: OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_2D, mip, internalformat, width, height, 0, size, tmpdata)); break; case TEX_TYPE_CUBE_MAP: for(int face = 0; face < 6; face++) { OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat, width, height, 0, size, tmpdata)); } break; #if OGRE_NO_GLES3_SUPPORT == 0 case TEX_TYPE_2D_ARRAY: case TEX_TYPE_3D: glCompressedTexImage3D(getGLES2TextureTarget(), mip, format, width, height, depth, 0, size, tmpdata); break; #endif default: break; }; if(width > 1) { width = width / 2; } if(height > 1) { height = height / 2; } if(depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY) { depth = depth / 2; } } delete [] tmpdata; } else { #if OGRE_NO_GLES3_SUPPORT == 0 #if OGRE_DEBUG_MODE LogManager::getSingleton().logMessage("GLES2Texture::create - Name: " + mName + " ID: " + StringConverter::toString(mTextureID) + " Width: " + StringConverter::toString(width) + " Height: " + StringConverter::toString(height) + " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex)); #endif switch(mTextureType) { case TEX_TYPE_1D: case TEX_TYPE_2D: case TEX_TYPE_2D_RECT: OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_2D, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height))); break; case TEX_TYPE_CUBE_MAP: OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_CUBE_MAP, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height))); break; case TEX_TYPE_2D_ARRAY: OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_2D_ARRAY, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height), GLsizei(depth))); break; case TEX_TYPE_3D: OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_3D, GLsizei(mNumMipmaps+1), internalformat, GLsizei(width), GLsizei(height), GLsizei(depth))); break; } #else GLenum datatype = GLES2PixelUtil::getGLOriginDataType(mFormat); // Run through this process to pregenerate mipmap pyramid for(GLint mip = 0; mip <= mNumMipmaps; mip++) { #if OGRE_DEBUG_MODE LogManager::getSingleton().logMessage("GLES2Texture::create - Mip: " + StringConverter::toString(mip) + " Name: " + mName + " ID: " + StringConverter::toString(mTextureID) + " Width: " + StringConverter::toString(width) + " Height: " + StringConverter::toString(height) + " Internal Format: " + StringConverter::toString(internalformat, 0, ' ', std::ios::hex) + " Format: " + StringConverter::toString(format, 0, ' ', std::ios::hex) + " Datatype: " + StringConverter::toString(datatype, 0, ' ', std::ios::hex) ); #endif // Normal formats switch(mTextureType) { case TEX_TYPE_1D: case TEX_TYPE_2D: #if OGRE_PLATFORM == OGRE_PLATFORM_NACL if(internalformat != format) { LogManager::getSingleton().logMessage("glTexImage2D: format != internalFormat, " "format=" + StringConverter::toString(format) + ", internalFormat=" + StringConverter::toString(internalformat)); } #endif OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_2D, mip, internalformat, width, height, 0, format, datatype, 0)); break; case TEX_TYPE_CUBE_MAP: for(int face = 0; face < 6; face++) { OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat, width, height, 0, format, datatype, 0)); } break; default: break; }; if (width > 1) { width = Bitwise::firstPO2From(width / 2); } if (height > 1) { height = Bitwise::firstPO2From(height / 2); } } #endif } }
bool Texture3D::SetData(unsigned level, int x, int y, int z, int width, int height, int depth, const void* data) { if (!object_ || !graphics_) { LOGERROR("No texture created, can not set data"); return false; } if (!data) { LOGERROR("Null source for setting data"); return false; } if (level >= levels_) { LOGERROR("Illegal mip level for setting data"); return false; } if (graphics_->IsDeviceLost()) { LOGWARNING("Texture data assignment while device is lost"); dataPending_ = true; return true; } if (IsCompressed()) { x &= ~3; y &= ~3; } int levelWidth = GetLevelWidth(level); int levelHeight = GetLevelHeight(level); int levelDepth = GetLevelDepth(level); if (x < 0 || x + width > levelWidth || y < 0 || y + height > levelHeight || z < 0 || z + depth > levelDepth || width <= 0 || height <= 0 || depth <= 0) { LOGERROR("Illegal dimensions for setting data"); return false; } graphics_->SetTextureForUpdate(this); bool wholeLevel = x == 0 && y == 0 && z == 0 && width == levelWidth && height == levelHeight && depth == levelDepth; unsigned format = GetSRGB() ? GetSRGBFormat(format_) : format_; #ifndef GL_ES_VERSION_2_0 if (!IsCompressed()) { if (wholeLevel) glTexImage3D(target_, level, format, width, height, depth, 0, GetExternalFormat(format_), GetDataType(format_), data); else glTexSubImage3D(target_, level, x, y, z, width, height, depth, GetExternalFormat(format_), GetDataType(format_), data); } else { if (wholeLevel) glCompressedTexImage3D(target_, level, format, width, height, depth, 0, GetDataSize(width, height, depth), data); else glCompressedTexSubImage3D(target_, level, x, y, z, width, height, depth, format, GetDataSize(width, height, depth), data); } #endif graphics_->SetTexture(0, 0); return true; }
/* * @~English * @brief Load a GL texture object from a ktxStream. * * This function will unpack compressed GL_ETC1_RGB8_OES and GL_ETC2_* format * textures in software when the format is not supported by the GL context, * provided the library has been compiled with SUPPORT_SOFTWARE_ETC_UNPACK * defined as 1. * * It will also convert textures with legacy formats to their modern equivalents * when the format is not supported by the GL context, provided that the library * has been compiled with SUPPORT_LEGACY_FORMAT_CONVERSION defined as 1. * * @param [in] stream pointer to the ktxStream from which to load. * @param [in,out] pTexture name of the GL texture to load. If NULL or if * <tt>*pTexture == 0</tt> the function will generate * a texture name. The function binds either the * generated name or the name given in @p *pTexture * to the texture target returned in @p *pTarget, * before loading the texture data. If @p pTexture * is not NULL and a name was generated, the generated * name will be returned in *pTexture. * @param [out] pTarget @p *pTarget is set to the texture target used. The * target is chosen based on the file contents. * @param [out] pDimensions If @p pDimensions is not NULL, the width, height and * depth of the texture's base level are returned in the * fields of the KTX_dimensions structure to which it points. * @param [out] pIsMipmapped * If @p pIsMipmapped is not NULL, @p *pIsMipmapped is set * to GL_TRUE if the KTX texture is mipmapped, GL_FALSE * otherwise. * @param [out] pGlerror @p *pGlerror is set to the value returned by * glGetError when this function returns the error * KTX_GL_ERROR. glerror can be NULL. * @param [in,out] pKvdLen If not NULL, @p *pKvdLen is set to the number of bytes * of key-value data pointed at by @p *ppKvd. Must not be * NULL, if @p ppKvd is not NULL. * @param [in,out] ppKvd If not NULL, @p *ppKvd is set to the point to a block of * memory containing key-value data read from the file. * The application is responsible for freeing the memory. * * * @return KTX_SUCCESS on success, other KTX_* enum values on error. * * @exception KTX_INVALID_VALUE @p target is @c NULL or the size of a mip * level is greater than the size of the * preceding level. * @exception KTX_INVALID_OPERATION @p ppKvd is not NULL but pKvdLen is NULL. * @exception KTX_UNEXPECTED_END_OF_FILE the file does not contain the * expected amount of data. * @exception KTX_OUT_OF_MEMORY Sufficient memory could not be allocated to store * the requested key-value data. * @exception KTX_GL_ERROR A GL error was raised by glBindTexture, * glGenTextures or gl*TexImage*. The GL error * will be returned in @p *glerror, if glerror * is not @c NULL. */ static KTX_error_code ktxLoadTextureS(struct ktxStream* stream, GLuint* pTexture, GLenum* pTarget, KTX_dimensions* pDimensions, GLboolean* pIsMipmapped, GLenum* pGlerror, unsigned int* pKvdLen, unsigned char** ppKvd) { GLint previousUnpackAlignment; KTX_header header; KTX_texinfo texinfo; void* data = NULL; khronos_uint32_t dataSize = 0; GLuint texname; int texnameUser; khronos_uint32_t faceLodSize; khronos_uint32_t faceLodSizeRounded; khronos_uint32_t level; khronos_uint32_t face; GLenum glFormat, glInternalFormat; KTX_error_code errorCode = KTX_SUCCESS; GLenum errorTmp; if (pGlerror) *pGlerror = GL_NO_ERROR; if (ppKvd) { *ppKvd = NULL; } if (!stream || !stream->read || !stream->skip) { return KTX_INVALID_VALUE; } if (!pTarget) { return KTX_INVALID_VALUE; } if (!stream->read(&header, KTX_HEADER_SIZE, stream->src)) { return KTX_UNEXPECTED_END_OF_FILE; } errorCode = _ktxCheckHeader(&header, &texinfo); if (errorCode != KTX_SUCCESS) { return errorCode; } if (ppKvd) { if (pKvdLen == NULL) return KTX_INVALID_OPERATION; *pKvdLen = header.bytesOfKeyValueData; if (*pKvdLen) { *ppKvd = (unsigned char*)malloc(*pKvdLen); if (*ppKvd == NULL) return KTX_OUT_OF_MEMORY; if (!stream->read(*ppKvd, *pKvdLen, stream->src)) { free(*ppKvd); *ppKvd = NULL; return KTX_UNEXPECTED_END_OF_FILE; } } } else { /* skip key/value metadata */ if (!stream->skip((long)header.bytesOfKeyValueData, stream->src)) { return KTX_UNEXPECTED_END_OF_FILE; } } if (contextProfile == 0) discoverContextCapabilities(); /* KTX files require an unpack alignment of 4 */ glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousUnpackAlignment); if (previousUnpackAlignment != KTX_GL_UNPACK_ALIGNMENT) { glPixelStorei(GL_UNPACK_ALIGNMENT, KTX_GL_UNPACK_ALIGNMENT); } texnameUser = pTexture && *pTexture; if (texnameUser) { texname = *pTexture; } else { glGenTextures(1, &texname); } glBindTexture(texinfo.glTarget, texname); // Prefer glGenerateMipmaps over GL_GENERATE_MIPMAP if (texinfo.generateMipmaps && (glGenerateMipmap == NULL)) { glTexParameteri(texinfo.glTarget, GL_GENERATE_MIPMAP, GL_TRUE); } if (texinfo.glTarget == GL_TEXTURE_CUBE_MAP) { texinfo.glTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; } glInternalFormat = header.glInternalFormat; glFormat = header.glFormat; if (!texinfo.compressed) { #if SUPPORT_LEGACY_FORMAT_CONVERSION // If sized legacy formats are supported there is no need to convert. // If only unsized formats are supported, there is no point in converting // as the modern formats aren't supported either. if (sizedFormats == _NON_LEGACY_FORMATS && supportsSwizzle) { convertFormat(texinfo.glTarget, &glFormat, &glInternalFormat); errorTmp = glGetError(); } else if (sizedFormats == _NO_SIZED_FORMATS) glInternalFormat = header.glBaseInternalFormat; #else // When no sized formats are supported, or legacy sized formats are not // supported, must change internal format. if (sizedFormats == _NO_SIZED_FORMATS || (!(sizedFormats & _LEGACY_FORMATS) && (header.glBaseInternalFormat == GL_ALPHA || header.glBaseInternalFormat == GL_LUMINANCE || header.glBaseInternalFormat == GL_LUMINANCE_ALPHA || header.glBaseInternalFormat == GL_INTENSITY))) { glInternalFormat = header.glBaseInternalFormat; } #endif } for (level = 0; level < header.numberOfMipmapLevels; ++level) { GLsizei pixelWidth = MAX(1, header.pixelWidth >> level); GLsizei pixelHeight = MAX(1, header.pixelHeight >> level); GLsizei pixelDepth = MAX(1, header.pixelDepth >> level); if (!stream->read(&faceLodSize, sizeof(khronos_uint32_t), stream->src)) { errorCode = KTX_UNEXPECTED_END_OF_FILE; goto cleanup; } if (header.endianness == KTX_ENDIAN_REF_REV) { _ktxSwapEndian32(&faceLodSize, 1); } faceLodSizeRounded = (faceLodSize + 3) & ~(khronos_uint32_t)3; if (!data) { /* allocate memory sufficient for the first level */ data = malloc(faceLodSizeRounded); if (!data) { errorCode = KTX_OUT_OF_MEMORY; goto cleanup; } dataSize = faceLodSizeRounded; } else if (dataSize < faceLodSizeRounded) { /* subsequent levels cannot be larger than the first level */ errorCode = KTX_INVALID_VALUE; goto cleanup; } for (face = 0; face < header.numberOfFaces; ++face) { if (!stream->read(data, faceLodSizeRounded, stream->src)) { errorCode = KTX_UNEXPECTED_END_OF_FILE; goto cleanup; } /* Perform endianness conversion on texture data */ if (header.endianness == KTX_ENDIAN_REF_REV && header.glTypeSize == 2) { _ktxSwapEndian16((khronos_uint16_t*)data, faceLodSize / 2); } else if (header.endianness == KTX_ENDIAN_REF_REV && header.glTypeSize == 4) { _ktxSwapEndian32((khronos_uint32_t*)data, faceLodSize / 4); } if (texinfo.textureDimensions == 1) { if (texinfo.compressed) { glCompressedTexImage1D(texinfo.glTarget + face, level, glInternalFormat, pixelWidth, 0, faceLodSize, data); } else { glTexImage1D(texinfo.glTarget + face, level, glInternalFormat, pixelWidth, 0, glFormat, header.glType, data); } } else if (texinfo.textureDimensions == 2) { if (header.numberOfArrayElements) { pixelHeight = header.numberOfArrayElements; } if (texinfo.compressed) { // It is simpler to just attempt to load the format, rather than divine which // formats are supported by the implementation. In the event of an error, // software unpacking can be attempted. glCompressedTexImage2D(texinfo.glTarget + face, level, glInternalFormat, pixelWidth, pixelHeight, 0, faceLodSize, data); } else { glTexImage2D(texinfo.glTarget + face, level, glInternalFormat, pixelWidth, pixelHeight, 0, glFormat, header.glType, data); } } else if (texinfo.textureDimensions == 3) { if (header.numberOfArrayElements) { pixelDepth = header.numberOfArrayElements; } if (texinfo.compressed) { glCompressedTexImage3D(texinfo.glTarget + face, level, glInternalFormat, pixelWidth, pixelHeight, pixelDepth, 0, faceLodSize, data); } else { glTexImage3D(texinfo.glTarget + face, level, glInternalFormat, pixelWidth, pixelHeight, pixelDepth, 0, glFormat, header.glType, data); } } errorTmp = glGetError(); #if SUPPORT_SOFTWARE_ETC_UNPACK // Renderion is returning INVALID_VALUE. Oops!! if ((errorTmp == GL_INVALID_ENUM || errorTmp == GL_INVALID_VALUE) && texinfo.compressed && texinfo.textureDimensions == 2 && (glInternalFormat == GL_ETC1_RGB8_OES || (glInternalFormat >= GL_COMPRESSED_R11_EAC && glInternalFormat <= GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC))) { GLubyte* unpacked; GLenum format, internalFormat, type; errorCode = _ktxUnpackETC((GLubyte*)data, glInternalFormat, pixelWidth, pixelHeight, &unpacked, &format, &internalFormat, &type, R16Formats, supportsSRGB); if (errorCode != KTX_SUCCESS) { goto cleanup; } if (!sizedFormats & _NON_LEGACY_FORMATS) { if (internalFormat == GL_RGB8) internalFormat = GL_RGB; else if (internalFormat == GL_RGBA8) internalFormat = GL_RGBA; } glTexImage2D(texinfo.glTarget + face, level, internalFormat, pixelWidth, pixelHeight, 0, format, type, unpacked); free(unpacked); errorTmp = glGetError(); } #endif if (errorTmp != GL_NO_ERROR) { if (pGlerror) *pGlerror = errorTmp; errorCode = KTX_GL_ERROR; goto cleanup; } } } cleanup: free(data); /* restore previous GL state */ if (previousUnpackAlignment != KTX_GL_UNPACK_ALIGNMENT) { glPixelStorei(GL_UNPACK_ALIGNMENT, previousUnpackAlignment); } if (errorCode == KTX_SUCCESS) { if (texinfo.generateMipmaps && glGenerateMipmap) { glGenerateMipmap(texinfo.glTarget); } *pTarget = texinfo.glTarget; if (pTexture) { *pTexture = texname; } if (pDimensions) { pDimensions->width = header.pixelWidth; pDimensions->height = header.pixelHeight; pDimensions->depth = header.pixelDepth; } if (pIsMipmapped) { if (texinfo.generateMipmaps || header.numberOfMipmapLevels > 1) *pIsMipmapped = GL_TRUE; else *pIsMipmapped = GL_FALSE; } } else { if (ppKvd && *ppKvd) { free(*ppKvd); *ppKvd = NULL; } if (!texnameUser) { glDeleteTextures(1, &texname); } } return errorCode; }
void OGLESTexture2D::CreateHWResource(ElementInitData const * init_data) { uint32_t texel_size = NumFormatBytes(format_); GLint glinternalFormat; GLenum glformat; GLenum gltype; OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_); glBindTexture(target_type_, texture_); for (uint32_t array_index = 0; array_index < array_size_; ++ array_index) { for (uint32_t level = 0; level < num_mip_maps_; ++ level) { uint32_t const w = this->Width(level); uint32_t const h = this->Height(level); if (IsCompressedFormat(format_)) { uint32_t const block_size = NumFormatBytes(format_) * 4; GLsizei const image_size = ((w + 3) / 4) * ((h + 3) / 4) * block_size; void* ptr; if (nullptr == init_data) { tex_data_[array_index * num_mip_maps_ + level].resize(image_size, 0); ptr = nullptr; } else { tex_data_[array_index * num_mip_maps_ + level].resize(image_size); std::memcpy(&tex_data_[array_index * num_mip_maps_ + level][0], init_data[array_index * num_mip_maps_ + level].data, image_size); ptr = &tex_data_[array_index * num_mip_maps_ + level][0]; } if (array_size_ > 1) { if (0 == array_index) { glCompressedTexImage3D(target_type_, level, glinternalFormat, w, h, array_size_, 0, image_size * array_size_, nullptr); } if (init_data != nullptr) { glCompressedTexSubImage3D(target_type_, level, 0, 0, array_index, w, h, 1, glformat, image_size, init_data[array_index * num_mip_maps_ + level].data); } } else { glCompressedTexImage2D(target_type_, level, glinternalFormat, w, h, 0, image_size, ptr); } } else { GLsizei const image_size = w * h * texel_size; void* ptr; if (nullptr == init_data) { tex_data_[array_index * num_mip_maps_ + level].resize(image_size, 0); ptr = nullptr; } else { tex_data_[array_index * num_mip_maps_ + level].resize(image_size); std::memcpy(&tex_data_[array_index * num_mip_maps_ + level][0], init_data[array_index * num_mip_maps_ + level].data, image_size); ptr = &tex_data_[array_index * num_mip_maps_ + level][0]; } if (array_size_ > 1) { if (0 == array_index) { glTexImage3D(target_type_, level, glinternalFormat, w, h, array_size_, 0, glformat, gltype, nullptr); } if (init_data != nullptr) { glTexSubImage3D(target_type_, level, 0, 0, array_index, w, h, 1, glformat, gltype, init_data[array_index * num_mip_maps_ + level].data); } } else { glTexImage2D(target_type_, level, glinternalFormat, w, h, 0, glformat, gltype, ptr); } } } } hw_res_ready_ = true; }
void RenderDevice::uploadTextureData( uint32 texObj, int slice, int mipLevel, const void *pixels ) { const RDITexture &tex = _textures.getRef( texObj ); TextureFormats::List format = tex.format; glActiveTexture( GL_TEXTURE0 ); glBindTexture( tex.type, tex.glObj ); #ifdef PLATFORM_ES2 int inputFormat = GL_RGBA, inputType = GL_UNSIGNED_BYTE; #else int inputFormat = GL_BGRA, inputType = GL_UNSIGNED_BYTE; #endif bool compressed = (format == TextureFormats::DXT1) || (format == TextureFormats::DXT3) || (format == TextureFormats::DXT5) || (format == TextureFormats::PVRTC2) || (format == TextureFormats::PVRTCA2) || (format == TextureFormats::PVRTC4) || (format == TextureFormats::PVRTCA4); switch( format ) { case TextureFormats::RGBA16F: inputFormat = GL_RGBA; #ifdef PLATFORM_ES2 // GL_HALF_FLOAT_OES seems not to work on 3GS, 4G and iPad1 // http://stackoverflow.com/questions/3850569/render-to-floating-point-texture-under-ios inputType = glExt::OES_texture_half_float ? GL_HALF_FLOAT_OES : GL_RGBA ; #else inputType = GL_FLOAT; #endif break; case TextureFormats::RGBA32F: inputFormat = GL_RGBA; inputType = GL_FLOAT; break; case TextureFormats::DEPTH: inputFormat = GL_DEPTH_COMPONENT; #ifdef PLATFORM_ES2 inputType = GL_UNSIGNED_SHORT; #else inputType = GL_FLOAT; #endif default: break; }; // Calculate size of next mipmap using "floor" convention int width = std::max( tex.width >> mipLevel, 1 ), height = std::max( tex.height >> mipLevel, 1 ); if ( (tex.type == TextureTypes::Tex2D && (width>_maxTextureSize || height>_maxTextureSize)) || (tex.type == TextureTypes::TexCube && (width>_maxCubeTextureSize || height>_maxCubeTextureSize))) goto UPLOADE_TEXUTURE_EXIT;//return; if( tex.type == TextureTypes::Tex2D || tex.type == TextureTypes::TexCube ) { int target = (tex.type == TextureTypes::Tex2D) ? GL_TEXTURE_2D : (GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice); if( compressed ) glCompressedTexImage2D( target, mipLevel, tex.glFmt, width, height, 0, calcTextureSize( format, width, height, 1 ), pixels ); else glTexImage2D( target, mipLevel, tex.glFmt, width, height, 0, inputFormat, inputType, pixels ); } else if( tex.type == TextureTypes::Tex3D ) { #if !defined(PLATFORM_ES2) int depth = std::max( tex.depth >> mipLevel, 1 ); if( compressed ) glCompressedTexImage3D( GL_TEXTURE_3D, mipLevel, tex.glFmt, width, height, depth, 0, calcTextureSize( format, width, height, depth ), pixels ); else glTexImage3D( GL_TEXTURE_3D, mipLevel, tex.glFmt, width, height, depth, 0, inputFormat, inputType, pixels ); #endif }
void OGLESTexture3D::CreateHWResource(ElementInitData const * init_data) { uint32_t texel_size = NumFormatBytes(format_); GLint glinternalFormat; GLenum glformat; GLenum gltype; OGLESMapping::MappingFormat(glinternalFormat, glformat, gltype, format_); glBindTexture(target_type_, texture_); for (uint32_t level = 0; level < num_mip_maps_; ++ level) { uint32_t const w = this->Width(level); uint32_t const h = this->Height(level); uint32_t const d = this->Depth(level); if (IsCompressedFormat(format_)) { uint32_t const block_size = NumFormatBytes(format_) * 4; GLsizei const image_size = ((w + 3) / 4) * ((h + 3) / 4) * d * block_size; void* ptr; if (nullptr == init_data) { tex_data_[level].resize(image_size, 0); ptr = nullptr; } else { tex_data_[level].resize(image_size); std::memcpy(&tex_data_[level][0], init_data[level].data, image_size); ptr = &tex_data_[level][0]; } if (glloader_GLES_VERSION_3_0()) { glCompressedTexImage3D(target_type_, level, glinternalFormat, w, h, d, 0, image_size, ptr); } else { glCompressedTexImage3DOES(target_type_, level, glinternalFormat, w, h, d, 0, image_size, ptr); } } else { GLsizei const image_size = w * h * d * texel_size; void* ptr; if (nullptr == init_data) { tex_data_[level].resize(image_size, 0); ptr = nullptr; } else { tex_data_[level].resize(image_size); std::memcpy(&tex_data_[level][0], init_data[level].data, image_size); ptr = &tex_data_[level][0]; } if (glloader_GLES_VERSION_3_0()) { glTexImage3D(target_type_, level, glinternalFormat, w, h, d, 0, glformat, gltype, ptr); } else { glTexImage3DOES(target_type_, level, glinternalFormat, w, h, d, 0, glformat, gltype, ptr); } } } hw_res_ready_ = true; }
// Compressed texture void gl4es_glCompressedMultiTexImage3D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) { text(glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data)); }
void GLTextureBuffer::upload(const PixelData &data, const PixelVolume &dest) { if((mUsage & TU_RENDERTARGET) != 0) BS_EXCEPT(NotImplementedException, "Writing to render texture from CPU not supported."); if ((mUsage & TU_DEPTHSTENCIL) != 0) BS_EXCEPT(NotImplementedException, "Writing to depth stencil texture from CPU not supported."); glBindTexture( mTarget, mTextureID ); if(PixelUtil::isCompressed(data.getFormat())) { if(data.getFormat() != mFormat || !data.isConsecutive()) BS_EXCEPT(InvalidParametersException, "Compressed images must be consecutive, in the source format"); GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat); switch(mTarget) { case GL_TEXTURE_1D: if (dest.left == 0) { glCompressedTexImage1D(GL_TEXTURE_1D, mLevel, format, dest.getWidth(), 0, data.getConsecutiveSize(), data.getData()); } else { glCompressedTexSubImage1D(GL_TEXTURE_1D, mLevel, dest.left, dest.getWidth(), format, data.getConsecutiveSize(), data.getData()); } break; case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: if (dest.left == 0 && dest.top == 0) { glCompressedTexImage2D(mFaceTarget, mLevel, format, dest.getWidth(), dest.getHeight(), 0, data.getConsecutiveSize(), data.getData()); } else { glCompressedTexSubImage2D(mFaceTarget, mLevel, dest.left, dest.top, dest.getWidth(), dest.getHeight(), format, data.getConsecutiveSize(), data.getData()); } break; case GL_TEXTURE_3D: if (dest.left == 0 && dest.top == 0 && dest.front == 0) { glCompressedTexImage3D(GL_TEXTURE_3D, mLevel, format, dest.getWidth(), dest.getHeight(), dest.getDepth(), 0, data.getConsecutiveSize(), data.getData()); } else { glCompressedTexSubImage3D(GL_TEXTURE_3D, mLevel, dest.left, dest.top, dest.front, dest.getWidth(), dest.getHeight(), dest.getDepth(), format, data.getConsecutiveSize(), data.getData()); } break; } } else { if(data.getWidth() != data.getRowPitch()) glPixelStorei(GL_UNPACK_ROW_LENGTH, data.getRowPitch()); if(data.getHeight()*data.getWidth() != data.getSlicePitch()) glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.getSlicePitch()/data.getWidth())); if(data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0) glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront()); if((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); switch(mTarget) { case GL_TEXTURE_1D: glTexSubImage1D(GL_TEXTURE_1D, mLevel, dest.left, dest.getWidth(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); break; case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: glTexSubImage2D(mFaceTarget, mLevel, dest.left, dest.top, dest.getWidth(), dest.getHeight(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); break; case GL_TEXTURE_3D: glTexSubImage3D( GL_TEXTURE_3D, mLevel, dest.left, dest.top, dest.front, dest.getWidth(), dest.getHeight(), dest.getDepth(), GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData()); break; } } // Restore defaults glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); BS_INC_RENDER_STAT_CAT(ResWrite, RenderStatObject_Texture); }
// Creation / loading methods void GL3PlusTexture::createInternalResourcesImpl(void) { // set HardwareBuffer::Usage for TU_RENDERTARGET if nothing else specified if((mUsage & TU_RENDERTARGET) && (mUsage & ~TU_RENDERTARGET) == 0) mUsage |= HardwareBuffer::HBU_DYNAMIC; // Adjust format if required. mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage); // Check requested number of mipmaps. uint32 maxMips = getMaxMipmaps(); if (PixelUtil::isCompressed(mFormat) && (mNumMipmaps == 0)) mNumRequestedMipmaps = 0; mNumMipmaps = mNumRequestedMipmaps; if (mNumMipmaps > maxMips) mNumMipmaps = maxMips; // Create a texture object and identify its GL type. OGRE_CHECK_GL_ERROR(glGenTextures(1, &mTextureID)); GLenum texTarget = getGL3PlusTextureTarget(); // Calculate size for all mip levels of the texture. uint32 width, height, depth; if ((mWidth * PixelUtil::getNumElemBytes(mFormat)) & 3) { // Standard alignment of 4 is not right for some formats. OGRE_CHECK_GL_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); } // Bind texture object to its type, making it the active texture object // for that type. mRenderSystem->_getStateCacheManager()->bindGLTexture( texTarget, mTextureID ); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_BASE_LEVEL, 0); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MAX_LEVEL, mNumMipmaps); // Set some misc default parameters, these can of course be changed later. mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set up texture swizzling. mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_GREEN); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_BLUE); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); if (PixelUtil::isLuminance(mFormat) && (mRenderSystem->hasMinGLVersion(3, 3) || mRenderSystem->checkExtension("GL_ARB_texture_swizzle"))) { if (PixelUtil::getComponentCount(mFormat) == 2) { mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_GREEN); } else { mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED); mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ONE); } } GLenum format = GL3PlusPixelUtil::getGLInternalFormat(mFormat, mHwGamma); GLenum datatype = GL3PlusPixelUtil::getGLOriginDataType(mFormat); width = mWidth; height = mHeight; depth = mDepth; // Allocate texture storage so that glTexSubImageXD can be // used to upload the texture. if (PixelUtil::isCompressed(mFormat)) { // Compressed formats GLsizei size; for (uint32 mip = 0; mip <= mNumMipmaps; mip++) { size = static_cast<GLsizei>(PixelUtil::getMemorySize(width, height, depth, mFormat)); // std::stringstream str; // str << "GL3PlusTexture::create - " << StringConverter::toString(mTextureID) // << " bytes: " << StringConverter::toString(PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat)) // << " Mip: " + StringConverter::toString(mip) // << " Width: " << StringConverter::toString(width) // << " Height: " << StringConverter::toString(height) // << " Format " << PixelUtil::getFormatName(mFormat) // << " Internal Format: 0x" << std::hex << format // << " Origin Format: 0x" << std::hex << GL3PlusPixelUtil::getGLOriginFormat(mFormat) // << " Data type: 0x" << std::hex << datatype; // LogManager::getSingleton().logMessage(LML_NORMAL, str.str()); switch(mTextureType) { case TEX_TYPE_1D: OGRE_CHECK_GL_ERROR(glCompressedTexImage1D(GL_TEXTURE_1D, mip, format, width, 0, size, NULL)); break; case TEX_TYPE_2D: OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_2D, mip, format, width, height, 0, size, NULL)); break; case TEX_TYPE_2D_RECT: OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_RECTANGLE, mip, format, width, height, 0, size, NULL)); break; case TEX_TYPE_2D_ARRAY: case TEX_TYPE_3D: OGRE_CHECK_GL_ERROR(glCompressedTexImage3D(texTarget, mip, format, width, height, depth, 0, size, NULL)); break; case TEX_TYPE_CUBE_MAP: for(int face = 0; face < 6; face++) { OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format, width, height, 0, size, NULL)); } break; default: break; }; if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY) { depth = depth / 2; } } } else { if (mRenderSystem->hasMinGLVersion(4, 2) || mRenderSystem->checkExtension("GL_ARB_texture_storage")) { switch(mTextureType) { case TEX_TYPE_1D: OGRE_CHECK_GL_ERROR(glTexStorage1D(GL_TEXTURE_1D, GLsizei(mNumMipmaps+1), format, GLsizei(width))); break; case TEX_TYPE_2D: case TEX_TYPE_2D_RECT: OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_2D, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height))); break; case TEX_TYPE_CUBE_MAP: OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_CUBE_MAP, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height))); break; case TEX_TYPE_2D_ARRAY: OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_2D_ARRAY, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height), GLsizei(depth))); break; case TEX_TYPE_3D: OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_3D, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height), GLsizei(depth))); break; } } else { GLenum originFormat = GL3PlusPixelUtil::getGLOriginFormat(mFormat); // Run through this process to pregenerate mipmap pyramid for(uint32 mip = 0; mip <= mNumMipmaps; mip++) { // std::stringstream str; // str << "GL3PlusTexture::create - " << StringConverter::toString(mTextureID) // << " bytes: " << StringConverter::toString(PixelUtil::getMemorySize(width, height, depth, mFormat)) // << " Mip: " + StringConverter::toString(mip) // << " Width: " << StringConverter::toString(width) // << " Height: " << StringConverter::toString(height) // << " Format " << PixelUtil::getFormatName(mFormat) // << " Internal Format: 0x" << std::hex << format // << " Origin Format: 0x" << std::hex << GL3PlusPixelUtil::getGLOriginFormat(mFormat) // << " Data type: 0x" << std::hex << datatype; // LogManager::getSingleton().logMessage(LML_NORMAL, str.str()); // Normal formats switch(mTextureType) { case TEX_TYPE_1D: OGRE_CHECK_GL_ERROR(glTexImage1D(GL_TEXTURE_1D, mip, format, width, 0, originFormat, datatype, NULL)); break; case TEX_TYPE_2D: OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_2D, mip, format, width, height, 0, originFormat, datatype, NULL)); break; case TEX_TYPE_2D_RECT: OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_RECTANGLE, mip, format, width, height, 0, originFormat, datatype, NULL)); break; case TEX_TYPE_3D: case TEX_TYPE_2D_ARRAY: OGRE_CHECK_GL_ERROR(glTexImage3D(texTarget, mip, format, width, height, depth, 0, originFormat, datatype, NULL)); break; case TEX_TYPE_CUBE_MAP: for(int face = 0; face < 6; face++) { OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format, width, height, 0, originFormat, datatype, NULL)); } break; default: break; }; if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY) { depth = depth / 2; } } } } // Reset unpack alignment to defaults OGRE_CHECK_GL_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 4)); _createSurfaceList(); // Generate mipmaps after all texture levels have been loaded // This is required for compressed formats such as DXT if (PixelUtil::isCompressed(mFormat) && mUsage & TU_AUTOMIPMAP) { OGRE_CHECK_GL_ERROR(glGenerateMipmap(getGL3PlusTextureTarget())); } // Get final internal format. mFormat = getBuffer(0,0)->getFormat(); }
// Creation / loading methods void GL3PlusTexture::createInternalResourcesImpl(void) { // Adjust format if required mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage); // Check requested number of mipmaps size_t maxMips = GL3PlusPixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat); if(PixelUtil::isCompressed(mFormat) && (mNumMipmaps == 0)) mNumRequestedMipmaps = 0; mNumMipmaps = mNumRequestedMipmaps; if (mNumMipmaps > maxMips) mNumMipmaps = maxMips; // Generate texture name OGRE_CHECK_GL_ERROR(glGenTextures(1, &mTextureID)); GLenum texTarget = getGL3PlusTextureTarget(); // Set texture type OGRE_CHECK_GL_ERROR(glBindTexture(texTarget, mTextureID)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_BASE_LEVEL, 0)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_MAX_LEVEL, (mMipmapsHardwareGenerated && (mUsage & TU_AUTOMIPMAP)) ? maxMips : mNumMipmaps )); // Set some misc default parameters, these can of course be changed later OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // Set up texture swizzling if(mGLSupport.checkExtension("GL_ARB_texture_swizzle") || gl3wIsSupported(3, 3)) { OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_GREEN)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_BLUE)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ALPHA)); if(mFormat == PF_BYTE_LA) { OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_GREEN)); } else if(mFormat == PF_L8 || mFormat == PF_L16) { OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED)); OGRE_CHECK_GL_ERROR(glTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_RED)); } } // If we can do automip generation and the user desires this, do so mMipmapsHardwareGenerated = Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP); // Allocate internal buffer so that glTexSubImageXD can be used // Internal format GLenum format = GL3PlusPixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma); GLenum datatype = GL3PlusPixelUtil::getGLOriginDataType(mFormat); size_t width = mWidth; size_t height = mHeight; size_t depth = mDepth; if (PixelUtil::isCompressed(mFormat)) { // Compressed formats size_t size = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat); // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not // accept a 0 pointer like normal glTexImageXD // Run through this process for every mipmap to pregenerate mipmap pyramid uint8* tmpdata = new uint8[size]; memset(tmpdata, 0, size); for (size_t mip = 0; mip <= mNumMipmaps; mip++) { size = PixelUtil::getMemorySize(width, height, depth, mFormat); switch(mTextureType) { case TEX_TYPE_1D: OGRE_CHECK_GL_ERROR(glCompressedTexImage1D(GL_TEXTURE_1D, mip, format, width, 0, size, tmpdata)); break; case TEX_TYPE_2D: OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_2D, mip, format, width, height, 0, size, tmpdata)); break; case TEX_TYPE_2D_RECT: OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_RECTANGLE, mip, format, width, height, 0, size, tmpdata)); break; case TEX_TYPE_2D_ARRAY: case TEX_TYPE_3D: OGRE_CHECK_GL_ERROR(glCompressedTexImage3D(texTarget, mip, format, width, height, depth, 0, size, tmpdata)); break; case TEX_TYPE_CUBE_MAP: for(int face = 0; face < 6; face++) { OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format, width, height, 0, size, tmpdata)); } break; default: break; }; // LogManager::getSingleton().logMessage("GL3PlusTexture::create - " + StringConverter::toString(mTextureID) + // " Mip: " + StringConverter::toString(mip) + // " Width: " + StringConverter::toString(width) + // " Height: " + StringConverter::toString(height) + // " Internal Format: " + StringConverter::toString(format) // ); if(width > 1) { width = width / 2; } if(height > 1) { height = height / 2; } if(depth > 1) { depth = depth / 2; } } delete [] tmpdata; } else { if((mGLSupport.checkExtension("GL_ARB_texture_storage") || gl3wIsSupported(4, 2)) && mTextureType == TEX_TYPE_2D) { OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_2D, GLint(mNumMipmaps+1), format, GLsizei(width), GLsizei(height))); } else { // Run through this process to pregenerate mipmap pyramid for(size_t mip = 0; mip <= mNumMipmaps; mip++) { // Normal formats switch(mTextureType) { case TEX_TYPE_1D: OGRE_CHECK_GL_ERROR(glTexImage1D(GL_TEXTURE_1D, mip, format, width, 0, GL_RGBA, datatype, 0)); break; case TEX_TYPE_2D: OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_2D, mip, format, width, height, 0, GL3PlusPixelUtil::getGLOriginFormat(mFormat), datatype, 0)); break; case TEX_TYPE_2D_RECT: OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_RECTANGLE, mip, format, width, height, 0, GL3PlusPixelUtil::getGLOriginFormat(mFormat), datatype, 0)); break; case TEX_TYPE_3D: case TEX_TYPE_2D_ARRAY: OGRE_CHECK_GL_ERROR(glTexImage3D(texTarget, mip, format, width, height, depth, 0, GL_RGBA, datatype, 0)); break; case TEX_TYPE_CUBE_MAP: for(int face = 0; face < 6; face++) { OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format, width, height, 0, GL3PlusPixelUtil::getGLOriginFormat(mFormat), datatype, 0)); } break; default: break; }; if (width > 1) { width = width / 2; } if (height > 1) { height = height / 2; } if (depth > 1) { depth = depth / 2; } } } } _createSurfaceList(); // Get final internal format mFormat = getBuffer(0,0)->getFormat(); }
void Texture::update() { io::Image::TextureType textureType = image->getTextureType(); target = targetTable[textureType]; unsigned format = formatTable[image->getChannelFormat()]; unsigned type = typeTable[image->getDataType()]; unsigned mipmaps = image->getMipmapCount(); unsigned internalFormat = internalFormatTable[image->getDataType()][image->getChannelFormat()]; if (srgbColorspace) { unsigned internalFormatSRGB = internalFormatTableSRGB[image->getDataType()][image->getChannelFormat()]; if (internalFormatSRGB) { #if defined(SOFA_HAVE_GLEW) && defined(GLEW_EXT_texture_sRGB) && defined(GLEW_ARB_framebuffer_sRGB) if (GLEW_EXT_texture_sRGB && GLEW_ARB_framebuffer_sRGB) internalFormat = internalFormatSRGB; else #endif { msg_error("Texture") << "SRGB colorspace is unsupported, GLEW_EXT_texture_srgb or GLEW_ARB_framebuffer_sRGB is missing." ; } } else { msg_error("Texture") << "SRGB colorspace isn't supported with the given texture format." ; } } glBindTexture(target, id); glPixelStorei(GL_PACK_ALIGNMENT,1); switch (textureType) { case io::Image::TEXTURE_2D: #if defined(SOFA_HAVE_GLEW) && defined(GLEW_VERSION_1_3) if (image->getDataType() == io::Image::UCOMPRESSED) for (unsigned i = 0; i < mipmaps; i++) glCompressedTexImage2D(target, i, internalFormat, image->getWidth(i), image->getHeight(i), 0, image->getMipmapSize(i), image->getMipmapPixels(i)); else #endif for (unsigned i = 0; i < mipmaps; i++) glTexImage2D(target, i, internalFormat, image->getWidth(i), image->getHeight(i), 0, format, type, image->getMipmapPixels(i)); break; case io::Image::TEXTURE_3D: #if defined(SOFA_HAVE_GLEW) && defined(GLEW_VERSION_1_2) #if defined(SOFA_HAVE_GLEW) && defined(GLEW_VERSION_1_3) if (image->getDataType() == io::Image::UCOMPRESSED) for (unsigned i = 0; i < mipmaps; i++) glCompressedTexImage3D(target, i, internalFormat, image->getWidth(i), image->getHeight(i), image->getDepth(i), 0, image->getMipmapSize(i), image->getMipmapPixels(i)); else #endif for (unsigned i = 0; i < mipmaps; i++) glTexImage3D(target, i, internalFormat, image->getWidth(i), image->getHeight(i), image->getDepth(i), 0, format, type, image->getMipmapPixels(i)); #endif break; case io::Image::TEXTURE_CUBE: #if defined(SOFA_HAVE_GLEW) && defined(GLEW_VERSION_1_3) if (image->getDataType() == io::Image::UCOMPRESSED) for (unsigned j = 0; j < 6; j++) for (unsigned i = 0; i < mipmaps; i++) glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, internalFormat, image->getWidth(i), image->getHeight(i), 0, image->getMipmapSize(i) / 6, (image->getPixels())? image->getCubeMipmapPixels(j, i) : 0); else for (unsigned j = 0; j < 6; j++) for (unsigned i = 0; i < mipmaps; i++) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, internalFormat, image->getWidth(i), image->getHeight(i), 0, format, type, (image->getPixels())? image->getCubeMipmapPixels(j, i) : 0); #endif break; default:; } glPixelStorei(GL_PACK_ALIGNMENT, 4); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL13_nglCompressedTexImage3DBO(JNIEnv *env, jclass clazz, jint target, jint level, jint internalformat, jint width, jint height, jint depth, jint border, jint imageSize, jlong data_buffer_offset, jlong function_pointer) { const GLvoid *data_address = (const GLvoid *)(intptr_t)offsetToPointer(data_buffer_offset); glCompressedTexImage3DPROC glCompressedTexImage3D = (glCompressedTexImage3DPROC)((intptr_t)function_pointer); glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data_address); }
bool Texture :: load3D ( const char * fileName ) { TexImage * image = loadTexImage ( fileName ); if ( image == NULL ) return false; if ( image -> getImageType () != TexImage :: image3D ) { delete image; return false; } setParamsFromTexImage ( image, GL_TEXTURE_3D ); glGenTextures ( 1, &id ); glBindTexture ( target, id ); glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); // set 1-byte alignment glTexParameteri ( target, GL_TEXTURE_WRAP_S, GL_REPEAT ); // set default params for texture glTexParameteri ( target, GL_TEXTURE_WRAP_T, GL_REPEAT ); glTexParameteri ( target, GL_TEXTURE_WRAP_R, GL_REPEAT ); if ( !image -> isCompressed () ) // not compressed image { glTexImage3D ( target, 0, getFormat ().getInternalFormat (), width, height, depth, 0, getFormat ().getFormat (), image -> getGlType (), image -> imageData () ); if ( autoMipmaps ) glGenerateMipmap ( target ); } else { int mipmaps = image -> getNumLevels (); int w = width; int h = height; int d = depth; byte * ptr = image -> imageData ( 0, 0 ); // glTexParameteri ( target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1 ); for ( int i = 0; i < mipmaps; i++ ) { int size = image -> imageDataSize ( 0, i ); glCompressedTexImage3D ( target, i, getFormat ().getInternalFormat (), w, h, d, 0, size, ptr ); if ( ( w = w / 2 ) < 1 ) w = 1; if ( ( h = h / 2 ) < 1 ) h = 1; if ( ( d = d / 2 ) < 1 ) d = 1; ptr += size; } } if ( autoMipmaps ) { glTexParameteri ( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glTexParameteri ( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); } else { glTexParameteri ( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri ( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); } glBindTexture ( target, 0 ); delete image; return true; }