0

I need to port some OpenGL code to C# OpenTK. Here is the chunk where I update a mapped PBO from an array of pixels in C++ :

    GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    if(ptr)
    {

        memcpy(ptr,imageInfo.Data,IMG_DATA_SIZE);
        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);  

    }

I need to do the same in OpenTK.My image data comes from an instance of Bitmap. I tried the following:

        IntPtr ptr = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
        if(ptr != IntPtr.Zero)
       {
           BitmapData data = updateColorMap.LockBits(new System.Drawing.Rectangle(0, 0, updateColorMap.Width, updateColorMap.Height),
                 ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                 Marshal.Copy(data.Scan0, 0, ptr, IMG_DATA_SIZE);
       }

But Marshal.Copy requires the first param to be of byte[] type.I didn't find how to retrieve it from the BitmapData.It returns only IntPtr (data.Scan0) .

So how can I get the byte array from the Bitmap?

UPDATE:

In the meantime I got help from the OpenTK forum and they proposed to do this instead:

           unsafe
            {
                GL.BufferData(BufferTarget.PixelUnpackBuffer, new IntPtr(IMG_DATA_SIZE), IntPtr.Zero, BufferUsageHint.StreamDraw);
                byte* ptr = (byte*)GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);


                if (ptr != null)
                {
                    BitmapData data = updateDepthMap.LockBits(new System.Drawing.Rectangle(0, 0, updateDepthMap.Width, updateDepthMap.Height),
                    ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                    byte* scan0 = (byte*)data.Scan0.ToPointer();
                    for (int i = 0; i < IMG_DATA_SIZE; ++i)
                    {

                        *ptr = *scan0;
                        ++ptr;
                        ++scan0;
                    }

                    updateDepthMap.UnlockBits(data);
                    GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);

                }
            }//unsafe

Now,this works,but it is TERRIBLY SLOW! The regular texture update runs 2x faster than this,which is wrong as async PBO transfer should speed up texture uploads.Indeed in my C++ version PBO upload causes almost 2x performance boost.

Michael IV
  • 11,016
  • 12
  • 92
  • 223
  • It should be alright with an IntPtr or I'm missing something, but there is also http://stackoverflow.com/questions/5298930/how-to-get-byte-from-intptr-in-c-sharp – j-p Nov 02 '14 at 20:16
  • Its not all right,it causes compilation error.The first param expects byte[] and not IntPtr – Michael IV Nov 02 '14 at 21:14

1 Answers1

-1

Ok so the solution is here: Copy data from from IntPtr to IntPtr

tested on linux.

Community
  • 1
  • 1
j-p
  • 1,622
  • 10
  • 18
  • Buffer out of range.But I double checked all the buffers have the same size. – Michael IV Nov 03 '14 at 11:36
  • try maybe to set first IntPtr as array like this: 'Marshal.Copy(new IntPtr[]{data.Scan0},0, ptr, IMG_DATA_SIZE);' a loop on all your pixel is very slow, normal.... – j-p Nov 03 '14 at 11:50
  • I've tried, that was not what I guessed. But have a look here: http://stackoverflow.com/questions/15975972/copy-data-from-from-intptr-to-intptr, if you have nothing against pinvoke, it should solve nicely your problem. – j-p Nov 03 '14 at 12:08
  • I thought Marshal.copy would concatenate IntPtr array contents into the destination IntPtr, but I was wrong. – j-p Nov 03 '14 at 12:15