Skip to content

Instantly share code, notes, and snippets.

@IanByun
Forked from arturoc/ofPBO.cpp
Last active August 28, 2016 13:41
Show Gist options
  • Save IanByun/e9c2d27ea74a27bdfa7c535fb4e513d0 to your computer and use it in GitHub Desktop.
Save IanByun/e9c2d27ea74a27bdfa7c535fb4e513d0 to your computer and use it in GitHub Desktop.
/*
* ofPBO.cpp
*
* Created on: 08/04/2012
* Author: arturo
* Revised on: 2016-08-27
* Reviser: ofIan, Ian Byun
* updated to match deletion and renaming of ofTextureData members
*/
#include "ofPBO.h"
ofPBO::ofPBO() {
// TODO Auto-generated constructor stub
}
ofPBO::~ofPBO() {
if(!pboIds.empty()){
glDeleteBuffersARB(pboIds.size(), &pboIds[0]);
}
}
void ofPBO::allocate(ofTexture & tex, int numPBOs) {
pboIds.resize(numPBOs);
glGenBuffersARB(numPBOs, &pboIds[0]);
int numChannels=1;
switch(tex.getTextureData().glInternalFormat) {
case GL_LUMINANCE:
numChannels = 1;
break;
case GL_RGB: case GL_RGB8:
numChannels = 3;
break;
case GL_RGBA: case GL_RGBA8:
numChannels = 4;
break;
}
dataSize = tex.getWidth()*tex.getHeight()*numChannels;
for(int i=0; i<(int)pboIds.size(); i++){
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[i]);
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, dataSize, 0, GL_STREAM_DRAW_ARB);
}
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
texture = tex;
glInternalFormat = tex.getTextureData().glInternalFormat; //GL_RGB8
glFormat = ofGetGLFormatFromInternal(glInternalFormat); //GL_RGB
glType = ofGetGlTypeFromInternal(glInternalFormat); //GL_UNSIGNED_BYTE
ofLogNotice() << "glInternalFormat: " << ofGetGlInternalFormatName(glInternalFormat);
ofLogNotice() << "glFormat: " << ofGetGlInternalFormatName(glFormat);
ofLogNotice() << "glType: " << (glType == GL_UNSIGNED_BYTE? "GL_UNSIGNED_BYTE" : ofToString(glType)) << endl;
}
void ofPBO::updateData(const ofPixels & pixels) {
if(pboIds.empty()){
ofLogError() << "pbo not allocated";
return;
}
//this is from http://www.songho.ca/opengl/gl_pbo.html
// "index" is used to copy pixels from a PBO to a texture object
// "nextIndex" is used to update pixels in the other PBO
index = (index + 1) % pboIds.size(); // 오버플로우를 감안한 ++index
int nextIndex = (index + 1) % pboIds.size();
// bind PBO to update pixel values
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[nextIndex]);
// map the buffer object into client's memory
// Note that glMapBufferARB() causes sync issue.
// If GPU is working with this buffer, glMapBufferARB() will wait(stall)
// for GPU to finish its job. To avoid waiting (stall), you can call
// first glBufferDataARB() with NULL pointer before glMapBufferARB().
// If you do that, the previous data in PBO will be discarded and
// glMapBufferARB() returns a new allocated pointer immediately
// even if GPU is still working with the previous data.
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, dataSize, 0, GL_STREAM_DRAW_ARB);
GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
if(ptr) {
// update data directly on the mapped buffer
memcpy(ptr, pixels.getPixels(), dataSize);
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
}
// it is good idea to release PBOs with ID 0 after use.
// Once bound with 0, all pixel operations behave normal ways.
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
void ofPBO::updateTexture() {
// bind the texture and PBO
texture.bind();
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[index]);
//http://stackoverflow.com/questions/2405734/difference-between-gltexsubimage-and-glteximage-function-in-opengl
//https://www.opengl.org/wiki/Common_Mistakes#Texture_upload_and_pixel_reads
//https://www.opengl.org/sdk/docs/man/html/glTexSubImage2D.xhtml
glTexSubImage2D(texture.getTextureData().textureTarget, 0, 0, 0, texture.getWidth(), texture.getHeight(), glFormat, glType, 0);
texture.unbind();
// it is good idea to release PBOs with ID 0 after use.
// Once bound with 0, all pixel operations behave normal ways.
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment