unit X11_XImages; // FIXME DeleteUnderlyingObject // FIXME public properties for Width, Height. Common base class together with X11_Pixmaps? {$MODE OBJFPC} {$M+} interface uses X11_Objects, xlib, X11, type_fixes, x, framebuffers; type TXImage = class(system.TObject) // (X11_Objects.TObject, IXImage, X11_Objects.IObject, IInterface) private fImage : PXImage; fBOwnsImage : Boolean; fDisplay : PDisplay; fFramebufferInfo : TFramebufferInfo; protected // function GetBytesPerLineCount : TCardinal; // fImage^.bytes_per_line; procedure UpdateFramebufferInfo; public destructor Destroy(); override; published constructor CreateSHM(aDisplay : PDisplay; const aVisual : IVisual; const aSHMSegment : ISHMSegment;aData : Pointer; aWidth, aHeight, aDepth : TCardinal; aFormat : Integer = ZPixmap); // SHM: constructor Create(aDisplay : PDisplay; const aVisual : IVisual; aWidth, aHeight, aDepth : TCardinal; aBitmapPad : Integer; aBytesPerLine : Integer; aFormat : Integer = ZPixmap; aData : Pointer = nil; aOffset : Integer = 0); constructor Reuse(aDisplay : PDisplay; aImage : PXImage; aBOwnsImage : Boolean); function FramebufferInfo : TFramebufferInfoP; public property Display : PDisplay read fDisplay; // property BytesPerLineCount : TCardinal read GetBytesPerLineCount; end; implementation uses xutil, xshm; destructor TXImage.Destroy(); begin if fBOwnsImage then XDestroyImage(fImage); inherited Destroy(); end; constructor TXImage.CreateSHM(aDisplay : PDisplay; const aVisual : IVisual; const aSHMSegment : ISHMSegment; aData : Pointer; aWidth, aHeight, aDepth : TCardinal; aFormat : Integer = ZPixmap); // SHM: var vImage : PXImage; VInfo : TXShmSegmentInfo; begin VInfo.shmseg := aSHMSegment.Handle; VInfo.shmaddr := aSHMSegment.SharedMemory.Address; { TODO? add the other stuff? } VInfo.shmid := aSHMSegment.SharedMemory.ID; VInfo.readonly := LongInt(aSHMSegment.BReadOnly); vImage := XShmCreateImage(aDisplay, aVisual.Handle, aDepth, aFormat, aData, @VInfo, aWidth, aHeight); // TODO handle errors. Reuse(aDisplay, vImage, True); end; constructor TXImage.Create(aDisplay : PDisplay; const aVisual : IVisual; aWidth, aHeight, aDepth : TCardinal; aBitmapPad : Integer; aBytesPerLine : Integer; aFormat : Integer = ZPixmap; aData : Pointer = nil; aOffset : Integer = 0); var vImage : PXImage; begin vImage := XCreateImage(aDisplay, aVisual.Handle, aDepth, aFormat, aOffset, aData, aWidth, aHeight, aBitmapPad, aBytesPerLine); // TODO handle errors. Reuse(aDisplay, vImage, True); end; constructor TXImage.Reuse(aDisplay : PDisplay; aImage : PXImage; aBOwnsImage : Boolean); begin fDisplay := aDisplay; fImage := aImage; fBOwnsImage := aBOwnsImage; UpdateFramebufferInfo(); end; {function TXImage.GetBytesPerLineCount : TCardinal; begin Result := fImage^.bytes_per_line; end;} function TXImage.FramebufferInfo : TFramebufferInfoP; begin Result := @fFramebufferInfo; end; // For all formats, bits_per_pixel is less than or equal to 32. For XY formats, bitmap_unit is 8, 16, 24, or 32 bits. For Z format, bits_per_pixel is 4, 8, 12, 16, 20, 24, 28 or 32 bits. procedure TXImage.UpdateFramebufferInfo; begin // TODO bits_per_pixel, // TODO xoffset (FIXME; this is in pixels, added to our X coord. Just move our starting point and decrease size... // TODO byte_order LSBFirst|MSBFirst // FIXME int bitmap_bit_order; /* LSBFirst, MSBFirst */ // FIXME int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */ // FIXME red_mask, green_mask, blue_mask. // FIXME PixelComponents PixelBitfield with fFramebufferInfo do begin assert(fImage^.format = ZPixmap); Init(pbR8G8B8{FIXME}, fImage^.width, fImage^.height); assert(PixelSize <= fImage^.bitmap_unit); PixelSize := fImage^.bitmap_unit; RowStride := fImage^.bytes_per_line; end; end; // TODO bits_per_pixel end.