Can anyone explain D3DLOCKED_RECT to me?

Started by
6 comments, last by MJP 15 years ago
I'm currently in the middle of converting a piece of code written in C++/DirectX (not my own) into C#/Managed DirectX and then hopefully on into XNA. I'm not too bad with C#/Managed DirectX, but my C++ is terrible, I'm surprised I've managed as much of this conversion as I have so far! I'm stuck though, I can't for the life of me figure out what the following snippet of code is trying to do. If anyone could explain it to me in plain English it would help me a lot, as then I can emulate it in C#/Managed DirectX myself.
D3DLOCKED_RECT rect;
V( Texture->LockRect( 0, &rect, NULL, D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE ) );
D3DXVECTOR4 * Buffer = (D3DXVECTOR4*)(rect.pBits);
Advertisement
In D3D9 you lock a texture when you want to either readback its contents, or modify its contents. The code you've posted is just a setup for this: it calls LockRect which locks a specific level and portion of the texture (in this case it specifies 0 for the top-level mipmap and NULL as the RECT representing the portion of the texture, which means it will lock the entire surface). LockRect then fills the D3DLOCKED_RECT with some info you need to extract or modify texel data, which is a pointer to the array of texel data and a value specifying the pitch of that data. After this, you would then access that Buffer pointer as an array to access or modify the data.
Okay, let me just see if I've got this right then.

You lock the texture to read it. Which is the first bit.

The second bit specifies that the data in the array (texture) is Vector4s (colors), and then creates a buffer that you can read this data from.

I'm sure what I've said above is partially nonsense, but am at least following along the right lines?
Well that code doesn't actually create the buffer...the LockRect function does that internally and stashes the pointer to that buffer in the D3DLOCKED_RECT. All that last line is doing and taking that buffer and doing a cast to D3DXVECTOR4*, so that it you could access that buffer as an array of D3DXVECTOR4's. You have to do this cast because the buffer pointer in the D3DLOCKED_RECT is of type void*, and you can't do anything with that without casting. This means you have to *know* the format of the texture and cast to the right type in order to extract the proper the data. This also means that this code will only work property for a texture that uses a 32-bit floating point surface format.
Ah. That makes perfect sense. Thanks a lot.

One last thing. What would be the best to go about this in XNA, would it be the GetData and SetData methods? Reading out the whole texture into an array of floats using GetData, then modifying that, and putting it back into the texture with SetData?
Yup, that's exactly what GetData and SetData do. As you've probably already noticed, they're a heck of a lot nicer and easier to use than LockRect. :-P
Yeah, I had noticed that. I was wondering if they were TOO simple though (ie. I wasn't understanding the problem properly).

Thanks a lot for the help, glad I signed up here today.
Well the main reason it's a lot simpler in C# is because it's using generics, so you don't need that ugly casting stuff. You could actually do something similar in C++ using templates, but native D3D9 can't actually use that because it's not a C++ API.

This topic is closed to new replies.

Advertisement