<div dir="ltr"><div class="gmail_extra">I would abstract all platform specific code. I define a encapsulating set of interfaces for any platform specific stuff. Interface types also provide a nice layer of abstraction.</div><div class="gmail_extra"><br></div><div class="gmail_extra">In such a way I have at least IDocument, IBitmap, IAudio, and IVideo; where the last three type define methods for loading and decompressing images, audio, and video frames in that order. Then for each platform I map the interfaces to whatever native OS functions work best (or perhaps easiest). On OSX I use the QuickTime objects to decode video and on Linux it would be ffmpeg. On Windows I use MSXML parser, on Linux it would be libxml2 (I use my own libxml wrapper which has better xpath encapsulation), and so on.</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">Interfaces go into standard units such as YourCompany.Graphics, and implementations go into YourCompany.Platform.Darwin.Graphics or YourCompany.Platform.Linux.Graphics. Then in code I only reference YourCompany.Graphics, which has code like this:  </div><div><br></div><div>unit YourCompany.Graphics;<br></div><div><br></div><div>type IBitmap = interface ... end;</div><div><br></div><div>function CreateBitmap(const FileName: string): IBitmap; overload;</div><div><div>function CreateBitmap(Stream: TStream): IBitmap; overload;</div></div><div><br></div></div><div class="gmail_extra">So then to your example. In my engine I have a TTextures asset manager class (exposed as a singleton):</div><div class="gmail_extra"><br></div><div class="gmail_extra">TTextures = class(TAssetManager)</div><div class="gmail_extra">  procedure Add(const FileName: string; const Name: string); overload;</div><div class="gmail_extra">  procedure Add(Stream: TStream; const Name: string); overload;</div><div class="gmail_extra"><div class="gmail_extra">  procedure Bind(const Name: string);</div><div class="gmail_extra">  property Texture[Name: string]: TTexture read GetTexture; default;</div><div class="gmail_extra">  ...</div><div><br></div><div>function Textures: TTextures;</div><div><br></div></div><div class="gmail_extra">The actual TTextures.Add methods uses an IBitmap interface which can to load, save, give dimensions, and provide access to pixel data.</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">procedure TTextures.Add(Stream: TStream; const Name: string);</div><div class="gmail_extra">var</div><div class="gmail_extra">  B: IBitmap;</div><div class="gmail_extra">  T: Texture;</div><div class="gmail_extra">begin</div><div class="gmail_extra">  if Texture[Name] <> nil then Exit;</div><div class="gmail_extra">  B := CreateBitmap(Stream);</div><div class="gmail_extra">  T := TTexture.Create;</div><div class="gmail_extra">  T.Name := Name;</div><div class="gmail_extra">  T.Width := B.Width;</div><div class="gmail_extra">  T.Height := B.Height;</div><div class="gmail_extra">  glGenTextures(1, @T.FId);</div><div class="gmail_extra">  // B.Pixels has the pixel data which will be freed with the interface<br></div><div class="gmail_extra">  ...</div><div class="gmail_extra">end;</div><div class="gmail_extra"></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">You get the idea I hope. </div><div class="gmail_extra"><br></div><div class="gmail_extra">For stuff which might need a different implementation on platforms: define interfaces.</div><div class="gmail_extra">For stuff which is unaffected by platforms, encapsulate that using types like records, classes, enums, and sets.</div><div class="gmail_extra"><br></div></div>