views:

88

answers:

2

In my application (Delphi 2010, OpenGL, windows XP), I need to read back the pixels of variable portions of the framebuffer.

The area of interest is input by the user through a selection rectangle (x1, y1, x2, y2).

With this coordinates I do this:

var
  pixels : PGLUByte; //pointer to unsigned bytes

begin       

 [Transformation of coordinates to Opengl viewport offsets]

 //reserve a block of memory for readpixels to write to
 ReallocMem(pixels, width * height* sizeof(GLUByte)*3); //<<< crash on this line after a few iterations
 if not assigned(pixels) then exit;
 //read the pixels
 glReadPixels(startx, viewport[3] - (starty+height), 
             width , height, 
             GL_RGB, GL_UNSIGNED_BYTE, 
             pixels);

 //Processing of the pixel data follows here...

 //when done, release the memory
 ReallocMem(pixels, 0);
end;

This function seems to work as intended at the first few tries, but after a few calls to it, the application crashes with an Access violation at $0000000 on the first ReallocMem.

I tried using Getmem, Finalize and Freemem, but these functions lead to the same behaviour.

Is my design principially correct? I tried to debug it, but i could not identify the cause of trouble. width and height always have plausible values, and allocating 5-10 blocks of 30 to 120 KiB should not be an issue on a machine with 3 GB of RAM.

Update

Between the calls to this function, The render pipeline might Draw a few frames, objects may be added to the scene - in principle anything the application is capable of, as this function is called when the user decided to select a rectangular portion of my scene for capture through dragging a seelction box over my Canvas.

Here is a sample of widths and heights from a debug session of mine

  1. width : 211 height: 484 size: 306372
  2. width : 162 height: 395 size: 191970
  3. width : 123 height: 275 size: 101475
  4. width : 14 height: 346 size: 14532

The fourth Selection failed in this session. in Other session, more succesive selections were possible, others crashed when trying the second, but none on the first.

Another thing: when I comment out glReadPixels, no more crashes appear.

+1  A: 

Do you initialize pixels to nil?

begin
  pixels := nil;
  ...

Do you allocate enough memory? This example

  • allocates nWidth + 1, nHeight + 1
  • mentions that OpenGL might align memory to 4 bytes by default (see GL_PACK_ALIGNMENT).
TOndrej
Good idea - but yes, i do.
sum1stolemyname
+1  A: 

I found it after all.

My calculation for width and height were of by one, so i needed to change my reallocmem-line to

ReallocMem(pixels, (width+1) * (height+1) * sizeof(GLUByte)*3);

Thank you for you consideration

sum1stolemyname
this means that width and height are, for instance, 127? This is awkward. I guess you should keep width*height in realloc, it's more intuitive. Anyway, in SO one can accept one's own answer, isn't it ?
Calvin1602
You are right. This was just a quickhack fix. I shall modify my calculation of width and heigth to reflect this.I'll have to wait until August 28th till I an accept my own answer, though.
sum1stolemyname