Sign in to follow this  

LockRect problem

This topic is 4162 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Alright, I rolled my own font system for my game. It loads a texture from a custom file with all the font characters on it. I make a vertex buffer for each character and pull out the character from the texture by its uv coords. I have to manually copy data into the texture, and this is where I am having some problems. I can only get it to work under certain conditions. Here is the relevant code:

D3DFORMAT Format = D3DFMT_A1R5G5B5;//D3DFMT_A8R8G8B8;

//Here I check width, height, and format to make sure it is supported

if (FAILED(hr = m_pD3DDevice->CreateTexture(TextureWidth,TextureHeight,1,0/*D3DUSAGE_DYNAMIC*/,Format,
	D3DPOOL_MANAGED/*D3DPOOL_DEFAULT*/,&m_pFontTexture,NULL)))
{
	return 1;
}

int a = 0, r = 0, g = 0, b = 0;
GetBitsForFormat(Format,&a,&r,&g,&b);
int NumberOfBytesInFormat = (a+r+g+b)/8;
if (NumberOfBytesInFormat!=1 && NumberOfBytesInFormat!=2 && NumberOfBytesInFormat!=3 && NumberOfBytesInFormat!=4)
	return 1;

D3DLOCKED_RECT LockedTexture = {0};
if (FAILED(m_pFontTexture->LockRect(0,&LockedTexture,NULL,NULL)))
{
	return 1;
}

char* pTData = reinterpret_cast<char*>(LockedTexture.pBits);

for (int y = 0; y < TextureHeight; y++)
	for (int x = 0; x < TextureWidth; x++)
		for (int i = 0; i < NumberOfBytesInFormat; i++)
			pTData[(y*(LockedTexture.Pitch/4)+x)*NumberOfBytesInFormat+i] = 0;

if (FAILED(m_pFontTexture->UnlockRect(0)))
	return 1;

As the code is now, it crashes in UnlockRect, as in, it freezes my computer and then gives me an access violation at 0x00000000. I checked and m_pFontTexture should be valid. When I comment out my four lines that zero out all the texture data, the crash doesn't happen. I casted the bits to a char array so I could support multiple formats. Changing to D3DFMT_A8R8G8B8, everything works. Keeping the format, and using dynamic textures in the default pool, everything works. On my old computer, the best format I can get is D3DFMT_A1R5G5B5, and it doesn't support dynamic textures. I know this has to work somehow because I can use D3DXCreateTextureFromFileEx and successfully render textures formed from bitmaps on the old computer. I'm out of ideas, I can't figure out how to get around this. Does anyone have any ideas of what might be happening? -Dev578

Share this post


Link to post
Share on other sites
pTData[(y*(LockedTexture.Pitch/4)+x)*NumberOfBytesInFormat+i] = 0;

is wrong because of the parenthesis, also do you need the / 4? isn't pitch int bytes? If you do need the / 4 then just move this:

pTData[(y*(LockedTexture.Pitch/4)+x*NumberOfBytesInFormat)+i] = 0;

also setting values byte by byte can be inefficient. You could try using zeromemory on a line at a time.

Share this post


Link to post
Share on other sites
You are dividing Pitch (number of bytes per row) by 4, so with A8R8G8B8 (32b/4B) it works, but with A1R5G5B5 (16b/2B) it doesn't.

So switching the 4 to NumberOfBytesInFormat would work, or you could modify the line to
pTData[(y*LockedTexture.Pitch)+x*NumberOfBytesInFormat+i] = 0;

Share this post


Link to post
Share on other sites
Alright, that makes logical sense. It is (sort of) able to zero out the texture, it goes out of bounds as is now. I am having another problem filling in the data with actual colors. My problem still lies with the D3DFMT_A1R5G5B5 format. Since there are only 5 bits of each color (and one of alpha), what I do is try to pack the data into a DWORD (A value that supports the largest color format I will be using), and pull it out as different char's (A value that supports the smallest color format I will be using). This is probably much easier said in code:


//Zero out the texture (I know, I will switch over to zeromemory once I get it working this way
//If I let ArrayPos get any higher, unlockrect crashes
int ArrayPos = 0;
for (int y = 0; y < TextureHeight; y++)
for (int x = 0; x <TextureWidth; x++)
for (int i = 0; i < NumberOfBytesInFormat; i++)
{
ArrayPos = (y*LockedTexture.Pitch) + (x*NumberOfBytesInFormat) + i;
if (ArrayPos < TextureHeight*LockedTexture.Pitch+65)
pTData[ArrayPos] = 0;
}
//this code is called for every character, I am just trying to get it to be a solid color to show that this method works, it doesn't
//hardcoded for the D3DFMT_A1R5G5B5 format
int Blue = 0, Green = 0, Red = 31, Alpha = 1;
color = (DWORD)Blue;
color += Green << b;
color += Red << (b+g);
color += Alpha << (b+g+r);

for (int i = 0; i < NumberOfBytesInFormat; i++)
pTData[(y*LockedTexture.Pitch) + (x*NumberOfBytesInFormat) + i] = (char)(color >> (i*8));

//Notes: color is a DWORD, LockedTexture.Pitch is 512, TextureWidth and TextureHeight are 256



The above code writes the texture from what I can see entirely see-through, certainly not red. In D3DFMT_A8R8G8B8, changing hardcoded colors to 8 bit values, everything works. Any ideas what is going on here? Your help is appreciated.

Dev578

Share this post


Link to post
Share on other sites
If you use zeromemory() remember pitch can be larger than width*sizeof(pixel).

Why do you have "+65" in your if statement?

You may want to use unsigned for all color manipulations to prevent side effects.

You may want to use a bit-mask:
(char)(color >> (i*8));

would become:
(char)((color>>(i*8))&0xFF);


The bit-mask prevents trying to typecast values larger than your destination.

If you are still having problems, please specify more clearly what issues you currently have.

Share this post


Link to post
Share on other sites
Thank you for your response. I have no idea why I'm adding 65 to the end of the if statement, other than the fact that if I add 66 or more, the program crashes. As for using unsigned values for the color manipulation, that makes sense. The bitmask kind of makes sense, but then again not really. My problem is that certain texture formats aren't even. D3DFMT_A1R5G5B5 has 5 bits for the r, g, and b, these don't evenly fit into my char array obtained from locking the texture. However, when a,r,g, and b are added, they always form an even number of bytes. My idea was to pack this information into a variable big enough to hold it all, then pull it out a char at a time into my array. This doesn't seem to be working at all. Making my data types unsigned doesn't seem to be doing anything, and the bitmask on the color doesn't seem to be doing anything either. ARGGHHHH, the problems that come with compatibility.

-Dev578

Share this post


Link to post
Share on other sites
Your statement of changing the 65 causing the program to crash concerns me. This implies your LockedTexture.Pitch < BytesPerPixel*TextureWidth, which should not be the case.

Do you have DirectX set to run the debug version with maximum error reporting?

So where does your program fail? Do the correct values get calculated to pass back to the texture? Does the texture get all data set to 0?

Please provide whatever additional information you can, as currently there is not enough for me to help.

Share this post


Link to post
Share on other sites

This topic is 4162 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this