Skip to content

Instantly share code, notes, and snippets.

@3p3r
Last active August 29, 2015 14:27
Show Gist options
  • Save 3p3r/e6d13e8aaf2d8c2abdc4 to your computer and use it in GitHub Desktop.
Save 3p3r/e6d13e8aaf2d8c2abdc4 to your computer and use it in GitHub Desktop.
Cinder CopyImageSubData (copies one OpenGL texture to another)
#include "CopyImageSubData.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/Fbo.h"
#include "cinder/gl/gl.h"
namespace cinder { namespace gl {
// The copy function retreival is only tested on Windows but should work
// on other platforms as well.
void CopyImageSubData(const ci::gl::Texture& src, ci::gl::Texture& dst)
{
typedef GLvoid(APIENTRY * PFNGLCOPYIMAGESUBDATA) (
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);
// Retrieve GL_ARB_copy_image extension statically
static struct _{
PFNGLCOPYIMAGESUBDATA copyFn;
_() : copyFn(nullptr) {
if (gl::isExtensionAvailable("GL_ARB_copy_image")) {
// Taken straight out of Glee Source:
#ifdef WIN32
copyFn = PFNGLCOPYIMAGESUBDATA(wglGetProcAddress("glCopyImageSubData"));
#elif defined(__APPLE__) || defined(__APPLE_CC__)
CFBundleRef bundle;
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true);
CFStringRef functionName = CFStringCreateWithCString(kCFAllocatorDefault, "GL_ARB_copy_image", kCFStringEncodingASCII);
void *function;
bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);
assert(bundle != NULL);
function = CFBundleGetFunctionPointerForName(bundle, functionName);
CFRelease(bundleURL);
CFRelease(functionName);
CFRelease(bundle);
copyFn = PFNGLCOPYIMAGESUBDATA(function);
#else
copyFn = PFNGLCOPYIMAGESUBDATA(glXGetProcAddressARB((const GLubyte *)"GL_ARB_copy_image"));
#endif
}
}
} __;
// Use GL_ARB_copy_image extension if available
if (__.copyFn)
{
GLsizei srcDepth = src.getTarget() == GL_TEXTURE_CUBE_MAP ? 6 : 1;
__.copyFn(src.getId(), src.getTarget(), 0, 0, 0, 0,
dst.getId(), dst.getTarget(), 0, 0, 0, 0,
src.getCleanWidth(), src.getCleanHeight(), srcDepth);
}
// Use legacy FBO copying in case GL_ARB_copy_image is not available
else
{
auto fbo = ci::gl::Fbo(src.getCleanWidth(), src.getCleanHeight());
glBindFramebuffer(GL_FRAMEBUFFER, fbo.getId());
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, src.getId(), 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
GL_TEXTURE_2D, dst.getId(), 0);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(
0, 0, src.getCleanWidth(), src.getCleanHeight(),
0, 0, dst.getCleanWidth(), dst.getCleanHeight(),
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
}} // namespace cinder::gl
#pragma once
namespace cinder { namespace gl {
class Texture;
// Internally copies textures with FBOs if GL_ARB_copy_image ext does not exist.
void CopyImageSubData(const cinder::gl::Texture& src, cinder::gl::Texture& dst);
}} // namespace cinder::gl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment