205 lines
6.3 KiB
C++
205 lines
6.3 KiB
C++
/**************************************************************************************************
|
|
* This file is a part of Ultralight. *
|
|
* *
|
|
* See <https://ultralig.ht> for licensing and more. *
|
|
* *
|
|
* (C) 2024 Ultralight, Inc. *
|
|
**************************************************************************************************/
|
|
#pragma once
|
|
#include <Ultralight/Defines.h>
|
|
#include <Ultralight/RefPtr.h>
|
|
#include <Ultralight/Bitmap.h>
|
|
#include <Ultralight/Geometry.h>
|
|
|
|
namespace ultralight {
|
|
|
|
///
|
|
/// User-defined pixel buffer surface.
|
|
///
|
|
/// The library uses this to store pixel data when rendering Views on the CPU (see
|
|
/// ViewConfig::is_accelerated).
|
|
///
|
|
/// You can provide the library with your own Surface implementation to reduce the latency of
|
|
/// displaying pixels in your application (Views will be drawn directly to a block of memory
|
|
/// controlled by you).
|
|
///
|
|
/// When a View is rendered on the CPU, you can retrieve the backing Surface via View::surface().
|
|
///
|
|
/// @pre This is automatically managed for you when using App::Create(), if you want to override
|
|
/// Surface or SurfaceFactory, you'll need to use Renderer::Create() instead.
|
|
///
|
|
/// ## Default Implementation
|
|
///
|
|
/// A default Surface implementation, BitmapSurface, is automatically provided by the library when
|
|
/// you call Renderer::Create() without defining a custom SurfaceFactory.
|
|
///
|
|
/// You should cast the Surface to a BitmapSurface to access the underlying Bitmap.
|
|
///
|
|
/// ## Setting the Surface Implementation
|
|
///
|
|
/// To define your own 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::set_surface_factory() before calling 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.
|
|
///
|
|
/// @note 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:
|
|
/// <pre>
|
|
/// 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();
|
|
/// }
|
|
/// </pre>
|
|
///
|
|
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_;
|
|
};
|
|
|
|
///
|
|
/// User-defined factory to provide your own surface implementation.
|
|
///
|
|
/// The library uses this to create/destroy Surface instances when rendering Views on the CPU.
|
|
///
|
|
/// @pre This is automatically managed for you when using App::Create(), if you want to override
|
|
/// Surface or SurfaceFactory, you'll need to use Renderer::Create() instead.
|
|
///
|
|
/// ## Setting the Surface Factory
|
|
///
|
|
/// 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.
|
|
///
|
|
/// This is automatically provided by the library when you call Renderer::Create() without defining
|
|
/// a custom SurfaceFactory.
|
|
///
|
|
/// This implementation uses a Bitmap to store pixel data (retrieve it via BitmapSurface::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> 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
|