Archived

This topic is now archived and is closed to further replies.

Annoying Managed DirectDraw Surface.Lock Bug

This topic is 4988 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

Surface.Lock returns a byte[*,*] array. Writinng to this byte array does not fill the entire surface. I don''t think pitch can really be ussed in this situation since the array has a limit on its dimensions. I have heard of SEVERAL people that have this same problem, and it''s quite frustrating. Is there ANY way at all of direct surface manipulation? When is this expected to be fixed?

Share this post


Link to post
Share on other sites
pitch is always used, no matter what kind of surface you use. if you did not take care of the pitch it's clear you won't be able to fill the screen.

EDIT: Lock does not give back a byte[*,*], it gives back a byte*. look at it like a file which has some predefined gap between lines and not like a thight fitting bitmap.

[edited by - RPTD on March 24, 2004 3:27:48 PM]

Share this post


Link to post
Share on other sites
The version of DirectX 9 I have returns a byte[,]. I am using Managed DirectDraw, and the wrapper somewhat disappoints me. What I meant about pitch is th at the values in the byte array clearly don't match up with the image coordinates, and there is no way to access an index outside of the bounds of the array, which the pitch might suggest.

Here is my code.


byte[,] image;

//Lock the surface

image= surf.Lock(LockFlags.SurfaceMemoryPointer | LockFlags.Wait);

//loop through all of the ys

for(int y=0; y<image.GetUpperBound(1); y++)
{

//and through every x that corresponds to that y

for(int x=0; x<image.GetUpperBound(0); x++)
{
//Just set it to black/

image[x,y]=0;
}
}

//Unlockf

this.surf.Unlock(image);



And I've tried using pitch, and I'll get an OutOfBounds exception I think. I dont fancy much the 2 dimmensional approach that they've taken with this.

[edited by - Muzlack on March 24, 2004 5:13:30 PM]

Share this post


Link to post
Share on other sites
what language and wrapper you use? i personally never use wrappers cause they tend to crank up more than they help. if you can try casting it (clean cast or dirty cast) it to a simple byte pointer and then access it like that (or use mem functions), whatever way you have to access a one dimensional byte data area.

Share this post


Link to post
Share on other sites
I''m using C#, and I''m making my own wrapper. Is it possible to use non-managed DirectX? I''m familiar with C++, and in fact, I''m porting my engine to C#, so if it were possible to use the same data structures etc. that I''m using, that would be cool.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I have had the same problem. From what I am looking at it looks as if it converts whats in memory directly to a 2d array.

The issue is I think IS casting. if you just do a :
Array temp = surfaceSecondary.Lock(LockFlags.SurfaceMemoryPointer);

I produces a 1024,768 array of shorts. Short being the default size of the Array class.

Humm... You know, I wonder what happens if you cast it to long. Maybe, since it gives an Array on the size of the screen, it also depends on the depth of the screen.

Aka, it needs to be an Int32 because my screen is at 32 bits.

I am checking on this.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Still waiting for my regestration information.

Ok, I am using remote desktop, so apperently thats why it was in shorts.

Check this out. Try running the DirectX9 wizard and making a DirectDraw project. Plop this code in and run it though the Quick watch.
// Snip
temp = surfaceSecondary.Lock(LockFlags.SurfaceMemoryPointer);
surfaceSecondary.Unlock(temp);

surfaceSecondary.ColorFill(Color.Yellow); // Change this and see the array values change!

temp = surfaceSecondary.Lock(LockFlags.SurfaceMemoryPointer);
surfaceSecondary.Unlock(temp);

// Snip

It looks like that Lock comamnd just gives a nice raw buffer of the surface. Since I am set up at 16-bit/1024x768 it makes an array of Int16, 1024 long, 768 tall. Only problem is clipping. If your not using full screen, you have to remeber where the clip window is.

Humm. Can''t wait to get home and try this.

Share this post


Link to post
Share on other sites
SOLVED!

temp = surfaceSecondary.Lock(LockFlags.SurfaceMemoryPointer);

for(int x=0;x<1024;x++)
for(int y=0;y<768;y++)
temp.SetValue((int)rnd.Next(16773378),x,y);
surfaceSecondary.Unlock(temp);
// surfaceSecondary.ColorFill(Color.Yellow);

Plug that into the main display routine, and poof, your getting one hell of a show.

You should try it at full screen

Unfornantly its not very fast, but its more of a proof of concept. In fact, I am only using half the colors as, for some stupid reason, it uses int, instead of unsigned int.

Anyway, I am off to figure out how to emulate an Apple 1!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi,

I have been having the same problem for ages what is rnd in the code you suggested

temp.SetValue((int)rnd.Next(16773378),x,y);

Share this post


Link to post
Share on other sites
i''ve also encountered this problem, and to me it seems to be a realy annoying bug. i''ve tried using the array as pointer, while taking into accont the pitch; it didn''t seem to help, but here is the important part:

int stride = back.SurfaceDescription.Pitch;
byte[,] barr = back.LockMicrosoft.DirectX.DirectDraw.LockFlags.SurfaceMemoryPointer );
unsafe
{
fixed (byte* pbdata = barr)
{
for (int j=0; j<100; j++)
{
for (int i=0; i<100; i++)
{
*(pbdata+j*stride+2*i+1) = 0xF8;
}
}
}
}
back.Unlock(barr);

i''m using a 16bit rgb device and this code should paint the surface red (its a 100X100 backbuffer surface called back).

however, it paints half the surface. i''ll be happy to know if this code works for u, and what am i doing wrong

Share this post


Link to post
Share on other sites