Last post about this, I swear.
I’ve got everything working 100% except for texturing. I’ll show you the code and what’s happening:
[code]void VideoEffectWorker::changeListenerCallback(void* object) {
if (object == glView) {
// TODO protect critical access
// not a problem yet, but could peut-etre.
glEnable(GL_TEXTURE_2D);
// texture filtering properties
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// glView has a new context! Upload the images to the GPU
// if they have already been loadeed from disk.
for (int i = 0; i < imageObjects.size(); ++i) {
glImages.set(i, loadImage(imageObjects[i]));
}
// set an orthographic projection: (0,0) at the top-left down to (1,1)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);
// glScalef(1.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// generate a display list.
quadList = glGenLists(1);
glNewList(quadList, GL_COMPILE);
glBegin(GL_QUADS);
// top-left
glTexCoord2f(0.0f, 0.0f);
glVertex3f (0.0f, 0.0f, 0.0f);
// bottom-left
glTexCoord2f(0.0f, 1.0f);
glVertex3f (0.0f, 1.0f, 0.0f);
// bottom-right
glTexCoord2f(1.0f, 1.0f);
glVertex3f (1.0f, 1.0f, 0.0f);
// top-right
glTexCoord2f(1.0f, 0.0f);
glVertex3f (1.0f, 0.0f, 0.0f);
glEnd();
glEndList();
// more stuff for the state machine
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
glFlush();
contextInit = true;
}
}
// Sets one of the numbered images.
void VideoEffectWorker::setImage(int n, Image* jImage) {
// set the new JUCE image.
if (n >= imageObjects.size()) return;
imageObjects.set(n, jImage);
// make the context active
if (!glView->lock()) return;
// TODO if glImages[n] != 0 { ... replace image instead of recreating ... }
// load it into the OpenGL context.
deleteImage(glImages[n]);
glImages.set(n, loadImage(imageObjects[n]));
// unlock the context.
glView->unlock();
}
// (private) Loads an image into the OpenGL context.
// Precondition: the OpenGL context is active.
GLuint VideoEffectWorker::loadImage(Image* jImage) {
// We need an image.
if (jImage == NULL) return 0;
// figure out JUCE's internal format.
GLint textureFormat, internalFormat;
if (jImage->isARGB()) {
internalFormat = GL_RGBA;
textureFormat = GL_BGRA;
} else if (jImage->isRGB()) {
internalFormat = GL_RGB;
textureFormat = GL_BGR;
} else {
textureFormat = internalFormat = GL_LUMINANCE;
}
// Get the texture data from the image.
int lineStride, pixelStride;
const uint8* pixelData = jImage->lockPixelDataReadOnly(0, 0,
jImage->getWidth(), jImage->getHeight(), lineStride, pixelStride);
// Generate a texture and bind it.
GLuint glTexture;
GLint oldTexture;
glGenTextures(1, &glTexture);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
glBindTexture(GL_TEXTURE_2D, glTexture);
// TODO: create a texture class and wrap this whole function.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0,
internalFormat,
jImage->getWidth(),
jImage->getHeight(),
0,
textureFormat,
GL_UNSIGNED_BYTE,
pixelData
);
// Re-bind the originally bound texture; release pixel data.
glBindTexture(GL_TEXTURE_2D, oldTexture);
jImage->releasePixelDataReadOnly(pixelData);
// return the bound texture.
return glTexture;
}
// (private) Deletes an image from the OpenGL context.
// Precondition: the OpenGL context is active.
void VideoEffectWorker::deleteImage(GLuint glImage) {
// make quite sure there's something to delete
if (glImage == 0) return;
// ... and delete it. If we can't get the context,
// it doesn't exist, and there's nothing to be deleted.
glDeleteTextures(1, &glImage);
}
// Handles the GL view’s rendering in a seperate thread.
void VideoEffectWorker::run() {
while (!threadShouldExit()) {
// grab exclusive access of the OpenGL context;
// this line may jump into handleNewContext synchronously.
if (contextInit && glView->lock()) {
// clear the screen
glClear(GL_COLOR_BUFFER_BIT);
// bind the first texture and draw it.
glBindTexture(GL_TEXTURE_2D, glImages[0]);
glCallList(quadList);
glFlush();
// release access; render
glView->swapBuffers();
glView->unlock();
}
}
contextInit = false;
}[/code]
So what I get is a white, untextured quad, which is not what I want. This however does tell me that the context creation method was called and the display list was compiled and is working. So that was good. But there were no OpenGL errors being flagged, and my texture wasn’t showing. So I did some sleuthing…
I tried removing the use of texture objects – that did the trick. The texture shows up as expected (specifically, I removed all glBindTexture commands).
So here’s my question – why is the display list valid in the thread, but not the texture object? Has anyone seen this before? I think I saw a thread about it while searching for this issue here, but there was no resolution. This happens on two computers; mine has a Radeon X1400 and was tested on Ubuntu and Windows Vista. The other one has an integrated GeForce 6 and was tested on Ubuntu. All work with the glBindTexture lines taken out; all show a white quad otherwise.
What am I missing?