Beispiel #1
0
void ImageViewerPanel::updateTexture()
{
	makeCurrent();
	if (textures != nullptr)
	{
		switch (texType)
		{
		case DISPLAY_TYPE::BEAUTY:
			glTextureStorage2D(tex, 1, GL_RGBA32F, imgsize[0], imgsize[1]);
			glTextureSubImage2D(tex, 0, 0, 0, imgsize[0], imgsize[1], GL_RGBA, GL_FLOAT, textures);
			break;
		case DISPLAY_TYPE::P:
		case DISPLAY_TYPE::N:
		case DISPLAY_TYPE::DPDU:
		case DISPLAY_TYPE::DPDV:
			glTextureStorage2D(tex, 1, GL_RGB32F, imgsize[0], imgsize[1]);
			glTextureSubImage2D(tex, 0, 0, 0, imgsize[0], imgsize[1], GL_RGB, GL_FLOAT, textures);
			break;
		default:
			break;
		}
		
	}
	else
	{
		glTextureStorage2D(tex, 1, GL_RGBA32F, 0, 0);
		glTextureSubImage2D(tex, 0, 0, 0, 0, 0, GL_RGBA, GL_FLOAT, 0);
	}
	doneCurrent();
}
Beispiel #2
0
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
{
	ASSERT(m_type != GSTexture::DepthStencil && m_type != GSTexture::Offscreen);
	GL_PUSH("Upload Texture %d", m_texture_id);

	m_dirty = true;
	m_clean = false;

	glPixelStorei(GL_UNPACK_ALIGNMENT, m_int_alignment);

	char* src = (char*)data;
	uint32 row_byte = r.width() << m_int_shift;
	uint32 map_size = r.height() * row_byte;
	char* map = PboPool::Map(map_size);

#ifdef ENABLE_OGL_DEBUG_MEM_BW
	g_real_texture_upload_byte += map_size;
#endif

	// PERF: slow path of the texture upload. Dunno if we could do better maybe check if TC can keep row_byte == pitch
	// Note: row_byte != pitch
	for (int h = 0; h < r.height(); h++) {
		memcpy(map, src, row_byte);
		map += row_byte;
		src += pitch;
	}

	PboPool::Unmap();

	glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, (const void*)PboPool::Offset());

	// FIXME OGL4: investigate, only 1 unpack buffer always bound
	PboPool::UnbindPbo();

	PboPool::EndTransfer();

	GL_POP();
	return true;

	// For reference, standard upload without pbo (Used to crash on FGLRX)
#if 0
	// pitch is in byte wherease GL_UNPACK_ROW_LENGTH is in pixel
	glPixelStorei(GL_UNPACK_ALIGNMENT, m_int_alignment);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch >> m_int_shift);

	glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, data);

	// FIXME useful?
	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Restore default behavior

	return true;
#endif
}
void OceanMesh::GenBuffers()
{
	MeshActor::GenBuffers();

	glGenBuffers(1, &uvBuffer);

	glEnable(GL_TEXTURE_2D);

	// OCEAN DEPTH HEIGHTMAP
	glActiveTexture(GL_TEXTURE0);
	glGenTextures(1, &oceanDepthTexID);
	glBindTexture(GL_TEXTURE_2D, oceanDepthTexID);
	glTextureStorage2D(oceanDepthTexID, 1, GL_RGBA8, oceanDepth->x, oceanDepth->y);
	glTextureSubImage2D(oceanDepthTexID, 0, 0, 0, oceanDepth->x, oceanDepth->y, GL_RGBA, GL_UNSIGNED_BYTE, oceanDepth->data);

	// WATER FLOW MAP
	glActiveTexture(GL_TEXTURE1);
	glGenTextures(1, &flowMapTexID);
	glBindTexture(GL_TEXTURE_2D, flowMapTexID);
	glTextureStorage2D(flowMapTexID, 1, GL_RGBA8, flowMap->x, flowMap->y);
	glTextureSubImage2D(flowMapTexID, 0, 0, 0, flowMap->x, flowMap->y, GL_RGBA, GL_UNSIGNED_BYTE, flowMap->data);

	// OCEAN NORMAL MAP
	glActiveTexture(GL_TEXTURE2);
	glGenTextures(1, &oceanNormalMapID);
	glBindTexture(GL_TEXTURE_2D, oceanNormalMapID);
	glTextureStorage2D(oceanNormalMapID, 1, GL_RGBA8_SNORM, oceanNormalMap->x, oceanNormalMap->y);
	glTextureSubImage2D(oceanNormalMapID, 0, 0, 0, oceanNormalMap->x, oceanNormalMap->y, GL_RGBA, GL_UNSIGNED_BYTE, oceanNormalMap->data);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// OCEAN NORMAL MAP
	glActiveTexture(GL_TEXTURE3);
	glGenTextures(1, &oceanNormalMapAltID);
	glBindTexture(GL_TEXTURE_2D, oceanNormalMapAltID);
	glTextureStorage2D(oceanNormalMapAltID, 1, GL_RGBA8_SNORM, oceanNormalMapAlt->x, oceanNormalMapAlt->y);
	glTextureSubImage2D(oceanNormalMapAltID, 0, 0, 0, oceanNormalMapAlt->x, oceanNormalMapAlt->y, GL_RGBA, GL_UNSIGNED_BYTE, oceanNormalMapAlt->data);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	// PERLIN NOISE
	glActiveTexture(GL_TEXTURE4);
	glGenTextures(1, &perlinID);
	glBindTexture(GL_TEXTURE_2D, perlinID);
	glTextureStorage2D(perlinID, 1, GL_RGBA8, perlinNoise->x, perlinNoise->y);
	glTextureSubImage2D(perlinID, 0, 0, 0, perlinNoise->x, perlinNoise->y, GL_RGBA, GL_UNSIGNED_BYTE, perlinNoise->data);
}
		void init2DTexture(const graphics::Context::InitTextureParams & _params) override
		{

			if (_params.msaaLevel == 0) {
				if (m_handle != _params.handle) {
					m_handle = _params.handle;
					glTextureStorage2D(GLuint(_params.handle),
								   _params.mipMapLevels,
								   GLenum(_params.internalFormat),
								   _params.width,
								   _params.height);
				}

				if (_params.data != nullptr) {
					glTextureSubImage2D(GLuint(_params.handle),
						_params.mipMapLevel,
						0, 0,
						_params.width,
						_params.height,
						GLuint(_params.format),
						GLenum(_params.dataType),
						_params.data);
				}
			}
			else {
				glTexStorage2DMultisample(GLuint(_params.handle),
										  _params.msaaLevel,
										  GLenum(_params.internalFormat),
										  _params.width,
										  _params.height,
										  GL_FALSE);
			}
		}
		void update2DTexture(const graphics::Context::UpdateTextureDataParams & _params) override
		{
			glTextureSubImage2D(GLuint(_params.handle),
				_params.mipMapLevel,
				_params.x,
				_params.y,
				_params.width,
				_params.height,
				GLuint(_params.format),
				GLenum(_params.dataType),
				_params.data);
		}
Beispiel #6
0
static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data)
{
    GLNVGcontext* gl = (GLNVGcontext*)uptr;
    GLNVGtexture* tex = glnvg__findTexture(gl, image);

    if (tex == NULL) return 0;

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, y);

    if (tex->type == NVG_TEXTURE_RGBA)
        glTextureSubImage2D(tex->tex, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
    else
        glTextureSubImage2D(tex->tex, 0, x, y, w, h, GL_RED, GL_UNSIGNED_BYTE, data);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);

    return 1;
}
Beispiel #7
0
void GSTextureOGL::Unmap()
{
	if (m_type == GSTexture::Texture || m_type == GSTexture::RenderTarget) {

		PboPool::Unmap();

		glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, m_r_x, m_r_y, m_r_w, m_r_h, m_int_format, m_int_type, (const void*)PboPool::Offset());

		// FIXME OGL4: investigate, only 1 unpack buffer always bound
		PboPool::UnbindPbo();

		PboPool::EndTransfer();

		GL_POP(); // PUSH is in Map
	}
}
Beispiel #8
0
kit::Texture::Ptr kit::Texture::create2DFromFile(std::string filename, kit::Texture::InternalFormat format, kit::Texture::EdgeSamplingMode edgemode, kit::Texture::FilteringMode minfilter, kit::Texture::FilteringMode magfilter)
{
  std::cout << "Loading texture from file " << filename.c_str() << std::endl;
  kit::Texture::Ptr returner = std::make_shared<kit::Texture>(Texture2D);
  returner->m_internalFormat    = format;

  // Try to load data from file
  unsigned char* bufferdata;
  int x, y, n;

  stbi_set_flip_vertically_on_load(1);
  bufferdata = stbi_load(filename.c_str(), &x, &y, &n, 4);
  if (bufferdata == nullptr)
  {
    KIT_ERR(stbi_failure_reason());
    x = 1;
    y = 1;
    n = 4;
    bufferdata = new unsigned char[4];
    bufferdata[0] = 255;
    bufferdata[1] = 0;
    bufferdata[2] = 0;
    bufferdata[3] = 255;
  }

  // Set resolution
  returner->m_resolution        = glm::uvec3(x, y, 0);

  // Specify storage and upload data to GPU
  KIT_GL(glTextureStorage2D(returner->m_glHandle, returner->calculateMipLevels(), returner->m_internalFormat, returner->m_resolution.x, returner->m_resolution.y));
  KIT_GL(glTextureSubImage2D(returner->m_glHandle, 0, 0, 0, x, y, GL_RGBA, GL_UNSIGNED_BYTE, bufferdata));

  // Free loaded data
  stbi_image_free(bufferdata);

  // Set parameters
  returner->setEdgeSamplingMode(edgemode);
  returner->setMinFilteringMode(minfilter);
  returner->setMagFilteringMode(magfilter);

  returner->setAnisotropicLevel(8.0f);

  // Generate mipmap
  returner->generateMipmap();

  return returner;
}
Beispiel #9
0
bool GLTextureRectangle::set2D( const void* srcPtr, const Vector2i& srcSize,
                               GLImageFormat srcFormat, GLPixelType srcType,
                               const Vector2i& dstOffset )
{
    bool succeeded = checkSize( srcSize, dstOffset );
    if( succeeded )
    {
        glTextureSubImage2D
        (
            id(), 0,
            dstOffset.x, dstOffset.y, srcSize.x, srcSize.y,
            glImageFormat( srcFormat ), glPixelType( srcType ),
            srcPtr
        );
    }
    return succeeded;
}
	bool initTexture()
	{
		gli::texture2d Texture(gli::load(getDataDirectory() + TEXTURE_DIFFUSE));
		if(Texture.empty())
			return 0;

		gli::gl GL(gli::gl::PROFILE_GL33);
		gli::gl::format const Format = GL.translate(Texture.format(), Texture.swizzles());
		GLenum const Target = GL.translate(Texture.target());
		glm::tvec2<GLsizei> const Dimensions(Texture.extent());

		glCreateTextures(GL_TEXTURE_2D, 1, &TextureName[texture::TEXTURE]);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(Texture.levels() - 1));
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_SWIZZLE_R, Format.Swizzles[0]);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_SWIZZLE_G, Format.Swizzles[1]);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_SWIZZLE_B, Format.Swizzles[2]);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_SWIZZLE_A, Format.Swizzles[3]);
		glTextureStorage2D(TextureName[texture::TEXTURE],
			static_cast<GLint>(Texture.levels()), Format.Internal,
			Dimensions.x, Texture.target() == gli::TARGET_2D ? Dimensions.y : static_cast<GLsizei>(Texture.layers() * Texture.faces()));

		for(gli::texture2d::size_type Level = 0; Level < Texture.levels(); ++Level)
		{
			glTextureSubImage2D(TextureName[texture::TEXTURE], static_cast<GLint>(Level),
				0, 0,
				static_cast<GLsizei>(Texture[Level].extent().x), static_cast<GLsizei>(Texture[Level].extent().y),
				Format.External, Format.Type,
				Texture[Level].data());
		}


		glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &TextureName[texture::MULTISAMPLE]);
		glTextureParameteri(TextureName[texture::MULTISAMPLE], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::MULTISAMPLE], GL_TEXTURE_MAX_LEVEL, 0);
		glTextureStorage2DMultisample(TextureName[texture::MULTISAMPLE], 4, GL_RGBA8, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y, GL_FALSE);

		glCreateTextures(GL_TEXTURE_2D, 1, &TextureName[texture::COLORBUFFER]);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_MAX_LEVEL, 0);
		glTextureStorage2D(TextureName[texture::COLORBUFFER], 1, GL_RGBA8, GLsizei(FRAMEBUFFER_SIZE.x), GLsizei(FRAMEBUFFER_SIZE.y));

		return true;
	}
	bool initTexture()
	{
		bool Validated(true);

		gli::gl GL(gli::gl::PROFILE_GL33);
		gli::texture2d Texture(gli::load_dds((getDataDirectory() + TEXTURE_DIFFUSE).c_str()));
		assert(!Texture.empty());
		gli::gl::format const Format = GL.translate(Texture.format(), Texture.swizzles());

		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

		glCreateTextures(GL_TEXTURE_2D, texture::MAX, &TextureName[0]);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_MAX_LEVEL, GLint(Texture.levels() - 1));
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_SWIZZLE_R, GL_RED);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_SWIZZLE_G, GL_GREEN);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_SWIZZLE_B, GL_BLUE);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
		glTextureParameteri(TextureName[texture::DIFFUSE], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTextureStorage2D(TextureName[texture::DIFFUSE], static_cast<GLint>(Texture.levels()), Format.Internal,
			static_cast<GLsizei>(Texture.extent().x), static_cast<GLsizei>(Texture.extent().y));

		for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
		{
			glTextureSubImage2D(TextureName[texture::DIFFUSE], static_cast<GLint>(Level),
				0, 0,
				static_cast<GLsizei>(Texture[Level].extent().x), static_cast<GLsizei>(Texture[Level].extent().y),
				Format.External, Format.Type,
				Texture[Level].data());
		}
	
		glm::ivec2 WindowSize(this->getWindowSize());

		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_MAX_LEVEL, 0);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTextureStorage2D(TextureName[texture::COLORBUFFER], static_cast<GLint>(1), GL_RGBA8,
			static_cast<GLsizei>(WindowSize.x * this->Supersampling), static_cast<GLsizei>(WindowSize.y * this->Supersampling));

		return Validated;
	}
Beispiel #12
0
bufferPtr glPixelBuffer::begin() const {
    GL_API::getStateTracker().setPixelPackUnpackAlignment();
    glNamedBufferSubData(_pixelBufferHandle, 0, _bufferSize, NULL);
    GL_API::getStateTracker().setActiveBuffer(GL_PIXEL_UNPACK_BUFFER, _pixelBufferHandle);

    switch (_pbtype) {
        case PBType::PB_TEXTURE_1D:
            glTextureSubImage1D(_textureID,
                                0,
                                0,
                                _width,
                                _format,
                                _dataType,
                                NULL);
            break;
        case PBType::PB_TEXTURE_2D:
            glTextureSubImage2D(_textureID,
                                0,
                                0,
                                0,
                                _width,
                                _height,
                                _format,
                                _dataType,
                                NULL);
            break;
        case PBType::PB_TEXTURE_3D:
            glTextureSubImage3D(_textureID,
                                0,
                                0,
                                0,
                                0,
                                _width,
                                _height,
                                _depth,
                                _format,
                                _dataType,
                                NULL);
            break;
    };

    return glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
}
Beispiel #13
0
void
piglit_init(int argc, char **argv)
{
	int i;
	piglit_require_extension("GL_ARB_direct_state_access");
	piglit_require_extension("GL_ARB_texture_storage");

	for(i = 0; i < 4096; ++i)
		data[i] = rand() & 0xff;

	glCreateTextures(GL_TEXTURE_2D, 1, &name);
	glTextureParameteri(name, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTextureParameteri(name, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTextureStorage2D(name, 1, GL_RGBA8, 64, 16);
	glTextureSubImage2D(name, 0, 0, 0, 64, 16, GL_RGBA, GL_UNSIGNED_BYTE,
			    data);

	piglit_gen_ortho_projection(0.0, 1.0, 0.0, 1.0, -2.0, 6.0, GL_FALSE);
}
Beispiel #14
0
GLuint LoadTexture(WORD resourceId)
{
    HRSRC hrsrc = FindResource(
        nullptr, MAKEINTRESOURCE(resourceId), RT_BITMAP);
    HGLOBAL hglobal = LoadResource(nullptr, hrsrc);
    const GLbyte *data = static_cast<const GLbyte *>(LockResource(hglobal));

    const int width = *reinterpret_cast<const int *>(data + 4);
    const int height = *reinterpret_cast<const int *>(data + 8);

    GLuint texture;
    glCreateTextures(GL_TEXTURE_2D, 1, &texture);
    glTextureStorage2D(texture, 1, GL_RGB8, width, height);
    glTextureSubImage2D(texture, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, data + 40);

    glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    return texture;
}
Beispiel #15
0
static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data)
{
    GLNVGcontext* gl = (GLNVGcontext*)uptr;
    GLNVGtexture* tex = glnvg__allocTexture(gl);

    if (tex == NULL) return 0;

    const bool formatRGBA8 = type == NVG_TEXTURE_RGBA;
    const bool useMipmaps = (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) != 0;
    glCreateTextures(GL_TEXTURE_2D, 1, &tex->tex);
    const uint32_t mipCount = useMipmaps ? bit_fls(core::max<uint32_t>(w, h)) : 1;
    glTextureStorage2D(tex->tex, mipCount, formatRGBA8 ? GL_RGBA8 : GL_R8, w, h);
    tex->width = w;
    tex->height = h;
    tex->type = type;


    if (data)
    {
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
        glTextureSubImage2D(tex->tex, 0, 0, 0, w, h, formatRGBA8 ? GL_RGBA : GL_RED, GL_UNSIGNED_BYTE, data);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
        // The new way to build mipmaps on GLES and GL3
        if (useMipmaps) {
            glGenerateTextureMipmap(tex->tex);
        }
    }

    glTextureParameteri(tex->tex, GL_TEXTURE_MIN_FILTER, useMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
    glTextureParameteri(tex->tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    return tex->id;
}
	bool initTexture()
	{
		gli::texture2d Texture(gli::load_dds((getDataDirectory() + TEXTURE_DIFFUSE).c_str()));
		if(Texture.empty())
			return false;

		gli::gl GL;
		gli::gl::format const Format = GL.translate(Texture.format());

		glCreateTextures(GL_TEXTURE_2D, 1, &TextureName[texture::TEXTURE]);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MAX_LEVEL, static_cast<GLint>(Texture.levels() - 1));
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTextureParameteri(TextureName[texture::TEXTURE], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTextureStorage2D(TextureName[texture::TEXTURE], GLint(Texture.levels()), Format.Internal, GLsizei(Texture[0].extent().x), GLsizei(Texture[0].extent().y));
		for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
		{
			glTextureSubImage2D(TextureName[texture::TEXTURE], GLint(Level),
				0, 0, 
				GLsizei(Texture[Level].extent().x), GLsizei(Texture[Level].extent().y),
				Format.External, Format.Type,
				Texture[Level].data());
		}

		glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &TextureName[texture::MULTISAMPLE]);
		glTextureParameteri(TextureName[texture::MULTISAMPLE], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::MULTISAMPLE], GL_TEXTURE_MAX_LEVEL, 0);
		glTextureStorage2DMultisample(TextureName[texture::MULTISAMPLE], 4, GL_RGBA8, FRAMEBUFFER_SIZE.x, FRAMEBUFFER_SIZE.y, GL_FALSE);

		glCreateTextures(GL_TEXTURE_2D, 1, &TextureName[texture::COLORBUFFER]);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_BASE_LEVEL, 0);
		glTextureParameteri(TextureName[texture::COLORBUFFER], GL_TEXTURE_MAX_LEVEL, 0);
		glTextureStorage2D(TextureName[texture::COLORBUFFER], 1, GL_RGBA8, GLsizei(FRAMEBUFFER_SIZE.x), GLsizei(FRAMEBUFFER_SIZE.y));

		return true;
	}
Beispiel #17
0
/**
 * Test a mip-mapped texture w/ rendering.
 */
static bool
test_2d_mipmap_rendering(void)
{
	GLuint tex;
	GLint width = 128, height = 64, levels = 8;
	GLint v, l;
	GLfloat vfloat;
	GLuint prog;

	glCreateTextures(GL_TEXTURE_2D, 1, &tex);
	glBindTextureUnit(0, tex);

	glTextureStorage2D(tex, levels, GL_RGBA8, width, height);

	piglit_check_gl_error(GL_NO_ERROR);

	/* check that the mipmap level sizes are correct */
	for (l = 0; l < levels; l++) {
		GLubyte *buf = create_image(width, height, Colors[l]);

		glTextureSubImage2D(tex, l, 0, 0, width, height,
				GL_RGBA, GL_UNSIGNED_BYTE, buf);

		free(buf);

		glGetTextureLevelParameteriv(tex, l, GL_TEXTURE_WIDTH,
					     &v);
		if (v != width) {
			printf("%s: level %d: bad width: %d, should be %d\n",
					 TestName, l, v, width);
			return false;
		}

		glGetTextureLevelParameteriv(tex, l, GL_TEXTURE_HEIGHT,
					     &v);
		if (v != height) {
			printf("%s: level %d: bad height: %d, should be %d\n",
					 TestName, l, v, height);
			return false;
		}


		/* Added to test glGetTextureLevelParameterfv */
		glGetTextureLevelParameterfv(tex, l, GL_TEXTURE_WIDTH,
					     &vfloat);
		if (vfloat != (GLfloat) width) {
			printf("%s: level %d: bad width: %.2f, "
			       "should be %.2f\n",
				TestName, l, vfloat, (GLfloat) width);
			return false;
		}

		glGetTextureLevelParameterfv(tex, l, GL_TEXTURE_HEIGHT,
					     &vfloat);
		if (vfloat != (GLfloat) height) {
			printf("%s: level %d: bad height: %.2f, "
			       "should be %.2f\n",
				TestName, l, vfloat, (GLfloat) height);
			return false;
		}


		if (width > 1)
			width /= 2;
		if (height > 1)
			height /= 2;
	}

	/* This should generate and error (bad level) */
	if (!piglit_khr_no_error) {
		GLubyte *buf = create_image(width, height, Colors[l]);
		GLenum err;

		glTextureSubImage2D(tex, levels, 0, 0, width, height,
				GL_RGBA, GL_UNSIGNED_BYTE, buf);

		err = glGetError();
		if (err == GL_NO_ERROR) {
			printf("%s: glTextureSubImage2D(illegal level)"
			       " failed to generate an error.\n",
			       TestName);
			return false;
		}

		free(buf);
	}

	/* now do a rendering test */
	glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER,
			GL_NEAREST_MIPMAP_NEAREST);
	glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	prog = dsa_create_program(GL_TEXTURE_2D);
	glUseProgram(prog);

	/* draw a quad using each texture mipmap level */
	for (l = 0; l < levels; l++) {
		GLfloat expected[4];
		GLint p;

		glTextureParameteri(tex, GL_TEXTURE_BASE_LEVEL, l);
		glTextureParameteri(tex, GL_TEXTURE_MAX_LEVEL, l);

		glClear(GL_COLOR_BUFFER_BIT);

		piglit_draw_rect_tex(-1.0, -1.0, 2.0, 2.0,
				     0.0, 0.0, 1.0, 1.0);

		expected[0] = Colors[l][0] / 255.0;
		expected[1] = Colors[l][1] / 255.0;
		expected[2] = Colors[l][2] / 255.0;
		expected[3] = Colors[l][3] / 255.0;

		p = piglit_probe_pixel_rgb(piglit_width/2, piglit_height/2,
					   expected);

		piglit_present_results();

		if (!p) {
			printf("%s: wrong color for mipmap level %d\n",
			       TestName, l);
			return false;
		}
	}

	glUseProgram(0);
	glDeleteProgram(prog);

	glDeleteTextures(1, &tex);

	return true;
}
Beispiel #18
0
	void OGLTexture1D::CreateHWResource(ArrayRef<ElementInitData> init_data, float4 const * clear_value_hint)
	{
		KFL_UNUSED(clear_value_hint);

		GLint glinternalFormat;
		GLenum glformat;
		GLenum gltype;
		OGLMapping::MappingFormat(glinternalFormat, glformat, gltype, format_);

		if (sample_count_ <= 1)
		{
			uint32_t const pbo_size = mipmap_start_offset_.back() * array_size_;
			if (glloader_GL_VERSION_4_5() || glloader_GL_ARB_direct_state_access())
			{
				glTextureParameteri(texture_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1);

				glNamedBufferStorage(pbo_, pbo_size, nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);

				uint32_t const w0 = this->Width(0);

				if (array_size_ > 1)
				{
					glTextureStorage2D(texture_, num_mip_maps_, glinternalFormat, w0, array_size_);
				}
				else
				{
					glTextureStorage1D(texture_, num_mip_maps_, glinternalFormat, w0);
				}

				if (!init_data.empty())
				{
					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);
							GLvoid const * data = init_data[array_index * num_mip_maps_ + level].data;

							if (IsCompressedFormat(format_))
							{
								uint32_t const block_size = NumFormatBytes(format_) * 4;
								GLsizei const image_size = ((w + 3) / 4) * block_size;

								if (array_size_ > 1)
								{
									glCompressedTextureSubImage2D(texture_, level, 0, array_index,
										w, 1, glformat, image_size, data);
								}
								else
								{
									glCompressedTextureSubImage1D(texture_, level, 0,
										w, glformat, image_size, data);
								}
							}
							else
							{
								if (array_size_ > 1)
								{
									glTextureSubImage2D(texture_, level, 0, array_index, w, 1,
										glformat, gltype, data);
								}
								else
								{
									glTextureSubImage1D(texture_, level, 0, w, glformat, gltype, data);
								}
							}
						}
					}
				}
			}
			else
			{
				auto& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
				
				re.BindTexture(0, target_type_, texture_);
				glTexParameteri(target_type_, GL_TEXTURE_MAX_LEVEL, num_mip_maps_ - 1);

				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_);
				if (glloader_GL_VERSION_4_4() || glloader_GL_ARB_buffer_storage())
				{
					glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pbo_size, nullptr, GL_DYNAMIC_STORAGE_BIT);
				}
				else
				{
					glBufferData(GL_PIXEL_UNPACK_BUFFER, pbo_size, nullptr, GL_STREAM_COPY);
				}
				re.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

				if (glloader_GL_VERSION_4_2() || glloader_GL_ARB_texture_storage())
				{
					uint32_t const w0 = this->Width(0);

					if (array_size_ > 1)
					{
						glTexStorage2D(target_type_, num_mip_maps_, glinternalFormat, w0, array_size_);
					}
					else
					{
						glTexStorage1D(target_type_, num_mip_maps_, glinternalFormat, w0);
					}

					if (!init_data.empty())
					{
						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);
								GLvoid const * data = init_data[array_index * num_mip_maps_ + level].data;

								if (IsCompressedFormat(format_))
								{
									uint32_t const block_size = NumFormatBytes(format_) * 4;
									GLsizei const image_size = ((w + 3) / 4) * block_size;

									if (array_size_ > 1)
									{
										glCompressedTexSubImage2D(target_type_, level, 0, array_index,
											w, 1, glformat, image_size, data);
									}
									else
									{
										glCompressedTexSubImage1D(target_type_, level, 0,
											w, glformat, image_size, data);
									}
								}
								else
								{
									if (array_size_ > 1)
									{
										glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
											glformat, gltype, data);
									}
									else
									{
										glTexSubImage1D(target_type_, level, 0, w, glformat, gltype, data);
									}
								}
							}
						}
					}
				}
				else
				{
					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);

							if (IsCompressedFormat(format_))
							{
								uint32_t const block_size = NumFormatBytes(format_) * 4;
								GLsizei const image_size = ((w + 3) / 4) * block_size;

								if (array_size_ > 1)
								{
									if (0 == array_index)
									{
										glCompressedTexImage2D(target_type_, level, glinternalFormat,
											w, array_size_, 0, image_size * array_size_, nullptr);
									}

									if (!init_data.empty())
									{
										glCompressedTexSubImage2D(target_type_, level, 0, array_index, w, 1,
											glformat, image_size, init_data[array_index * num_mip_maps_ + level].data);
									}
								}
								else
								{
									glCompressedTexImage1D(target_type_, level, glinternalFormat,
										w, 0, image_size,
										init_data.empty() ? nullptr : init_data[array_index * num_mip_maps_ + level].data);
								}
							}
							else
							{
								if (array_size_ > 1)
								{
									if (0 == array_index)
									{
										glTexImage2D(target_type_, level, glinternalFormat, w, array_size_, 0, glformat, gltype, nullptr);
									}

									if (!init_data.empty())
									{
										glTexSubImage2D(target_type_, level, 0, array_index, w, 1,
											glformat, gltype, init_data[array_index * num_mip_maps_ + level].data);
									}
								}
								else
								{
									glTexImage1D(target_type_, level, glinternalFormat, w, 0, glformat, gltype,
										init_data.empty() ? nullptr : init_data[array_index * num_mip_maps_ + level].data);
								}
							}
						}
					}
				}
			}
		}
		else
		{
			glBindRenderbuffer(GL_RENDERBUFFER, texture_);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, sample_count_, glinternalFormat, width_, 1);
		}

		hw_res_ready_ = true;
	}
Beispiel #19
0
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
{
	ASSERT(m_type != GSTexture::DepthStencil && m_type != GSTexture::Offscreen);

	// Default upload path for the texture is the Map/Unmap
	// This path is mostly used for palette. But also for texture that could
	// overflow the pbo buffer
	// Data upload is rather small typically 64B or 1024B. So don't bother with PBO
	// and directly send the data to the GL synchronously

	m_clean = false;

	uint32 row_byte = r.width() << m_int_shift;
	uint32 map_size = r.height() * row_byte;
#ifdef ENABLE_OGL_DEBUG_MEM_BW
	g_real_texture_upload_byte += map_size;
#endif

#if 0
	if (r.height() == 1) {
		// Palette data. Transfer is small either 64B or 1024B.
		// Sometimes it is faster, sometimes slower.
		glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, data);
		return true;
	}
#endif

	GL_PUSH("Upload Texture %d", m_texture_id);

	// The easy solution without PBO
#if 0
	// Likely a bad texture
	glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch >> m_int_shift);

	glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, data);

	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Restore default behavior
#endif

	// The complex solution with PBO
#if 1
	char* src = (char*)data;
	char* map = PboPool::Map(map_size);

	// PERF: slow path of the texture upload. Dunno if we could do better maybe check if TC can keep row_byte == pitch
	// Note: row_byte != pitch
	for (int h = 0; h < r.height(); h++) {
		memcpy(map, src, row_byte);
		map += row_byte;
		src += pitch;
	}

	PboPool::Unmap();

	glTextureSubImage2D(m_texture_id, GL_TEX_LEVEL_0, r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, (const void*)PboPool::Offset());

	// FIXME OGL4: investigate, only 1 unpack buffer always bound
	PboPool::UnbindPbo();

	PboPool::EndTransfer();
#endif

	return true;
}
Beispiel #20
0
PIGLIT_GL_TEST_CONFIG_END

/** Test texture size errors and subtexture position errors */
static bool
test_pos_and_sizes(void)
{
	bool pass = true;
	GLuint name;

	/* all of these should generate GL_INVALID_VALUE */
	glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, -16, 0, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, -6, -5, 0, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	glTexImage2D(GL_TEXTURE_2D, -2, GL_RGBA, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	glTexImage2D(GL_TEXTURE_2D, 2000, GL_RGBA, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	/* Setup dsa. */
	glCreateTextures(GL_TEXTURE_2D, 1, &name);
	glBindTextureUnit(0, name);	/* Since next command isn't bindless. */

	/* setup valid 2D texture for subsequent TexSubImage calls */
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);

	glTextureSubImage2D(name, 0, 6, 6, 100, 100, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	glTextureSubImage2D(name, 0, -6, -6, 10, 10, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	glCopyTextureSubImage2D(name, 0, -6, -6, 2, 2, 10, 10);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	glCopyTextureSubImage2D(name, 0, 6, 6, 2, 2, 200, 200);
	pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass;

	/* mipmap level 1 doesn't exist */
	glTextureSubImage2D(name, 1, 0, 0, 8, 8, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;

	/* mipmap level 2 doesn't exist */
	glCopyTextureSubImage2D(name, 2, 0, 0, 0, 0, 4, 4);
	pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass;

	/* To test 1D and 3D entry points, let's try using the wrong functions. */
	glTextureSubImage1D(name, 0, 0, 4, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_ENUM) && pass;

	glTextureSubImage3D(name, 0, 0, 0, 0, 4, 4, 4, GL_RGBA, GL_FLOAT, NULL);
	pass = piglit_check_gl_error(GL_INVALID_ENUM) && pass;

	glCopyTextureSubImage1D(name, 0, 0, 0, 0, 4);
	pass = piglit_check_gl_error(GL_INVALID_ENUM) && pass;

	glCopyTextureSubImage3D(name, 0, 0, 0, 0, 0, 0, 4, 4);
	pass = piglit_check_gl_error(GL_INVALID_ENUM) && pass;

	return pass;
}
Beispiel #21
0
void ImageViewerPanel::initializeGL()
{
	//glewInit();

	glGetIntegerv(GL_MAJOR_VERSION, &ogl_ver_major);
	glGetIntegerv(GL_MINOR_VERSION, &ogl_ver_minor);

	shaderP = make_unique<GLSLProgram>(
		"resources/shaders/img_vs.glsl",
		"resources/shaders/img_fs.glsl");

	if (ogl_ver_major == 4 && ogl_ver_minor >= 5)
	{
		// DSA
		// Create VAO
		glCreateBuffers(1, &vbo);
		glNamedBufferData(vbo, sizeof(frame), frame, GL_STATIC_DRAW);
		
		// IBO
		GLuint indices[] = { 0,1,2,2,3,0 };
		glCreateBuffers(1, &ibo);
		glNamedBufferData(ibo, sizeof(indices), indices, GL_STATIC_DRAW);

		// VAO
		glCreateVertexArrays(1, &vao);
		glEnableVertexArrayAttrib(vao, 0);

		// Setup the formats
		glVertexArrayAttribFormat(vao, 0, 2, GL_FLOAT, GL_FALSE, 0);
		glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(float) * 2);
		glVertexArrayAttribBinding(vao, 0, 0);

		glVertexArrayElementBuffer(vao, ibo);

		// Setup textures
		int texSize = 4;
		glCreateTextures(GL_TEXTURE_2D, 1, &tex);
		glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTextureParameteri(tex, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTextureParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTextureParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		glTextureStorage2D(tex, 1, GL_RGB32F, imgsize[0], imgsize[1]);
		if (texLen > 0)
		{
			glTextureSubImage2D(tex, 0, 0, 0, imgsize[0], imgsize[1], GL_RGB, GL_FLOAT, textures);
		}
		texHandle = glGetTextureHandleARB(tex);
		glMakeTextureHandleResidentARB(texHandle);
		
		
	}
	else
	{
		// Non-DSA
		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);
		// Bind UV values
		glGenBuffers(1, &vbo);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, sizeof(frame), frame, GL_STATIC_DRAW);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
		glEnableVertexAttribArray(0);

		glBindVertexArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
	}

}
Beispiel #22
0
kit::Texture::Texture(const std::string & filename, kit::Texture::InternalFormat format, uint8_t levels, Type t) : kit::Texture(t)
{
    std::cout << "Loading texture from file \"" << filename.c_str() << "\"" << std::endl;
    m_filename = filename;
    if(t == Type::Texture2D)
    {
        m_internalFormat    = format;

        // Try to load data from file
        unsigned char* bufferdata;
        int x, y, n;

        stbi_set_flip_vertically_on_load(1);
        bufferdata = stbi_load(filename.c_str(), &x, &y, &n, 4);
        if (bufferdata == nullptr)
        {
            KIT_THROW(stbi_failure_reason());
        }

        // Set resolution
        m_resolution        = glm::uvec3(x, y, 0);

        uint8_t mipLevels = levels > 0 ? levels : calculateMipLevels();

        // Specify storage and upload data to GPU
#ifndef KIT_SHITTY_INTEL
        glTextureStorage2D(m_glHandle, mipLevels, m_internalFormat, m_resolution.x, m_resolution.y);
        glTextureSubImage2D(m_glHandle, 0, 0, 0, x, y, GL_RGBA, GL_UNSIGNED_BYTE, bufferdata);
#else
        bind();
        glTexStorage2D(m_type, mipLevels, m_internalFormat, m_resolution.x, m_resolution.y);
        glTexSubImage2D(m_type, 0, 0, 0, x, y, GL_RGBA, GL_UNSIGNED_BYTE, bufferdata);
#endif

        // Free loaded data
        stbi_image_free(bufferdata);

        // Set parameters
        setEdgeSamplingMode(EdgeSamplingMode::Repeat);
        setMinFilteringMode(m_minFilteringMode);
        setMagFilteringMode(m_magFilteringMode);

        setAnisotropicLevel(1.0f);
    }
    if(t == Type::Texture3D)
    {
        m_internalFormat = format;

        // Try to load data from file
        unsigned char* bufferdata;
        int x, y, n;

        stbi_set_flip_vertically_on_load(0);
        bufferdata = stbi_load(filename.c_str(), &x, &y, &n, 4);
        if (bufferdata == nullptr) {
            KIT_THROW(stbi_failure_reason());
        }

        if (y != x*x || y%y != 0)
        {
            KIT_THROW("Failed to load 3d texture from file, not perfectly cubical");
        }

        // Set resolution
        m_resolution = glm::uvec3(x, x, x);

        // Specify storage and upload data to GPU
#ifndef KIT_SHITTY_INTEL
        glTextureStorage3D(m_glHandle, 1, m_internalFormat, x, x, x);
        glTextureSubImage3D(m_glHandle, 0, 0, 0, 0, x, x, x, GL_RGBA, GL_UNSIGNED_BYTE, bufferdata);
#else
        returner->bind();
        glTexStorage3D(returner->m_type, 1, m_internalFormat, x, x, x);
        glTexSubImage3D(returner->m_type, 0, 0, 0, 0, x, x, x, GL_RGBA, GL_UNSIGNED_BYTE, bufferdata);
#endif
        // Free loaded data
        stbi_image_free(bufferdata);

        setEdgeSamplingMode(EdgeSamplingMode::Repeat);
        setMinFilteringMode(m_minFilteringMode);
        setMagFilteringMode(m_magFilteringMode);

        setAnisotropicLevel(1.0f);
    }
}
Beispiel #23
-1
Image2D::Image2D(std::string const &path) :
    AbstractTexture(GL_TEXTURE_2D, true, true)
{
    ImageLoader il(path);

    GLsizei levels = log2(std::max(il.width(), il.height())) + 1;

    glTextureStorage2D(mId, levels, il.internalFormat(), il.width(), il.height());
    glTextureSubImage2D(mId, 0, 0, 0, il.width(), il.height(),
                        il.format(), GL_UNSIGNED_BYTE, il.data());
    glGenerateTextureMipmap(mId);
    makeResident();
}