/// /// @file Surface.h /// /// @brief The header for the Surface and SurfaceFactory interfaces. /// /// @author /// /// This file is a part of Ultralight, a next-generation HTML renderer. /// /// Website: /// /// Copyright (C) 2022 Ultralight, Inc. All rights reserved. /// #pragma once #include #include #include #include namespace ultralight { /// /// Offscreen pixel buffer surface. (Premultiplied BGRA 32-bit format) /// /// When using the CPU renderer, each View is painted to its own Surface. /// /// You can provide your own Surface implementation to make the renderer paint directly to a block /// of memory controlled by you (this is useful for lower-latency uploads to GPU memory or other /// platform-specific bitmaps). /// /// A default Surface implementation, BitmapSurface, is automatically provided by the library when /// you call Renderer::Create() without defining a custom SurfaceFactory. /// /// To provide your own custom Surface implementation, you should inherit from this class, handle /// the virtual member functions, and then define a custom SurfaceFactory that creates/destroys an /// instance of your class. After that, you should pass an instance of your custom SurfaceFactory /// class to `Platform::instance().set_font_loader()` before calling App::Create() or /// Renderer::Create(). /// class UExport Surface { public: virtual ~Surface(); /// /// Width (in pixels). /// virtual uint32_t width() const = 0; /// /// Height (in pixels). /// virtual uint32_t height() const = 0; /// /// Number of bytes between rows (usually width * 4) /// virtual uint32_t row_bytes() const = 0; /// /// Size in bytes. /// virtual size_t size() const = 0; /// /// Lock the pixel buffer and get a pointer to the beginning of the data for reading/writing. /// /// Native pixel format is premultiplied BGRA 32-bit (8 bits per channel). /// virtual void* LockPixels() = 0; /// /// Unlock the pixel buffer. /// virtual void UnlockPixels() = 0; /// /// Resize the pixel buffer to a certain width and height (both in pixels). /// /// This should never be called while pixels are locked. /// virtual void Resize(uint32_t width, uint32_t height) = 0; /// /// Set the dirty bounds to a certain value. /// /// This is called after the Renderer paints to an area of the pixel buffer. (The new value will /// be joined with the existing dirty_bounds()) /// virtual void set_dirty_bounds(const IntRect& bounds); /// /// Get the dirty bounds. /// /// This value can be used to determine which portion of the pixel buffer has been updated since /// the last call to ClearDirtyBounds(). /// /// The general algorithm to determine if a Surface needs display is: ///
  ///   if (!surface.dirty_bounds().IsEmpty()) {
  ///       // Surface pixels are dirty and needs display.
  ///       // Cast Surface to native Surface and use it here (pseudo code)
  ///       DisplaySurface(surface);
  ///
  ///       // Once you're done, clear the dirty bounds:
  ///       surface.ClearDirtyBounds();
  ///  }
  ///  
/// virtual IntRect dirty_bounds() const; /// /// Clear the dirty bounds. /// /// You should call this after you're done displaying the Surface. /// virtual void ClearDirtyBounds(); protected: Surface(); IntRect dirty_bounds_; }; /// /// SurfaceFactory can be used to provide your own native Surface implementation. /// /// This can be used to wrap a platform-specific GPU texture, Windows DIB, macOS CGImage, or any /// other pixel buffer target for display on screen. /// /// The default factory creates/destroys a BitmapSurface but you can override this by providing your /// own factory to Platform::set_surface_factory. /// class UExport SurfaceFactory { public: virtual ~SurfaceFactory(); /// /// Create a native Surface with a certain width and height (in pixels). /// virtual Surface* CreateSurface(uint32_t width, uint32_t height) = 0; /// /// Destroy a native Surface previously created by CreateSurface(). /// virtual void DestroySurface(Surface* surface) = 0; }; /// /// The default Surface implementation, backed by a Bitmap. /// class UExport BitmapSurface : public Surface { public: virtual uint32_t width() const override; virtual uint32_t height() const override; virtual uint32_t row_bytes() const override; virtual size_t size() const override; virtual void* LockPixels() override; virtual void UnlockPixels() override; virtual void Resize(uint32_t width, uint32_t height) override; /// /// Get the underlying Bitmap. /// RefPtr bitmap(); protected: BitmapSurface(uint32_t width, uint32_t height); virtual ~BitmapSurface(); BitmapSurface(const BitmapSurface&) = delete; void operator=(const BitmapSurface&) = delete; friend class BitmapSurfaceFactory; void* impl_; }; /// /// Get the default Bitmap Surface Factory singleton. (Do not destroy this, this singleton is owned /// by the library). /// UExport SurfaceFactory* GetBitmapSurfaceFactory(); } // namespace ultralight