Hello, I'm trying to change IWineD3DSurface::UnlockRect for rendertargets to avoid glDrawPixels. Instead, I'd like to load the image from memory into an OpenGL texture, and draw that texture with a textured quad onto the front / back buffer.
The problem I have is that the texture(or better, the resulting image) only has a solid color: The color of the first pixel in the source memory. I've read the texture section of the GL programming guide, but I didn't find a solution. I've attached a patch with my changes.
The reason why I want to make this change is that glDrawPixels and glReadPixels are horribly slow on radeon cards, they take a few secounds for a 1024x768 image. The current code doesn't work for the open source driver at any color depth(mesa software acceleration doesn't work eighter), and it's broken for some color depths with the fglrx driver.
On 13/02/06, Stefan Dösinger stefandoesinger@gmx.at wrote:
Hello, I'm trying to change IWineD3DSurface::UnlockRect for rendertargets to avoid glDrawPixels. Instead, I'd like to load the image from memory into an OpenGL texture, and draw that texture with a textured quad onto the front / back buffer.
The problem I have is that the texture(or better, the resulting image) only has a solid color: The color of the first pixel in the source memory. I've read the texture section of the GL programming guide, but I didn't find a solution. I've attached a patch with my changes.
The reason why I want to make this change is that glDrawPixels and glReadPixels are horribly slow on radeon cards, they take a few secounds for a 1024x768 image. The current code doesn't work for the open source driver at any color depth(mesa software acceleration doesn't work eighter), and it's broken for some color depths with the fglrx driver.
I've only had a quick look, so I may have overlooked it, but were do you bind the texture?
H. Verbeet <hverbeet <at> gmail.com> writes:
On 13/02/06, Stefan Dösinger <stefandoesinger <at> gmx.at> wrote:
Hello, I'm trying to change IWineD3DSurface::UnlockRect for rendertargets to avoid glDrawPixels. Instead, I'd like to load the image from memory into an OpenGL texture, and draw that texture with a textured quad onto the front / back buffer.
I've only had a quick look, so I may have overlooked it, but were do you bind the texture?
Indeed, from looking at the patch you will need to call glGenTextures, then glBindTexture. Something like the following should. However if you anticipate the texture target getting rebound overtime, you will have to maintain the texture ID so you can rebind it with glBindTexture() before each call to glTexSubImage2D.
glGenTextures(1, &This->texture_id); checkGLcall("glGenTextures");
glBindTexture(GL_TEXTURE_2D, This->texture_id); checkGLcall("glBindTexture");
glTexImage2D(GL_TEXTURE_2D, 0, D3DFmt2GLIntFmt(myDevice, This->resource.format), This->pow2Width, This->pow2Height, 0, D3DFmt2GLFmt(myDevice, This->resource.format), D3DFmt2GLType(myDevice, This->resource.format), NULL); checkGLcall("glTexImage2D");
On termination you should cleanup with glDeleteTextures(1, &This->texture_id).
Regards, Aric
Hi,
Indeed, from looking at the patch you will need to call glGenTextures, then glBindTexture. Something like the following should. However if you anticipate the texture target getting rebound overtime, you will have to maintain the texture ID so you can rebind it with glBindTexture() before each call to glTexSubImage2D.
I got a bit delayed by a hard drive crash, but now I've come back to this problem. I added a glGenTextures, glBindTexture before drawing, and a glBindTexture(GL_TEXTURE_2D, 0) and a glDeleteTexture after drawing, but this didn't improve the problem. The texture still has the solid color of the first pixel :(
Another possible problem I've found was that I calculated the texture coords with a int / int division. I've typcasted that to float / float, but without any change.
The texture is meant to be used only once, because on the next UnlockRect call on a rendertarget, the app might have changed the whole memory, and I have to re-load the whole locked area
Another possible problem I've found was that I calculated the texture coords with a int / int division. I've typcasted that to float / float, but without any change.
Does hardcoding the the coordinates to (0.0f, 0.0f)-(1.0f, 1.0f) make any difference? Might be a quick way to rule out texture coordinates as a cause.
Does hardcoding the the coordinates to (0.0f, 0.0f)-(1.0f, 1.0f) make any difference? Might be a quick way to rule out texture coordinates as a cause.
I tried that, doesn't make any difference. I'll do some tests outside wine with glDrawPixels, because I'm not really sure if it's really that slow on my card. Maybe the d3d initialisation drives it into a bad state.
Hi,
I've only had a quick look, so I may have overlooked it, but were do you bind the texture?
Do I need to bind a texture? I create a new texture with glTexImage, upload a texture part with glTexSubImage. AFAIK this should be enought to have the texture available for drawing.
I tried with binding a texture before, but it gave the same results. This was before I knew about the red book, so I might have made other mistakes. I'll check this.
On 14/02/06, Stefan Dösinger stefandoesinger@gmx.at wrote:
Do I need to bind a texture? I create a new texture with glTexImage, upload a texture part with glTexSubImage. AFAIK this should be enought to have the texture available for drawing.
OpenGL needs to know which texture you're operating on. glBindTexture binds a texture to a texturing target, like GL_TEXTURE_2D. If you don't, it's not defined which texture you're operating on, although it could be a texture you've previously bound somewhere else, and glTexImage would overwrite it. glGenTextures is used to allocate texture ids, glDeleteTextures is used to free them again.
Stefan Dösinger wrote:
Hi,
I've only had a quick look, so I may have overlooked it, but were do you bind the texture?
Do I need to bind a texture? I create a new texture with glTexImage, upload a texture part with glTexSubImage. AFAIK this should be enought to have the texture available for drawing.
But notice that glTexImage doesn't take any pointers to store the texture. If glTexImage did set its result to the current texture, you would have to recall it everytime you wanted to use that texture again because you couldn't store it. You need to call glBindTexture _before_ calling glTexImage, and _again_ before you start drawing the surface that is going to have that texture on it (assuming that there's the possibility of other things being rendered between when you create the texture with glTexImage and when you plan to actually use it). Make sure you're using glBindTexture in both places if you're not getting any results. Also check the parameters to glTexImage, if they're wrong you usually get no texture at all.