unit Framebuffer; interface uses UNIXtype; {$PACKRECORDS C} { from Linux 2.6.26.2 } type { Interpretation of offset for color fields: All offsets are from the right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you can use the offset as right argument to <<). A pixel afterwards is a bit stream and is written to video memory as that unmodified. This implies big-endian byte order if bits_per_pixel is greater than 8. } TBitfield = record { C } offset : cuint32; { beginning of bitfield } length : cuint32; { length of bitfield } msb_right : cuint32; { != 0 : Most significant bit is right } end; TBitfieldP = ^TBitfield; TActivateFlag = (acDeferUntilNextOpen, acTest, acDeferUntilNextVBL = 4, acChangeCmapOnNextVBL = 5, acAll = 6, acForce{even when no change} = 7, acInvalidateVideomode = 8); TActivateFlags = set of TActivateFlag; //#define FB_ACTIVATE_MASK 15 TVariableScreeninfo = record { C } xres : cuint32; { visible resolution } yres : cuint32; xres_virtual : cuint32; { virtual resolution } yres_virtual : cuint32; xoffset : cuint32; { offset from virtual to visible } yoffset : cuint32; { resolution } bits_per_pixel : cuint32; { guess what } grayscale : cuint32; { != 0 Graylevels instead of colors } red, green, blue, transparent : TBitfield; { bitfield in fb mem if true color - else only length is significant. } nonstd : cuint32; { != 0 Non standard pixel format } activate : cuint32; { see FB_ACTIVATE_* } height : cuint32; { height of picture in mm } width : cuint32; { width of picture in mm } accel_flags : cuint32; { (OBSOLETE) see fb_info.flags } { Timing: All values in pixclocks, except pixclock (of course) } pixclock : cuint32; { pixel clock in ps (pico seconds) } left_margin : cuint32; { time from sync to picture } right_margin : cuint32; { time from picture to sync } upper_margin : cuint32; { time from sync to picture } lower_margin : cuint32; hsync_len : cuint32; { length of horizontal sync } vsync_len : cuint32; { length of vertical sync } sync : cuint32; { see FB_SYNC_* } vmode : cuint32; { see FB_VMODE_* } rotate : cuint32; { angle we rotate counter clockwise } reserved_1 : cuint32; { Reserved for future compatibility } reserved_2 : cuint32; { Reserved for future compatibility } reserved_3 : cuint32; { Reserved for future compatibility } reserved_4 : cuint32; { Reserved for future compatibility } reserved_5 : cuint32; { Reserved for future compatibility } end; TVariableScreeninfoP = ^TVariableScreeninfo; TCmap = record { C } start : cuint32; { First entry } len : cuint32; { Number of entries } red : Pcuint16; { Red values } green : Pcuint16; blue : Pcuint16; transp : Pcuint16; { transparency, can be NULL } end; TCmapP = ^TCmap; TCon2fbmap = record { C } console : cuint32; framebuffer : cuint32; end; TCon2fbmapP = ^TCon2fbmap; TType = (ftPackedPixels = 0, ftPlanes = 1, ftInterleavedPlanes = 2, ftText = 3, ftVGAPlanes = 4); TVisual = (viMono01, viMono10, viTruecolor, viPseudocolor, viDirectcolor, viStaticPseudocolor); // from C. TFixedScreeninfo = record { C } id : array[0..15] of char; smem_start : culong; { Start of frame buffer mem (physical address). } smem_len : cuint32; { Length of frame buffer mem. } type_ : cuint32; { see "TType". } type_aux : cuint32; { Interleave for interleaved Planes } visual : cuint32; { see TVisual } xpanstep : cuint16; { zero if no hardware panning } ypanstep : cuint16; { zero if no hardware panning } ywrapstep : cuint16; { zero if no hardware ywrap } line_length : cuint32; { length of a line in bytes } mmio_start : culong; { Start of Memory Mapped I/O (physical address). } mmio_len : cuint32; { Length of Memory Mapped I/O. } accel : cuint32; { Indicate to driver which specific chip/card we have } reserved_1 : cuint16; { Reserved for future compatibility } reserved_2 : cuint16; { Reserved for future compatibility } reserved_3 : cuint16; { Reserved for future compatibility } end; TFixedScreeninfoP = ^TFixedScreeninfo; TVblank = record { C } flags, count, vcount, hcount, reserved_1, reserved_2, reserved_3, reserved_4 : cuint32; end; TVblankP = ^TVblank; TCopyarea = record { C } dx, dy, width, height, sx, sy : cuint32; end; TCopyareaP = ^TCopyarea; TFillrect = record { C } dx, dy, width, height, color, rop : cuint32; end; TFillrectP = ^TFillrect; TImage = record { C } dx, dy, width, height : cuint32; fg_color, bg_color : cuint32; depth : Byte; data : Pointer; cmap : TCmap; end; TImageP = ^TImage; TCurpos = record { C } x, y : cuint16; end; TCurposP = ^TCurpos; TCursorField = (cfImage, cfPosition, cfHotSpot, cfCmap, cfShape, cfSize); TCursorFields = set of TCursorField; TCursor = record { C } fields_to_set{TCursorFields}, enable, rop : cuint16; mask : PByte; hot : TCurpos; image : TImage; end; TCursorP = ^TCursor; TIOCTL = ( FBIOGET_VSCREENINFO = $4600, FBIOPUT_VSCREENINFO = $4601, FBIOGET_FSCREENINFO = $4602, FBIOGETCMAP = $4604, FBIOPUTCMAP = $4605, FBIOPAN_DISPLAY = $4606, // ??? FIXME #define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor) FBIOGET_CON2FBMAP = $460F, FBIOPUT_CON2FBMAP = $4610, FBIOBLANK = $4611, // ??? FIXME #define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank) FBIO_ALLOC = $4613, FBIO_FREE = $4614, FBIOGET_GLYPH = $4615, FBIOGET_HWCINFO = $4616, FBIOPUT_MODEINFO = $4617, FBIOGET_DISPINFO = $4818 ); function FormatBitfield(const value : TBitfield) : String; implementation uses BaseUNIX, sysutils; function Test : Integer; var VFD : cint; VVariableScreeninfo : TVariableScreeninfo; VFixedScreeninfo : TFixedScreeninfo; VScreenSize : size_t; VMapped : Pointer; begin VFD := fpopen('/dev/fb0', O_RDWR); if (VFD = -1) then exit(1); if fpioctl(VFD, Integer(FBIOGET_FSCREENINFO), @VFixedScreeninfo) <> 0 then exit(1); // Writeln(TType(VFixedScreeninfo.type_) = ftPackedPixels); { 0. } // Writeln(TVisual(VFixedScreeninfo.visual) = viTruecolor); { 2. } if fpioctl(VFD, Integer(FBIOGET_VSCREENINFO), @VVariableScreeninfo) <> 0 then exit(1); // Writeln(Format('Size: [%d mm x %d mm]', [VVariableScreeninfo.width, VVariableScreeninfo.height])); // -1, -1 // Writeln(VFixedScreeninfo.line_length); // rowstride { 4096. } // no driver in the Linux tree does this and I don't know what it is: assert(VVariableScreeninfo.red.msb_right = 0); assert(VVariableScreeninfo.green.msb_right = 0); assert(VVariableScreeninfo.blue.msb_right = 0); assert(VVariableScreeninfo.transparent.msb_right = 0); { Writeln(Format('red: %s', [FormatBitfield(VVariableScreeninfo.red)])); Writeln(Format('green: %s', [FormatBitfield(VVariableScreeninfo.green)])); Writeln(Format('blue: %s', [FormatBitfield(VVariableScreeninfo.blue)])); Writeln(Format('transparent: %s', [FormatBitfield(VVariableScreeninfo.transparent)])); } VScreenSize := VVariableScreeninfo.xres * VVariableScreeninfo.yres * VVariableScreeninfo.bits_per_pixel div 8; { VFixedScreeninfo.smem_len ? } VMapped := fpMMap(nil, VScreenSize, PROT_READ or PROT_WRITE, MAP_SHARED, VFD, 0); if VMapped = MAP_FAILED then exit(1); fpMUnmap(VMapped, VScreenSize); fpClose(VFD); exit(0); end; function FormatBitfield(const value : TBitfield) : String; begin Exit(Format('(offset: %d, length: %d. msb_right: %d)', [value.offset, value.length, value.msb_right])); end; initialization assert(sizeof(TFixedScreeninfo) = 68); assert(sizeof(TBitfield) = 12); assert(sizeof(TVariableScreeninfo) = 160); assert(sizeof(TCmap) = 24); assert(sizeof(TCon2fbmap) = 8); assert(sizeof(TVblank) = 32); assert(sizeof(TCopyarea) = 24); assert(sizeof(TFillrect) = 24); assert(sizeof(TImage) = 56); assert(sizeof(TCurpos) = 4); assert(sizeof(TCursor) = 72); assert(sizeof(char) = 1); { if Test <> 0 then Halt(1); } end.