/*
 * Test reading back an RGBA texture as luminance.
 */
static bool
test_rgba(void)
{
	static const GLfloat rgbaImage[4] = { 0.5, 0.25, 0.125, 1.0 };
	static const GLfloat lumImage[1] = { 0.5 };
	GLuint tex;
	GLfloat test[2*2*4];

	/* create 1x1 GL_RGBA texture */
	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
		     GL_RGBA, GL_FLOAT, rgbaImage);

	/* Get and check luminance image */
	glGetTextureImage(tex, 0, GL_LUMINANCE, GL_FLOAT, sizeof(test), test);
	if (!lum_equal(lumImage, test)) {
		printf("%s: glGetTextureImage(GL_RGBA as"
		       " GL_LUMINANCE) failed\n", TestName);
		printf("  Expected %g  Found %g\n", lumImage[0], test[0]);
		return false;
	}

	return true;
}
Пример #2
0
bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
{
	// LOTS OF CRAP CODE!!!! PLEASE FIX ME !!!
	if (m_type != GSTexture::Offscreen) return false;

	// The fastest way will be to use a PBO to read the data asynchronously. Unfortunately GSdx
	// architecture is waiting the data right now.

#if 0
	// Maybe it is as good as the code below. I don't know

	glGetTextureImage(m_texture_id, GL_TEX_LEVEL_0, m_int_format, m_int_type, 1024*1024*16, m_local_buffer);

#else

	// Bind the texture to the read framebuffer to avoid any disturbance
	glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
	glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);

	glPixelStorei(GL_PACK_ALIGNMENT, m_int_alignment);
	glReadPixels(0, 0, m_size.x, m_size.y, m_int_format, m_int_type, m_local_buffer);
	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

#endif

	m.bits = m_local_buffer;
	m.pitch = m_size.x << m_int_shift;

	return true;
}
Пример #3
0
bool kit::Texture::saveToFile(const std::string&filename)
{
    // Fetch data from GPU
    unsigned char * data = new unsigned char[(m_resolution.x * m_resolution.y) * 4];

#ifndef KIT_SHITTY_INTEL
    glGetTextureImage(m_glHandle, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLsizei)(((m_resolution.x * m_resolution.y) * 4) * sizeof(unsigned char)), &data[0]);
#else
    bind();
    glGetTexImage(m_type, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
#endif

    stbi_write_set_flip_vertically_on_save(1);

    // Write data to disk
    if(stbi_write_tga(filename.c_str(), m_resolution.x, m_resolution.y, 4, (void*)data) == 0)
    {
        KIT_ERR("Failed to write image to file")
        delete[] data;
        return false;
    }

    delete[] data;
    return true;
}
Пример #4
0
bool GSTextureOGL::Map(GSMap& m, const GSVector4i* _r)
{
	GSVector4i r = _r ? *_r : GSVector4i(0, 0, m_size.x, m_size.y);

	// LOTS OF CRAP CODE!!!! PLEASE FIX ME !!!
	if (m_type == GSTexture::Offscreen) {
		// The fastest way will be to use a PBO to read the data asynchronously. Unfortunately GSdx
		// architecture is waiting the data right now.

#if 0
		// Maybe it is as good as the code below. I don't know
		// With openGL 4.5 you can use glGetTextureSubImage

		glGetTextureImage(m_texture_id, GL_TEX_LEVEL_0, m_int_format, m_int_type, 1024*1024*16, m_local_buffer);

#else

		// Bind the texture to the read framebuffer to avoid any disturbance
		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
		glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);

		glPixelStorei(GL_PACK_ALIGNMENT, m_int_alignment);
		glReadPixels(r.x, r.y, r.width(), r.height(), m_int_format, m_int_type, m_local_buffer);

		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

#endif

		m.bits = m_local_buffer;
		m.pitch = m_size.x << m_int_shift;

		return true;
	} else if (m_type == GSTexture::Texture || m_type == GSTexture::RenderTarget) {
		GL_PUSH("Upload Texture %d", m_texture_id); // POP is in Unmap

		m_dirty = true;
		m_clean = false;

		uint32 row_byte = r.width() << m_int_shift;
		uint32 map_size = r.height() * row_byte;

		m.bits = (uint8*)PboPool::Map(map_size);
		m.pitch = row_byte;

#ifdef ENABLE_OGL_DEBUG_MEM_BW
	g_real_texture_upload_byte += map_size;
#endif

		// Save the area for the unmap
		m_r_x = r.x;
		m_r_y = r.y;
		m_r_w = r.width();
		m_r_h = r.height();

		return true;
	}

	return false;
}
Пример #5
0
bool GSTextureOGL::Save(const std::string& fn)
{
	// Collect the texture data
	uint32 pitch = 4 * m_committed_size.x;
	uint32 buf_size = pitch * m_committed_size.y * 2;// Note *2 for security (depth/stencil)
	std::unique_ptr<uint8[]> image(new uint8[buf_size]);
#ifdef ENABLE_OGL_DEBUG
	GSPng::Format fmt = GSPng::RGB_A_PNG;
#else
	GSPng::Format fmt = GSPng::RGB_PNG;
#endif

	if (IsBackbuffer()) {
		glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image.get());
	} else if(IsDss()) {
		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);

		glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_texture_id, 0);
		glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image.get());

		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

		fmt = GSPng::RGB_A_PNG;
	} else if(m_format == GL_R32I) {
		// Note: 4.5 function used for accurate DATE
		// barely used outside of dev and not sparse anyway
		glGetTextureImage(m_texture_id, 0, GL_RED_INTEGER, GL_INT, buf_size, image.get());

		fmt = GSPng::R32I_PNG;
	} else {
		glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);

		glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);

		if (m_format == GL_RGBA8) {
			glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image.get());
		}
		else if (m_format == GL_R16UI)
		{
			glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, image.get());
			fmt = GSPng::R16I_PNG;
		}
		else if (m_format == GL_R8)
		{
			fmt = GSPng::R8I_PNG;
			glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RED, GL_UNSIGNED_BYTE, image.get());
		}

		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
	}

	int compression = theApp.GetConfigI("png_compression_level");
	return GSPng::Save(fmt, fn, image.get(), m_committed_size.x, m_committed_size.y, pitch, compression);
}
Пример #6
0
	void Texture::read(size_t size, void* data) const
	{
		GLenum tex_type = toTextureType(type());
		SurfaceFormat fmt = this->format();
		ImageFormat gl_fmt = toImageFormat(fmt);

		// Read to 'data', not to a device buffer
		//glBindBuffer(GL_PIXEL_PACK_BUFFER, GL_NONE);

#	if defined(VCL_GL_ARB_direct_state_access)
		glGetTextureImage(_glId, 0, gl_fmt.Format, gl_fmt.Type, (GLsizei)size, data);
#	else
		TextureBindPoint bp(tex_type, _glId);
		if (tex_type != GL_TEXTURE_CUBE_MAP)
		{
#		if defined(VCL_GL_EXT_direct_state_access)
			glGetTextureImageEXT(_glId, tex_type, 0, gl_fmt.Format, gl_fmt.Type, data);
#		else
			glGetTexImage(tex_type, 0, gl_fmt.Format, gl_fmt.Type, data);
#		endif
		}
		else
		{
			const GLenum faces[] =
			{
				GL_TEXTURE_CUBE_MAP_POSITIVE_X,
				GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
				GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
				GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
				GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
			};
			int pixel_size = Vcl::Graphics::sizeInBytes(fmt);
			GLsizei w = (GLsizei)width();
			GLsizei h = (GLsizei)height();

			unsigned char* data_ptr = reinterpret_cast<unsigned char*>(data);
			for (const auto face : faces)
			{
#		if defined(VCL_GL_EXT_direct_state_access)
				glGetTextureImageEXT(_glId, face, 0, gl_fmt.Format, gl_fmt.Type, data_ptr);
#		else
				glGetTexImage(face, 0, gl_fmt.Format, gl_fmt.Type, data_ptr);
#		endif
				data_ptr += w * h * pixel_size;
			}
		}
#	endif
	}
Пример #7
0
bool kit::Texture::saveToFile(std::string filename)
{
  // Fetch data from GPU
  unsigned char * data = new unsigned char[(this->m_resolution.x * this->m_resolution.y) * 4];
  KIT_GL(glGetTextureImage(this->m_glHandle, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLsizei)(((this->m_resolution.x * this->m_resolution.y) * 4) * sizeof(unsigned char)), &data[0]));

  stbi_write_set_flip_vertically_on_save(1);

  // Write data to disk
  if(stbi_write_tga(filename.c_str(), this->m_resolution.x, this->m_resolution.y, 4, (void*)data) == 0)
  {
    KIT_ERR("Failed to write image to file")
    delete[] data;
    return false;
  }

  delete[] data;
  return true;
}
Пример #8
0
glm::uvec4 kit::Texture::getPixelUint(glm::vec3 position)
{
    glm::uvec4 returner(0, 0, 0, 0);

    // Clamp position
    if (position.x > 1.0f) position.x = 1.0f;
    if (position.x < 0.0f) position.x = 0.0f;
    if (position.y > 1.0f) position.y = 1.0f;
    if (position.y < 0.0f) position.x = 0.0f;
    if (position.z > 1.0f) position.z = 1.0f;
    if (position.z < 0.0f) position.x = 0.0f;

    // Flip Y
    position.y = 1.0f - position.y;

    // Get a fragment position
    glm::uvec3 fragPosition(uint32_t(position.x * float(m_resolution.x)), uint32_t(position.y * float(m_resolution.y)), uint32_t(position.z * float(m_resolution.z)));

    // Clamp again, because now we are in pixelspace, and we dont really want to be able to pick at 1.0, as that is one pixel outside. Ugly but it works.
    if (fragPosition.x >= m_resolution.x) fragPosition.x = m_resolution.x - 1;
    if (fragPosition.y >= m_resolution.y) fragPosition.y = m_resolution.y - 1;

    uint32_t numUints = m_resolution.x * m_resolution.y * 4;
    size_t dataSize = numUints * sizeof(uint32_t);
    std::vector<uint32_t> data(numUints);

    // Download pixels from the GPU
#ifndef KIT_SHITTY_INTEL
    glGetTextureImage(m_glHandle, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, (GLsizei)dataSize, &data[0]);
#else
    bind();
    glGetTexImage(m_type, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,  &data[0]);
#endif

    // Fill the returner
    returner.x = data[((m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4];
    returner.y = data[((m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4 + 1];
    returner.z = data[((m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4 + 2];
    returner.w = data[((m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4 + 3];

    // Return the returner
    return returner;
}
Пример #9
0
glm::vec4 kit::Texture::getPixelFloat(glm::vec3 position)
{
    glm::vec4 returner(0.0, 0.0, 0.0, 0.0);

    // Clamp position
    if (position.x > 1.0f) position.x = 1.0f;
    if (position.x < 0.0f) position.x = 0.0f;
    if (position.y > 1.0f) position.y = 1.0f;
    if (position.y < 0.0f) position.x = 0.0f;
    if (position.z > 1.0f) position.z = 1.0f;
    if (position.z < 0.0f) position.x = 0.0f;

    // Flip Y
    position.y = 1.0f - position.y;

    // Get a fragment position
    glm::uvec3 fragPosition(uint32_t(position.x * float(m_resolution.x)), uint32_t(position.y * float(m_resolution.y)), uint32_t(position.z * float(m_resolution.z)));

    if (fragPosition.x >= m_resolution.x) fragPosition.x = m_resolution.x - 1;
    if (fragPosition.y >= m_resolution.y) fragPosition.y = m_resolution.y - 1;

    uint32_t numFloats = m_resolution.x * m_resolution.y * 4;
    size_t dataSize = numFloats * sizeof(float);
    std::vector<float> data(numFloats);

    // Download pixels from the GPU
#ifndef KIT_SHITTY_INTEL
    glGetTextureImage(m_glHandle, 0, GL_RGBA, GL_FLOAT, (GLsizei)dataSize, &data[0]);
#else
    bind();
    glGetTexImage(m_type, 0, GL_RGBA, GL_FLOAT, &data[0]);
#endif

    // Fill the returner
    returner.x = data[ ( (m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4    ];
    returner.y = data[ ( (m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4 + 1];
    returner.z = data[ ( (m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4 + 2];
    returner.w = data[ ( (m_resolution.x * m_resolution.y) * fragPosition.z) + (fragPosition.x + (fragPosition.y * m_resolution.x)) * 4 + 3];

    // Return the returner
    return returner;
}
Пример #10
0
static int test_getteximage(void)
{
	GLubyte compare[4096];
	int i;

	glGetTextureImage(name, 0, GL_RGBA, GL_UNSIGNED_BYTE,
			  sizeof(compare), compare);

	for(i = 0; i < 4096; ++i) {
		if (data[i] != compare[i]) {
			printf("GetTextureImage() returns incorrect data in byte %i\n", i);
			printf("    corresponding to (%i,%i) channel %i\n", i / 64, (i / 4) % 16, i % 4);
			printf("    expected: %i\n", data[i]);
			printf("    got: %i\n", compare[i]);
			return 0;
		}
	}

	return 1;
}
Пример #11
0
enum piglit_result
piglit_display(void)
{
	bool pass = true;
	GLuint name;
	GLubyte *data = malloc(50 * 50 * 6 * 4 * sizeof(GLubyte));
	GLubyte *image = malloc(50 * 50 * 4 * sizeof(GLubyte));

	/* Throw some invalid inputs at glGetTextureImage. */

	/* Non-gen-ed name */
	glGetTextureImage(3, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, data);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);

	/* Unsupported target. */
	glGenTextures(1, &name);
	glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_X, name);
	glGetTextureImage(name, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, data);
	pass &= piglit_check_gl_error(GL_INVALID_ENUM);
	glDeleteTextures(1, &name);

	/* Unsupported dsa target for non-dsa version. */
	glGetTexImage(GL_TEXTURE_CUBE_MAP, 0, GL_RGBA, GL_UNSIGNED_BYTE,
		     data);
	pass &= piglit_check_gl_error(GL_INVALID_ENUM);

	/* No Storage
	 *
	 * The spec doesn't say what should happen in this case.  This is
	 * addressed by Khronos Bug 13223.
	 */
	glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &name);
	glGetTextureImage(name, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, data);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);
	glDeleteTextures(1, &name);

	/* Insufficient storage
	 *
	 * The spec doesn't say what should happen in this case.  This is
	 * addressed by Khronos Bug 13223.
	 */
	glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &name);
	glBindTexture(GL_TEXTURE_CUBE_MAP, name);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0,
		     GL_RGBA8, 50, 50, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0,
		     GL_RGBA8, 50, 50, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,
		     GL_RGBA8, 50, 50, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
	/* Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set */
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,
		     GL_RGBA8, 50, 50, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,
		     GL_RGBA8, 50, 50, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
	glGetTextureImage(name, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, data);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);
	glDeleteTextures(1, &name);

	/* Trivial, but should work. */
	glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &name);
	glTextureStorage2D(name, 1, GL_RGBA8, 50, 50);
	glGetTextureImage(name, 0, GL_RGBA, GL_UNSIGNED_BYTE,
			  50 * 50 * 6 * 4, data);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}