void GLTextureBuffer::blitFromTexture(GLTextureBuffer* src, const PixelVolume& srcBox, const PixelVolume& dstBox)
	{
		if (src->mMultisampleCount > 0 && mMultisampleCount == 0) // Resolving MS texture
		{
			if (mTarget != GL_TEXTURE_2D || mTarget != GL_TEXTURE_2D_MULTISAMPLE)
				BS_EXCEPT(InvalidParametersException, "Non-2D multisampled texture not supported.");

			GLint currentFBO = 0;
			glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFBO);

			GLuint readFBO = GLRTTManager::instance().getBlitReadFBO();
			GLuint drawFBO = GLRTTManager::instance().getBlitDrawFBO();

			// Attach source texture
			glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
			src->bindToFramebuffer(0, 0, true);

			// Attach destination texture
			glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
			bindToFramebuffer(0, 0, true);

			// Perform blit
			glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);

			glReadBuffer(GL_COLOR_ATTACHMENT0);
			glDrawBuffer(GL_COLOR_ATTACHMENT0);

			glBlitFramebuffer(srcBox.left, srcBox.top, srcBox.right, srcBox.bottom, 
				dstBox.left, dstBox.top, dstBox.right, dstBox.bottom, GL_COLOR_BUFFER_BIT, GL_NEAREST);

			// Restore the previously bound FBO
			glBindFramebuffer(GL_FRAMEBUFFER, currentFBO);
		}
		else // Just plain copy
		{
			if (mMultisampleCount != src->mMultisampleCount)
				BS_EXCEPT(InvalidParametersException, "When copying textures their multisample counts must match.");

			if (mTarget == GL_TEXTURE_3D) // 3D textures can't have arrays so their Z coordinate is handled differently
			{
				glCopyImageSubData(src->mTextureID, src->mTarget, src->mLevel, srcBox.left, srcBox.top, srcBox.front,
					mTextureID, mTarget, mLevel, dstBox.left, dstBox.top, dstBox.front, srcBox.getWidth(), srcBox.getHeight(), srcBox.getDepth());
			}
			else
			{
				glCopyImageSubData(src->mTextureID, src->mTarget, src->mLevel, srcBox.left, srcBox.top, src->mFace,
					mTextureID, mTarget, mLevel, dstBox.left, dstBox.top, mFace, srcBox.getWidth(), srcBox.getHeight(), 1);
			}
		}		
	}
void GlRenderer::copy_rect( uint16_t source_top_left[2],
                            uint16_t target_top_left[2],
                            uint16_t dimensions[2])
{
    // Draw pending commands
    this->draw();

    uint32_t upscale = this->internal_upscaling;

    GLint src_x = (GLint) source_top_left[0] * (GLint) upscale;
    GLint src_y = (GLint) source_top_left[1] * (GLint) upscale;
    GLint dst_x = (GLint) target_top_left[0] * (GLint) upscale;
    GLint dst_y = (GLint) target_top_left[1] * (GLint) upscale;

    GLsizei w = (GLsizei) dimensions[0] * (GLsizei) upscale;
    GLsizei h = (GLsizei) dimensions[1] * (GLsizei) upscale;

    // XXX CopyImageSubData gives undefined results if the source
    // and target area overlap, this should be handled
    // explicitely
    /* TODO - OpenGL 4.3 and GLES 3.2 requirement! FIXME! */
    glCopyImageSubData( this->fb_out->id, GL_TEXTURE_2D, 0, src_x, src_y, 0,
                        this->fb_out->id, GL_TEXTURE_2D, 0, dst_x, dst_y, 0,
                        w, h, 1 );

    get_error();
}
void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj)
{
   AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
   GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);

   if( gglHasExtension(ARB_copy_image) )
   {
      if(mBackBufferColorTex.getWidth() == glTexture->getWidth()
         && mBackBufferColorTex.getHeight() == glTexture->getHeight()
         && mBackBufferColorTex.getFormat() == glTexture->getFormat())
      {
         glCopyImageSubData(
           static_cast<GFXGLTextureObject*>(mBackBufferColorTex.getPointer())->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
           glTexture->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
           getSize().x, getSize().y, 1);
         return;
      }
   }

   PRESERVE_FRAMEBUFFER();

   if(!mCopyFBO)
   {
      glGenFramebuffers(1, &mCopyFBO);
   }
   
   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFBO);
   glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture->getHandle(), 0);
   
   glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackBufferFBO);
   
   glBlitFramebuffer(0, 0, getSize().x, getSize().y,
      0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
Exemple #4
0
/*
 *
 * Core in:
 * OpenGL    : 2.0 
 * OpenGLES  : 3.2
 */
void rglCopyImageSubData( 	GLuint srcName,
  	GLenum srcTarget,
  	GLint srcLevel,
  	GLint srcX,
  	GLint srcY,
  	GLint srcZ,
  	GLuint dstName,
  	GLenum dstTarget,
  	GLint dstLevel,
  	GLint dstX,
  	GLint dstY,
  	GLint dstZ,
  	GLsizei srcWidth,
  	GLsizei srcHeight,
  	GLsizei srcDepth)
{
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES32)
   glCopyImageSubData(srcName,
         srcTarget,
         srcX,
         srcY,
         srcZ,
         dstName,
         dstTarget,
         dstLevel,
         dstX,
         dstY,
         dstZ,
         srcWidth,
         srcHeight,
         srcDepth);
#endif
}
Exemple #5
0
Texture2DArray::Texture2DArray(const Texture2DArray& rhs)
    : Texture(rhs)
    , dimensions_(rhs.dimensions_)
{
    setTextureParameterFunction(this, &Texture2DArray::default2DArrayTextureParameterFunction);
    initialize(nullptr);
    if(OpenGLCapabilities::getOpenGLVersion() >= 430){
        //GPU memcpy
        glCopyImageSubData(rhs.getID(), rhs.getTarget(), 0, 0, 0, 0, getID(), 
            target_, 0, 0, 0, 0, dimensions_.x, dimensions_.y, dimensions_.z);
    }
    else{
        //Copy data through PBO
        loadFromPBO(&rhs);
    }
}
Exemple #6
0
static bool
test_copy_image(const struct fmt_test *test, GLuint src, GLuint *texture)
{
	bool result = true;
	GLuint tex = create_texture(test);
	*texture = tex;
	glCopyImageSubData(src, GL_TEXTURE_2D, 0, 0, 0, 0, tex, GL_TEXTURE_2D,
			   0, 0, 0, 0, piglit_width, piglit_height, 0);

	if (!piglit_check_gl_error(GL_NO_ERROR)) {
		piglit_report_subtest_result(PIGLIT_FAIL,
					     "format 0x%x copyimage fail",
					     test->iformat);
		result = false;
	}
	return result;
}
Exemple #7
0
Texture2DArray& Texture2DArray::operator=(const Texture2DArray& rhs) {
    if (this != &rhs) {
        Texture::operator=(rhs);
        dimensions_ = rhs.dimensions_;
        setTextureParameterFunction(this, &Texture2DArray::default2DArrayTextureParameterFunction);
        initialize(nullptr);
        if(OpenGLCapabilities::getOpenGLVersion() >= 430){
            //GPU memcpy
            glCopyImageSubData(rhs.getID(), rhs.getTarget(), 0, 0, 0, 0, getID(), 
                target_, 0, 0, 0, 0, rhs.dimensions_.x, rhs.dimensions_.y, rhs.dimensions_.z);
        }
        else{
            //Copy data through PBO
            loadFromPBO(&rhs);
        }
    }

    return *this;
}
Exemple #8
0
static enum piglit_result
run_multisample_test(struct texture_format *src_format,
		     struct texture_format *dst_format)
{
	bool pass = true;
	int fbo_width, fbo_height;
	GLuint fbo, rb, src_tex, dst_tex, res_tex;
	static const GLfloat verts[] = {
		0.0, 0.0,
		0.0, 1.0,
		1.0, 1.0,
		1.0, 1.0,
		1.0, 0.0,
		0.0, 0.0
	};

	/* Upload the source, destination, and expected result */
	src_tex = piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE, 0,
					     src_format->internal_format,
					     TEX_SIZE, TEX_SIZE, 1, samples,
					     src_format->format,
					     src_format->data_type, src_data);

	dst_tex = piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE, 0,
					     dst_format->internal_format,
					     TEX_SIZE, TEX_SIZE, 1, samples,
					     dst_format->format,
					     dst_format->data_type, dst_data);

	res_tex = piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE, 0,
					     dst_format->internal_format,
					     TEX_SIZE, TEX_SIZE, 1, samples,
					     dst_format->format,
					     dst_format->data_type, res_data);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	/* If any of these are zero, but there was no error, then it must
	 * not be renderable, so we just skip without even reporting the
	 * subtest.
	 */
	if ((src_tex == 0 || dst_tex == 0 || res_tex == 0) && pass)
		return PIGLIT_SKIP;

	glCopyImageSubData(src_tex, GL_TEXTURE_2D_MULTISAMPLE, 0,
			   TEX_SIZE / 4, TEX_SIZE / 4, 0,
			   dst_tex, GL_TEXTURE_2D_MULTISAMPLE, 0,
			   TEX_SIZE / 4, TEX_SIZE / 4, 0,
			   TEX_SIZE / 2, TEX_SIZE / 2, 1);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	glCopyImageSubData(dst_tex, GL_TEXTURE_2D_MULTISAMPLE, 0,
			   0, TEX_SIZE / 2, 0,
			   dst_tex, GL_TEXTURE_2D_MULTISAMPLE, 0,
			   TEX_SIZE / 2, 0, 0,
			   TEX_SIZE / 2, TEX_SIZE / 2, 1);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	if (piglit_automatic) {
		fbo_width = TEX_SIZE;
		fbo_height = TEX_SIZE;
		glGenFramebuffers(1, &fbo);
		glBindFramebuffer(GL_FRAMEBUFFER, fbo);

		glGenRenderbuffers(1, &rb);
		glBindRenderbuffer(GL_RENDERBUFFER, rb);
		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA,
				      fbo_width, fbo_height);
		glFramebufferRenderbuffer(GL_FRAMEBUFFER,
					  GL_COLOR_ATTACHMENT0,
					  GL_RENDERBUFFER, rb);
	} else {
		fbo_width = piglit_width;
		fbo_height = piglit_height;
		glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
	}
	pass &= piglit_check_gl_error(GL_NO_ERROR);
	glViewport(0, 0, fbo_width, fbo_height);

	glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	/* Now we use a comparison shader to check to see if the
	 * destination matches the expected result.
	 */
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, dst_tex);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, res_tex);

	load_compare_program(dst_format);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
	glDrawArrays(GL_TRIANGLES, 0, 6);
	glDisableVertexAttribArray(0);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	/* If the destination texture matches the expected result, we
	 * should get green.  If not, we get red and this test fails.
	 */
	pass &= piglit_probe_rect_rgb(0, 0, fbo_width, fbo_height, green);

	glDeleteTextures(1, &src_tex);
	glDeleteTextures(1, &dst_tex);
	glDeleteTextures(1, &res_tex);

	if (!piglit_automatic)
		piglit_present_results();

	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
}
Exemple #9
0
static bool
test_simple_errors(GLenum src_target, GLenum dst_target)
{
	bool pass = true;
	GLuint i, src, src2, dst;

	src = image_create(src_target);
	dst = image_create(dst_target);

	/* Test all three combinations of incomplete src or dst  */
	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);

	image_storage(src_target, src, GL_RGBA8, 32, 32);
	assert(piglit_check_gl_error(GL_NO_ERROR));

	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);

	image_storage(dst_target, dst, GL_RGBA8, 32, 32);
	assert(piglit_check_gl_error(GL_NO_ERROR));

	/* We want to test with empty src but valid dst */
	src2 = image_create(src_target);

	glCopyImageSubData(src2, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);

	/* This is no longer needed */
	image_delete(src_target, src2);

	/* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core
	 * Profile spec says:
	 *
	 *     "An INVALID_VALUE error is generated if either name does not
	 *     correspond to a valid renderbuffer or texture object according
	 *     to the corresponding target parameter."
	 */
	if (src_target != GL_RENDERBUFFER_EXT) {
		for (i = 0; i < ARRAY_LENGTH(targets); ++i) {
			if (targets[i] == src_target)
				continue;

			/* here, targets[i] doesn't match src object's target */
			glCopyImageSubData(src, targets[i], 0, 0, 0, 0,
					   dst, dst_target, 0, 0, 0, 0,
					   0, 0, 0);
			pass &= piglit_check_gl_error(GL_INVALID_VALUE);
			if (!pass)
				return false;
		}
	}

	/* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core
	 * Profile spec says:
	 *
	 *     "An INVALID_VALUE error is generated if either name does not
	 *     correspond to a valid renderbuffer or texture object according
	 *     to the corresponding target parameter."
	 */
	if (dst_target != GL_RENDERBUFFER_EXT) {
		for (i = 0; i < ARRAY_LENGTH(targets); ++i) {
			if (targets[i] == dst_target)
				continue;

			/* here, targets[i] doesn't match dst object's target */
			glCopyImageSubData(src, src_target, 0, 0, 0, 0,
					   dst, targets[i], 0, 0, 0, 0,
					   0, 0, 0);
			pass &= piglit_check_gl_error(GL_INVALID_VALUE);
			if (!pass)
				return false;
		}
	}

	/* 4523 should be a bogus renderbuffer/texture */
	glCopyImageSubData(4523, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   4523, dst_target, 0, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);

	/* Invalid level */
	glCopyImageSubData(src, src_target, 5, 0, 0, 0,
			   dst, dst_target, 0, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   dst, dst_target, 5, 0, 0, 0, 0, 0, 0);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);

	/* Region out of bounds */
	glCopyImageSubData(src, src_target, 0, 7, 5, 2,
			   dst, dst_target, 0, 0, 0, 0, 26, 25, 20);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 7, 5, 2,
			   dst, dst_target, 0, 0, 0, 0, 25, 30, 20);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 7, 5, 2,
			   dst, dst_target, 0, 0, 0, 0, 25, 24, 31);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 7, 5, 2, 26, 25, 20);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 7, 5, 2, 25, 30, 20);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	glCopyImageSubData(src, src_target, 0, 0, 0, 0,
			   dst, dst_target, 0, 7, 5, 2, 25, 24, 31);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);

	image_delete(src_target, src);
	image_delete(dst_target, dst);

	return pass;
}
Exemple #10
0
static bool
test_compressed_alignment_errors()
{
	bool pass = true;
	GLuint tex[4];

	glGenTextures(4, tex);

	glBindTexture(GL_TEXTURE_2D, tex[0]);
	glTexStorage2D(GL_TEXTURE_2D, 1,
		       GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 128, 128);
	glBindTexture(GL_TEXTURE_2D, tex[1]);
	glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16UI, 32, 32);

	/* Check for alignment constaints */
	/* bad width = 21 */
	glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0,
			   tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 21, 24, 1);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	/* bad height = 22 */
	glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0,
			   tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 20, 22, 1);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	/* bad srcX = 2 */
	glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 2, 0, 0,
			   tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 20, 24, 1);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);
	/* bad srcY = 1 */
	glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 1, 0,
			   tex[1], GL_TEXTURE_2D, 0, 0, 0, 0, 20, 24, 1);
	pass &= piglit_check_gl_error(GL_INVALID_VALUE);

	/* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core
	 * Profile spec says:
	 *
	 *     "An INVALID_OPERATION error is generated if the texel size of
	 *     the uncompressed image is not equal to the block size of the
	 *     compressed image."
	 */
	glBindTexture(GL_TEXTURE_2D, tex[2]);
	glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB16UI, 32, 32);
	glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0,
			   tex[2], GL_TEXTURE_2D, 0, 0, 0, 0, 20, 20, 1);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);

	/* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core
	 * Profile spec says:
	 *
	 *     "An INVALID_OPERATION error is generated if the formats are
	 *     not compatible."
	 *
	 * The definition of compatible refers back to table 8.22 "Compatible
	 * internal formats for TextureView."  This table does not contain
	 * S3TC formats because they are from an older extension.  Given the
	 * different encodings of DXT1 and DXT3 textures, it is reasonable to
	 * assume they would not be compatible for texture views, and this
	 * matches at least NVIDIA's implementation.
	 */
	glBindTexture(GL_TEXTURE_2D, tex[3]);
	glTexStorage2D(GL_TEXTURE_2D, 1,
		       GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 32, 32);
	glCopyImageSubData(tex[0], GL_TEXTURE_2D, 0, 0, 0, 0,
			   tex[3], GL_TEXTURE_2D, 0, 0, 0, 0, 20, 20, 1);
	pass &= piglit_check_gl_error(GL_INVALID_OPERATION);

	glDeleteTextures(4, tex);

	return pass;
}
Exemple #11
0
PIGLIT_GL_TEST_CONFIG_END


static bool
test_combination(GLenum intFormat,
		 GLenum srcFormat, GLenum srcType,
		 GLenum dstFormat, GLenum dstType)
{
	const int width = 16, height = 16;
	int i;
	GLuint textures[2];
	GLubyte *image, *getimage;
	bool pass = true;
	int comps;

	switch (srcFormat) {
	case GL_RGB:
	case GL_BGR:
		comps = 3;
		break;
	case GL_RGBA:
	case GL_BGRA:
	case GL_RGBA_INTEGER:
	case GL_BGRA_INTEGER:
		comps = 4;
		break;
	default:
		assert(!"Unexpected format");
		comps = 4;
	}

	getimage = malloc(width * height * comps);

	image = malloc(width * height * comps);
	if (comps == 4) {
		for (i = 0; i < width * height; i++) {
			image[i * 4 + 0] = 0xff;
			image[i * 4 + 1] = 0x80;
			image[i * 4 + 2] = 0x40;
			image[i * 4 + 3] = 0x20;
		}
	}
	else {
		for (i = 0; i < width * height; i++) {
			image[i * 3 + 0] = 0xff;
			image[i * 3 + 1] = 0x80;
			image[i * 3 + 2] = 0x40;
		}
	}

	glGenTextures(2, textures);

	/* setup tex0 */
	glBindTexture(GL_TEXTURE_2D, textures[0]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, intFormat, width, height, 0,
		     srcFormat, srcType, image);

	/* setup tex1 */
	glBindTexture(GL_TEXTURE_2D, textures[1]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, intFormat, width, height, 0,
		     dstFormat, dstType, NULL);

	if (!piglit_check_gl_error(GL_NO_ERROR)) {
		/* should be no errors */
		pass = false;
	}

	/* Copy from tex0 to tex1 */
	glCopyImageSubData(textures[0], GL_TEXTURE_2D, 0, /* src image */
			   0, 0, 0,  /* src offset */
			   textures[1], GL_TEXTURE_2D, 0, /* dst image */
			   0, 0, 0,  /* dst offset */
			   width, height, 1);  /* src size */

	/* Readback tex1 */
	glGetTexImage(GL_TEXTURE_2D, 0, srcFormat, srcType, getimage);

	if (memcmp(image, getimage, width * height * comps) != 0) {
		printf("Failure:\n");
		printf("  internal tex format=%s\n",
		       piglit_get_gl_enum_name(intFormat));
		printf("  src tex format=%s type=%s\n",
		       piglit_get_gl_enum_name(srcFormat),
		       piglit_get_gl_enum_name(srcType));
		printf("  dst tex format=%s type=%s\n",
		       piglit_get_gl_enum_name(dstFormat),
		       piglit_get_gl_enum_name(dstType));
		printf("Expected %u %u %u %u\n",
		       image[0], image[1], image[2], image[3]);
		printf("Found %u %u %u %u\n",
		       getimage[0], getimage[1], getimage[2], getimage[3]);
		pass = false;
	}

	glDeleteTextures(2, textures);

	free(image);
	free(getimage);

	return pass;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglCopyImageSubData(JNIEnv *__env, jclass clazz, jint srcName, jint srcTarget, jint srcLevel, jint srcX, jint srcY, jint srcZ, jint dstName, jint dstTarget, jint dstLevel, jint dstX, jint dstY, jint dstZ, jint srcWidth, jint srcHeight, jint srcDepth, jlong __functionAddress) {
	glCopyImageSubDataPROC glCopyImageSubData = (glCopyImageSubDataPROC)(intptr_t)__functionAddress;
	UNUSED_PARAMS(__env, clazz)
	glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
}
	bool initTexture()
	{
		bool Validated(true);

		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

		glGenTextures(texture::MAX, &TextureName[0]);

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

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, TextureName[texture::DIFFUSE]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, GLint(Texture.levels() - 1));
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);

		// Set image
		for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
		{
			glTexImage2D(GL_TEXTURE_2D, GLint(Level),
				Format.Internal,
				GLsizei(Texture[Level].extent().x), GLsizei(Texture[Level].extent().y),
				0,
				Format.External, Format.Type,
				Texture[Level].data());
		}

		// Allocate texture storage of texture::COPY.
		glBindTexture(GL_TEXTURE_2D, TextureName[texture::COPY]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, GLint(Texture.levels() - 1));
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);

		for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
		{
			glTexImage2D(GL_TEXTURE_2D, GLint(Level),
				Format.Internal,
				GLsizei(Texture[Level].extent().x), GLsizei(Texture[Level].extent().y),
				0,
				Format.External, Format.Type,
				nullptr);
		}

		glBindTexture(GL_TEXTURE_2D, 0);

		// Fill texture data of texture::COPY from texture::DIFFUSE.
		for(std::size_t Level = 0; Level < Texture.levels(); ++Level)
		{
			glCopyImageSubData(
				TextureName[texture::DIFFUSE], GL_TEXTURE_2D, GLint(Level), 0, 0, 0,
				TextureName[texture::COPY], GL_TEXTURE_2D, GLint(Level), 0, 0, 0,
				GLsizei(Texture[Level].extent().x), GLsizei(Texture[Level].extent().y), 1);
		}

		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

		return Validated;
	}
Exemple #14
0
void GLGSRender::end()
{
	if (skip_frame || !framebuffer_status_valid || (conditional_render_enabled && conditional_render_test_failed) || !check_program_state())
	{
		rsx::thread::end();
		return;
	}

	if (manually_flush_ring_buffers)
	{
		//Use approximations to reseve space. This path is mostly for debug purposes anyway
		u32 approx_vertex_count = rsx::method_registers.current_draw_clause.get_elements_count();
		u32 approx_working_buffer_size = approx_vertex_count * 256;

		//Allocate 256K heap if we have no approximation at this time (inlined array)
		m_attrib_ring_buffer->reserve_storage_on_heap(std::max(approx_working_buffer_size, 256 * 1024U));
		m_index_ring_buffer->reserve_storage_on_heap(16 * 1024);
	}

	//Do vertex upload before RTT prep / texture lookups to give the driver time to push data
	u32 vertex_draw_count;
	u32 actual_vertex_count;
	u32 vertex_base;
	std::optional<std::tuple<GLenum, u32> > indexed_draw_info;
	std::tie(vertex_draw_count, actual_vertex_count, vertex_base, indexed_draw_info) = set_vertex_buffer();

	std::chrono::time_point<steady_clock> program_start = steady_clock::now();
	//Load program here since it is dependent on vertex state

	load_program(vertex_base, actual_vertex_count);

	std::chrono::time_point<steady_clock> program_stop = steady_clock::now();
	m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(program_stop - program_start).count();

	if (manually_flush_ring_buffers)
	{
		m_attrib_ring_buffer->unmap();
		m_index_ring_buffer->unmap();
	}
	else
	{
		//DMA push; not needed with MAP_COHERENT
		//glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
	}

	//Check if depth buffer is bound and valid
	//If ds is not initialized clear it; it seems new depth textures should have depth cleared
	auto copy_rtt_contents = [](gl::render_target *surface)
	{
		//Copy data from old contents onto this one
		//1. Clip a rectangular region defning the data
		//2. Perform a GPU blit
		u16 parent_w = surface->old_contents->width();
		u16 parent_h = surface->old_contents->height();
		u16 copy_w, copy_h;

		std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
		glCopyImageSubData(surface->old_contents->id(), GL_TEXTURE_2D, 0, 0, 0, 0, surface->id(), GL_TEXTURE_2D, 0, 0, 0, 0, copy_w, copy_h, 1);
		surface->set_cleared();
		surface->old_contents = nullptr;
	};

	//Check if we have any 'recycled' surfaces in memory and if so, clear them
	std::vector<int> buffers_to_clear;
	bool clear_all_color = true;
	bool clear_depth = false;

	for (int index = 0; index < 4; index++)
	{
		if (std::get<0>(m_rtts.m_bound_render_targets[index]) != 0)
		{
			if (std::get<1>(m_rtts.m_bound_render_targets[index])->cleared())
				clear_all_color = false;
			else
				buffers_to_clear.push_back(index);
		}
	}

	gl::render_target *ds = std::get<1>(m_rtts.m_bound_depth_stencil);
	if (ds && !ds->cleared())
	{
		clear_depth = true;
	}

	//Temporarily disable pixel tests
	glDisable(GL_SCISSOR_TEST);

	if (clear_depth || buffers_to_clear.size() > 0)
	{
		GLenum mask = 0;

		if (clear_depth)
		{
			gl_state.depth_mask(GL_TRUE);
			gl_state.clear_depth(1.0);
			gl_state.clear_stencil(255);
			mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
		}

		if (clear_all_color)
			mask |= GL_COLOR_BUFFER_BIT;

		glClear(mask);

		if (buffers_to_clear.size() > 0 && !clear_all_color)
		{
			GLfloat colors[] = { 0.f, 0.f, 0.f, 0.f };
			//It is impossible for the render target to be typa A or B here (clear all would have been flagged)
			for (auto &i: buffers_to_clear)
				glClearBufferfv(draw_fbo.id(), i, colors);
		}

		if (clear_depth)
			gl_state.depth_mask(rsx::method_registers.depth_write_enabled());

		ds->set_cleared();
	}

	if (g_cfg.video.strict_rendering_mode)
	{
		if (ds->old_contents != nullptr)
			copy_rtt_contents(ds);

		for (auto &rtt : m_rtts.m_bound_render_targets)
		{
			if (std::get<0>(rtt) != 0)
			{
				auto surface = std::get<1>(rtt);
				if (surface->old_contents != nullptr)
					copy_rtt_contents(surface);
			}
		}
	}

	glEnable(GL_SCISSOR_TEST);

	std::chrono::time_point<steady_clock> textures_start = steady_clock::now();

	//Setup textures
	//Setting unused texture to 0 is not needed, but makes program validation happy if we choose to enforce it
	for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
	{
		int location;
		if (!rsx::method_registers.fragment_textures[i].enabled())
		{
			if (m_textures_dirty[i])
			{
				glActiveTexture(GL_TEXTURE0 + i);
				glBindTexture(GL_TEXTURE_2D, 0);

				m_textures_dirty[i] = false;
			}
			continue;
		}

		if (m_program->uniforms.has_location("tex" + std::to_string(i), &location))
		{
			m_gl_textures[i].set_target(get_gl_target_for_texture(rsx::method_registers.fragment_textures[i]));
			__glcheck m_gl_texture_cache.upload_texture(i, rsx::method_registers.fragment_textures[i], m_gl_textures[i], m_rtts);
			__glcheck m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
		}
	}

	//Vertex textures
	for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
	{
		int texture_index = i + rsx::limits::fragment_textures_count;
		int location;

		if (!rsx::method_registers.vertex_textures[i].enabled())
		{
			//glActiveTexture(GL_TEXTURE0 + texture_index);
			//glBindTexture(GL_TEXTURE_2D, 0);
			continue;
		}

		if (m_program->uniforms.has_location("vtex" + std::to_string(i), &location))
		{
			m_gl_vertex_textures[i].set_target(get_gl_target_for_texture(rsx::method_registers.vertex_textures[i]));
			__glcheck m_gl_texture_cache.upload_texture(texture_index, rsx::method_registers.vertex_textures[i], m_gl_vertex_textures[i], m_rtts);
		}
	}

	std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
	m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();

	std::chrono::time_point<steady_clock> draw_start = steady_clock::now();

	if (g_cfg.video.debug_output)
	{
		m_program->validate();
	}

	if (indexed_draw_info)
	{
		const GLenum index_type = std::get<0>(indexed_draw_info.value());
		const u32 index_offset = std::get<1>(indexed_draw_info.value());

		if (__glcheck gl_state.enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
		{
			__glcheck glPrimitiveRestartIndex((index_type == GL_UNSIGNED_SHORT)? 0xffff: 0xffffffff);
		}

		__glcheck glDrawElements(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), vertex_draw_count, index_type, (GLvoid *)(uintptr_t)index_offset);
	}
	else
	{
		glDrawArrays(gl::draw_mode(rsx::method_registers.current_draw_clause.primitive), 0, vertex_draw_count);
	}

	m_attrib_ring_buffer->notify();
	m_index_ring_buffer->notify();
	m_vertex_state_buffer->notify();
	m_fragment_constants_buffer->notify();
	m_transform_constants_buffer->notify();

	std::chrono::time_point<steady_clock> draw_end = steady_clock::now();
	m_draw_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(draw_end - draw_start).count();
	m_draw_calls++;

	if (zcull_task_queue.active_query &&
		zcull_task_queue.active_query->active)
		zcull_task_queue.active_query->num_draws++;

	synchronize_buffers();
	rsx::thread::end();
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglCopyImageSubData(JNIEnv *env, jclass clazz, jint srcName, jint srcTarget, jint srcLevel, jint srcX, jint srcY, jint srcZ, jint dstName, jint dstTarget, jint dstLevel, jint dstX, jint dstY, jint dstZ, jint srcWidth, jint srcHeight, jint srcDepth, jlong function_pointer) {
	glCopyImageSubDataPROC glCopyImageSubData = (glCopyImageSubDataPROC)((intptr_t)function_pointer);
	glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
}
Exemple #16
0
static enum piglit_result
run_test(struct texture_format *src_format, struct texture_format *dst_format)
{
	bool pass = true, warn = false;
	unsigned src_width, src_height, dst_width, dst_height;
	unsigned src_level, dst_level;
	GLuint texture[2];

	glEnable(GL_TEXTURE_2D);

	glGenTextures(2, texture);

	src_width = TEX_SIZE * src_format->block_width;
	src_height = TEX_SIZE * src_format->block_height;

	glBindTexture(GL_TEXTURE_2D, texture[0]);
	if (src_format->can_be_reinterpreted) {
		src_level = DEFAULT_SRC_LEVEL;
		glTexStorage2D(GL_TEXTURE_2D, src_level + 2,
			       src_format->internal_format,
			       src_width << src_level, src_height << src_level);
		if (src_format->block_width != 1 ||
		    src_format->block_height != 1) {
			/* Compressed */
			glCompressedTexSubImage2D(GL_TEXTURE_2D, src_level,
						  0, 0,
						  src_width, src_height,
						  src_format->internal_format,
						  TEX_SIZE * TEX_SIZE * src_format->bytes,
						  src_data);
		} else {
			glTexSubImage2D(GL_TEXTURE_2D, src_level, 0, 0,
				     src_width, src_height, src_format->format,
				     src_format->data_type, src_data);
		}
	} else {
		src_level = 0;
		/* All non-reintepretable textures are uncompressed */
		glTexImage2D(GL_TEXTURE_2D, 0, src_format->internal_format,
			     src_width, src_height, 0, src_format->format,
			     src_format->data_type, src_data);
	}
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	pass &= piglit_check_gl_error(GL_NO_ERROR);
	if (!pass)
		goto cleanup;

	warn |= !check_texture(texture[0], src_level, src_format, src_data);

	dst_width = TEX_SIZE * dst_format->block_width;
	dst_height = TEX_SIZE * dst_format->block_height;

	glBindTexture(GL_TEXTURE_2D, texture[1]);
	if (dst_format->can_be_reinterpreted) {
		dst_level = DEFAULT_DST_LEVEL;
		glTexStorage2D(GL_TEXTURE_2D, dst_level + 2,
			       dst_format->internal_format,
			       dst_width << dst_level, dst_height << dst_level);
		if (dst_format->block_width != 1 ||
		    dst_format->block_height != 1) {
			/* Compressed */
			glCompressedTexSubImage2D(GL_TEXTURE_2D, dst_level,
						  0, 0,
						  dst_width, dst_height,
						  dst_format->internal_format,
						  TEX_SIZE * TEX_SIZE * dst_format->bytes,
						  dst_data);
		} else {
			glTexSubImage2D(GL_TEXTURE_2D, dst_level, 0, 0,
				     dst_width, dst_height, dst_format->format,
				     dst_format->data_type, dst_data);
		}
	} else {
		dst_level = 0;
		/* All non-reintepritable textures are uncompressed */
		glTexImage2D(GL_TEXTURE_2D, 0, dst_format->internal_format,
			     dst_width, dst_height, 0, dst_format->format,
			     dst_format->data_type, dst_data);
	}
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	pass &= piglit_check_gl_error(GL_NO_ERROR);
	if (!pass)
		goto cleanup;

	warn |= !check_texture(texture[1], dst_level, dst_format, dst_data);

	glCopyImageSubData(texture[0], GL_TEXTURE_2D, src_level,
			   src_width / 4, src_height / 4, 0,
			   texture[1], GL_TEXTURE_2D, dst_level,
			   dst_width / 4, dst_height / 4, 0,
			   src_width / 2, src_height / 2, 1);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	glCopyImageSubData(texture[1], GL_TEXTURE_2D, dst_level,
			   0, dst_height / 2, 0,
			   texture[1], GL_TEXTURE_2D, dst_level,
			   dst_width / 2, 0, 0,
			   dst_width / 2, dst_height / 2, 1);
	pass &= piglit_check_gl_error(GL_NO_ERROR);

	pass &= check_texture(texture[1], dst_level, dst_format, res_data);

cleanup:
	glDeleteTextures(2, texture);

	glDisable(GL_TEXTURE_2D);

	return pass ? (warn ? PIGLIT_WARN : PIGLIT_PASS) : PIGLIT_FAIL;
}
Exemple #17
0
/**
 * Create a 3D texture of the given format and size, draw a textured quad
 * with that texture, and check results.
 */
static bool
test_render(GLenum internalFormat, int width, int height, int depth)
{
	static const float c1[4] = {0.25, 0.25, 0.25, 1.0};
	static const float c2[4] = {0.75, 0.75, 0.75, 1.0};
	bool pass = true;
	char *data;
	int i, j;
	GLuint tex;
	unsigned mbytes = tex_size(internalFormat, width, height, depth);

	printf("Testing %d x %d x %d %s (%u MB) texture\n",
	       width, height, depth,
	       piglit_get_gl_enum_name(internalFormat), mbytes);
	fflush(stdout);

	glGenTextures(1, &tex);
	glBindTexture(GL_TEXTURE_3D, tex);
	alloc_tex3d(GL_TEXTURE_3D, internalFormat, width, height, depth);

	if (!piglit_check_gl_error(GL_NO_ERROR)) {
		printf("Creating texture failed in test_render().\n");
		pass = false;
		goto end;
	}

	/* Set its pixels, slice by slice. */
	data = malloc(width * height * 4);
	for (j = 0; j < height; j++) {
		for (i = 0; i < width; i++) {
			int a = (j * width + i) * 4;
			data[a+0] =
			data[a+1] =
			data[a+2] =
			data[a+3] = (i * 255) / (width - 1);
		}
	}

	if (piglit_is_extension_supported("GL_ARB_copy_image")) {
		/* load 0th slice */
		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0,
				width, height, 1,
				GL_RGBA, GL_UNSIGNED_BYTE, data);

		/* copy 0th slice to other slices (should be faster) */
		for (i = 1; i < depth; i++) {
			glCopyImageSubData(tex, GL_TEXTURE_3D, 0, 0, 0, 0,
					   tex, GL_TEXTURE_3D, 0, 0, 0, i,
					   width, height, 1);
		}
	}
	else {
		/* load each slice with glTexSubImage3D */
		for (i = 0; i < depth; i++) {
			glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i,
					width, height, 1,
					GL_RGBA, GL_UNSIGNED_BYTE, data);
		}
	}
	free(data);

	glClear(GL_COLOR_BUFFER_BIT);

	/* Now try basic rendering. */
	glEnable(GL_TEXTURE_3D);
	glBegin(GL_QUADS);
	glTexCoord3f(0, 0, 0.5);
	glVertex2f(0, 0);
	glTexCoord3f(0, 1, 0.5);
	glVertex2f(0, piglit_height);
	glTexCoord3f(1, 1, 0.5);
	glVertex2f(piglit_width, piglit_height);
	glTexCoord3f(1, 0, 0.5);
	glVertex2f(piglit_width, 0);
	glEnd();

	pass = piglit_probe_pixel_rgb(piglit_width * 1 / 4,
				      piglit_height * 1 / 4, c1) && pass;
	pass = piglit_probe_pixel_rgb(piglit_width * 3 / 4,
				      piglit_height * 1 / 4, c2) && pass;
	pass = piglit_probe_pixel_rgb(piglit_width * 1 / 4,
				      piglit_height * 3 / 4, c1) && pass;
	pass = piglit_probe_pixel_rgb(piglit_width * 3 / 4,
				      piglit_height * 3 / 4, c2) && pass;
	piglit_present_results();

	if (!pass) {
		printf("rendering failed with %d x %d x %d %s texture\n",
		       width, height, depth,
		       piglit_get_gl_enum_name(internalFormat));
	}

end:
	glDeleteTextures(1, &tex);

	return pass;
}
JNIEXPORT void JNICALL Java_org_lwjgl_opengles_GLES32_glCopyImageSubData(JNIEnv *__env, jclass clazz, jint srcName, jint srcTarget, jint srcLevel, jint srcX, jint srcY, jint srcZ, jint dstName, jint dstTarget, jint dstLevel, jint dstX, jint dstY, jint dstZ, jint srcWidth, jint srcHeight, jint srcDepth) {
    glCopyImageSubDataPROC glCopyImageSubData = (glCopyImageSubDataPROC)tlsGetFunction(315);
    UNUSED_PARAM(clazz)
    glCopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
}
Exemple #19
0
	void OGLTexture1D::CopyToSubTexture1D(Texture& target,
			uint32_t dst_array_index, uint32_t dst_level, uint32_t dst_x_offset, uint32_t dst_width,
			uint32_t src_array_index, uint32_t src_level, uint32_t src_x_offset, uint32_t src_width)
	{
		BOOST_ASSERT(type_ == target.Type());
		
		if ((format_ == target.Format()) && !IsCompressedFormat(format_) && (glloader_GL_VERSION_4_3() || glloader_GL_ARB_copy_image())
			&& (src_width == dst_width) && (1 == sample_count_))
		{
			OGLTexture& ogl_target = *checked_cast<OGLTexture*>(&target);
			glCopyImageSubData(
				texture_, target_type_, src_level,
				src_x_offset, 0, src_array_index,
				ogl_target.GLTexture(), ogl_target.GLType(), dst_level,
				dst_x_offset, 0, dst_array_index, src_width, 1, 1);
		}
		else
		{
			OGLRenderEngine& re = *checked_cast<OGLRenderEngine*>(&Context::Instance().RenderFactoryInstance().RenderEngineInstance());
			if ((sample_count_ > 1) && !IsCompressedFormat(format_) && (glloader_GL_ARB_texture_rg() || (4 == NumComponents(format_))))
			{
				GLuint fbo_src, fbo_dst;
				re.GetFBOForBlit(fbo_src, fbo_dst);

				GLuint old_fbo = re.BindFramebuffer();

				glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src);
				if (array_size_ > 1)
				{
					glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_, src_level, src_array_index);
				}
				else
				{
					if (sample_count_ <= 1)
					{
						glFramebufferTexture1D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target_type_, texture_, src_level);
					}
					else
					{
						glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER,
											GL_COLOR_ATTACHMENT0,
											GL_RENDERBUFFER, texture_);
					}
				}

				OGLTexture& ogl_target = *checked_cast<OGLTexture*>(&target);
				glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst);
				if (array_size_ > 1)
				{
					glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ogl_target.GLTexture(), dst_level, dst_array_index);
				}
				else
				{
					glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target_type_, ogl_target.GLTexture(), dst_level);
				}

				glBlitFramebuffer(src_x_offset, 0, src_x_offset + src_width, 1,
								dst_x_offset, 0, dst_x_offset + dst_width, 1,
								GL_COLOR_BUFFER_BIT, (src_width == dst_width) ? GL_NEAREST : GL_LINEAR);

				re.BindFramebuffer(old_fbo, true);
			}
			else
			{
				if ((src_width == dst_width) && (format_ == target.Format()))
				{
					if (IsCompressedFormat(format_))
					{
						BOOST_ASSERT(0 == (src_x_offset & 0x3));
						BOOST_ASSERT(0 == (dst_x_offset & 0x3));
						BOOST_ASSERT(0 == (src_width & 0x3));
						BOOST_ASSERT(0 == (dst_width & 0x3));

						Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only, 0, this->Width(src_level));
						Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only, 0, target.Width(dst_level));

						uint32_t const block_size = NumFormatBytes(format_) * 4;
						uint8_t const * s = mapper_src.Pointer<uint8_t>() + (src_x_offset / 4 * block_size);
						uint8_t* d = mapper_dst.Pointer<uint8_t>() + (dst_x_offset / 4 * block_size);
						std::memcpy(d, s, src_width / 4 * block_size);
					}
					else
					{
						size_t const format_size = NumFormatBytes(format_);

						Texture::Mapper mapper_src(*this, src_array_index, src_level, TMA_Read_Only, src_x_offset, src_width);
						Texture::Mapper mapper_dst(target, dst_array_index, dst_level, TMA_Write_Only, dst_x_offset, dst_width);
						uint8_t const * s = mapper_src.Pointer<uint8_t>();
						uint8_t* d = mapper_dst.Pointer<uint8_t>();

						std::memcpy(d, s, src_width * format_size);
					}
				}
				else
				{
					this->ResizeTexture1D(target, dst_array_index, dst_level, dst_x_offset, dst_width,
						src_array_index, src_level, src_x_offset, src_width, true);
				}
			}
		}
	}
int OgreOculus::go(void)
{
	// Create Root object
	root = new Ogre::Root("plugin.cfg", "ogre.cfg");

	// OpenGL
    root->loadPlugin("RenderSystem_GL_d");
    root->setRenderSystem(root->getRenderSystemByName("OpenGL Rendering Subsystem"));

	// Initialize Root
	root->initialise(false);

	// Initialize Oculus
	ovrHmd hmd;
	ovrHmdDesc hmdDesc;
	ovrGraphicsLuid luid;
	ovr_Initialize(nullptr);
	if(ovr_Create(&hmd, &luid) != ovrSuccess)
		exit(-1);
	hmdDesc = ovr_GetHmdDesc(hmd);
	if(ovr_ConfigureTracking(hmd,
		ovrTrackingCap_Orientation |ovrTrackingCap_MagYawCorrection |ovrTrackingCap_Position,
		0) != ovrSuccess)
		exit(-2);

	// Turn off HUD
	ovr_SetInt(hmd, "PerfHudMode", ovrPerfHud_Off);

	// Create a window
	window = root->createRenderWindow("Ogre + Oculus = <3", hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2, false);

	// Create scene manager and cameras
	smgr = root->createSceneManager(Ogre::ST_GENERIC);

	// Load Ogre resource paths from config file
    Ogre::ConfigFile cf;
    cf.load("resources_d.cfg");

    // Go through all sections & settings in the file and add resources
    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

    Ogre::String secName, typeName, archName;
    while (seci.hasMoreElements())
    {
        secName = seci.peekNextKey();
        Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
        Ogre::ConfigFile::SettingsMultiMap::iterator i;
        for (i = settings->begin(); i != settings->end(); ++i)
        {
            typeName = i->first;
            archName = i->second;

            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
                archName, typeName, secName);
        }
    }

	// Set resources
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

	// Create the model itself via OgreModel.cpp
	createOgreModel(smgr);

	// Create camera
	createCamera();

	// Set viewport and background color
	Ogre::Viewport* vp = window->addViewport(mCamera);
	vp->setBackgroundColour(Ogre::ColourValue(34, 89, 0)); // Yellow

	// Set aspect ratio
	mCamera->setAspectRatio(
    Ogre::Real(vp->getActualWidth()) /
    Ogre::Real(vp->getActualHeight()));

	// Initialize glew
	if(glewInit() != GLEW_OK)
		exit(-3);

	// Get texture sizes
	ovrSizei texSizeL, texSizeR;
	texSizeL = ovr_GetFovTextureSize(hmd, ovrEye_Left, hmdDesc.DefaultEyeFov[left], 1);
	texSizeR = ovr_GetFovTextureSize(hmd, ovrEye_Right, hmdDesc.DefaultEyeFov[right], 1);

	// Calculate render buffer size
	ovrSizei bufferSize;
	bufferSize.w = texSizeL.w + texSizeR.w;
	bufferSize.h = max(texSizeL.h, texSizeR.h);

	// Create render texture set
	ovrSwapTextureSet* textureSet;
	if(ovr_CreateSwapTextureSetGL(hmd, GL_RGB, bufferSize.w, bufferSize.h, &textureSet) != ovrSuccess)
		exit(-4);

	// Create Ogre render texture
	Ogre::GLTextureManager* textureManager = static_cast<Ogre::GLTextureManager*>(Ogre::GLTextureManager::getSingletonPtr());
	Ogre::TexturePtr rtt_texture(textureManager->createManual("RttTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
		Ogre::TEX_TYPE_2D, bufferSize.w, bufferSize.h, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET));
	Ogre::RenderTexture* rttEyes = rtt_texture->getBuffer(0, 0)->getRenderTarget();
	Ogre::GLTexture* gltex = static_cast<Ogre::GLTexture*>(Ogre::GLTextureManager::getSingleton().getByName("RttTex").getPointer());
	GLuint renderTextureID = gltex->getGLID();

	// Put camera viewport on the ogre render texture
	Ogre::Viewport* vpts[nbEyes];
	vpts[left]=rttEyes->addViewport(cams[left], 0, 0, 0, 0.5f);
	vpts[right]=rttEyes->addViewport(cams[right], 1, 0.5f, 0, 0.5f);
	vpts[left]->setBackgroundColour(Ogre::ColourValue(34, 89, 0)); // Black background
	vpts[right]->setBackgroundColour(Ogre::ColourValue(34, 89, 0));

	ovrTexture* mirrorTexture;
	if(ovr_CreateMirrorTextureGL(hmd, GL_RGB, hmdDesc.Resolution.w, hmdDesc.Resolution.h, &mirrorTexture) != ovrSuccess)
		exit(-5);
	Ogre::TexturePtr mirror_texture(textureManager->createManual("MirrorTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
		Ogre::TEX_TYPE_2D, hmdDesc.Resolution.w, hmdDesc.Resolution.h, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET));

	// Get GLIDs
	GLuint ogreMirrorTextureID = static_cast<Ogre::GLTexture*>(Ogre::GLTextureManager::getSingleton().getByName("MirrorTex").getPointer())->getGLID();
	GLuint oculusMirrorTextureID = ((ovrGLTexture*)mirrorTexture)->OGL.TexId;

	// Create EyeRenderDesc
	ovrEyeRenderDesc EyeRenderDesc[nbEyes];
	EyeRenderDesc[left] = ovr_GetRenderDesc(hmd, ovrEye_Left, hmdDesc.DefaultEyeFov[left]);
	EyeRenderDesc[right] = ovr_GetRenderDesc(hmd, ovrEye_Right, hmdDesc.DefaultEyeFov[right]);

	// Get offsets
	ovrVector3f offset[nbEyes];
	offset[left]=EyeRenderDesc[left].HmdToEyeViewOffset;
	offset[right]=EyeRenderDesc[right].HmdToEyeViewOffset;

	// Compositor layer
	ovrLayerEyeFov layer;
	layer.Header.Type = ovrLayerType_EyeFov;
	layer.Header.Flags = 0;
	layer.ColorTexture[left] = textureSet;
	layer.ColorTexture[right] = textureSet;
	layer.Fov[left] = EyeRenderDesc[left].Fov;
	layer.Fov[right] = EyeRenderDesc[right].Fov;
	layer.Viewport[left] = OVR::Recti(0, 0, bufferSize.w/2, bufferSize.h);
	layer.Viewport[right] = OVR::Recti(bufferSize.w/2, 0, bufferSize.w/2, bufferSize.h);

	// Get projection matrices
	for(size_t eyeIndex(0); eyeIndex < ovrEye_Count; eyeIndex++)
	{
		// Get the projection matrix
		OVR::Matrix4f proj = ovrMatrix4f_Projection(EyeRenderDesc[eyeIndex].Fov,
			static_cast<float>(0.01f),
			4000,
			true);

		// Convert it to Ogre matrix
		Ogre::Matrix4 OgreProj;
		for(size_t x(0); x < 4; x++)
			for(size_t y(0); y < 4; y++)
				OgreProj[x][y] = proj.M[x][y];

		// Set the matrix
		cams[eyeIndex]->setCustomProjectionMatrix(true, OgreProj);
	}

	// Variables for render loop
	bool render(true);
	ovrFrameTiming hmdFrameTiming;
	ovrTrackingState ts;
	OVR::Posef pose;
	ovrLayerHeader* layers;

	// Create event listener for handling user input
	createEventListener();

	//Run physics loop in a new thread
	std::map<Ogre::Entity*, Ogre::Vector3> positionRequests;
	std::map<Ogre::Entity*, std::string> animationRequests;
	std::map<Ogre::Entity*, std::vector<int>> rotationRequests;
	std::map<std::string, std::string> message;
	std::thread physicsThread(physicsLoop, smgr, &message, &positionRequests, &animationRequests, &rotationRequests);

	// Render loop
	while(render)
	{
		// Suspend physics loop and perform requested movement/rotations/animations
		if(positionRequests.size() > 0 || animationRequests.size() > 0 || rotationRequests.size() > 0){
			message.insert(std::pair<std::string, std::string>("", ""));
		
			for(auto const &request : positionRequests) {
				Ogre::Vector3 pos = request.second;
				Ogre::SceneNode* sceneNode = request.first->getParentSceneNode();
				sceneNode->setPosition(pos);
			}

			for(auto const &request : animationRequests) {
				request.first->getAnimationState(request.second)->addTime(0.1);
			}

			for(auto const &request : rotationRequests) {
				Ogre::SceneNode* sceneNode = request.first->getParentSceneNode();
				sceneNode->roll(Ogre::Degree(request.second[0]));
				sceneNode->pitch(Ogre::Degree(request.second[1]));
				sceneNode->yaw(Ogre::Degree(request.second[2]));
			}

			positionRequests.clear();
			animationRequests.clear();
			rotationRequests.clear();

			// Resume physics loop
			message.clear();
		}

		// Update Ogre window
		Ogre::WindowEventUtilities::messagePump();

		// Advance textureset index
		textureSet->CurrentIndex = (textureSet->CurrentIndex + 1) % textureSet->TextureCount;
		
		// Capture user input
		mKeyboard->capture();
		mMouse->capture();

		// Movement calculations
		mPlayerNode->translate(mDirection, Ogre::Node::TS_LOCAL);
		hmdFrameTiming = ovr_GetFrameTiming(hmd, 0);
		ts = ovr_GetTrackingState(hmd, hmdFrameTiming.DisplayMidpointSeconds);
		pose = ts.HeadPose.ThePose;
		ovr_CalcEyePoses(pose, offset, layer.RenderPose);
		oculusOrient = pose.Rotation;
		oculusPos = pose.Translation;
		mHeadNode->setOrientation(Ogre::Quaternion(oculusOrient.w, oculusOrient.x, oculusOrient.y, oculusOrient.z) * initialOculusOrientation.Inverse());
		
		// Apply head tracking
		mHeadNode->setPosition(headPositionTrackingSensitivity * Ogre::Vector3(oculusPos.x, oculusPos.y,oculusPos.z));
		
		// Update Ogre viewports
		root->_fireFrameRenderingQueued();
		vpts[left]->update();
		vpts[right]->update();

		// Copy the rendered image to the Oculus Swap Texture
		glCopyImageSubData(renderTextureID, GL_TEXTURE_2D, 0, 0, 0, 0,
		((ovrGLTexture*)(&textureSet->Textures[textureSet->CurrentIndex]))->OGL.TexId, GL_TEXTURE_2D, 0, 0, 0, 0,
		bufferSize.w,bufferSize.h, 1);
		layers = &layer.Header;

		// Submit new frame to the Oculus and update window
		ovr_SubmitFrame(hmd, 0, nullptr, &layers, 1);
		window->update();

		// Exit loop when window is closed
		if(window->isClosed()) render = false;
	}

	// Shud down Oculus
	ovr_Destroy(hmd);
	ovr_Shutdown();

	// Delete Ogre root and return
	delete root;
	return EXIT_SUCCESS;
}