render

package
v0.28.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package render provides the integration layer between gg and GPU frameworks.

This package defines the core abstractions for device integration, allowing gg to render to GPU surfaces provided by host applications (like gogpu.App).

Key Principle

gg RECEIVES a GPU device from the host application, it does NOT create its own. This follows the Vello/femtovg/Skia pattern where the rendering library is injected with GPU resources rather than managing them itself.

Core Interfaces

  • DeviceHandle: Provides GPU device access from the host application
  • RenderTarget: Defines where rendering output goes (Pixmap, Texture, Surface)
  • Renderer: Executes drawing commands to a target
  • EventSource: Input events for UI integration (future)

Renderer Implementations

  • SoftwareRenderer: CPU-based rendering using the core/ package
  • GPURenderer: GPU-accelerated rendering (stub for Phase 3)

RenderTarget Implementations

  • PixmapTarget: CPU-backed *image.RGBA target
  • TextureTarget: GPU texture target (stub)
  • SurfaceTarget: Window surface from host (stub)

Usage

Integration with gogpu:

app := gogpu.NewApp(gogpu.Config{...})
var renderer render.Renderer
var scene *Scene
var initialized bool

app.OnDraw(func(dc *gogpu.Context) {
    if !initialized {
        // Get gpucontext.DeviceProvider from gogpu
        provider := app.GPUContextProvider()
        if provider != nil {
            // gg receives GPU device from gogpu (zero overhead)
            renderer, _ = render.NewGPURenderer(provider)

            // Build scene (retained mode)
            scene = NewScene()
            scene.SetFillColor(Red)
            scene.Circle(100, 100, 50)
            scene.Fill()
            initialized = true
        }
    }

    // Render scene to CPU target (GPU targets in Phase 3)
    target := render.NewPixmapTarget(800, 600)
    renderer.Render(target, scene)
})

Software rendering fallback:

// Create CPU-backed target
target := render.NewPixmapTarget(800, 600)

// Create software renderer
renderer := render.NewSoftwareRenderer()

// Render scene
renderer.Render(target, scene)

// Get rendered image
img := target.Image()

Architecture

                 User Application
                       │
      ┌────────────────┼────────────────┐
      │                │                │
      ▼                ▼                ▼
 gogpu.App       gg.Context         gg.Scene
 (windowing)     (immediate)        (retained)
      │                │                │
      └────────────────┼────────────────┘
                       │
                       ▼
               gg/render package
      ┌────────────────┼────────────────┐
      │                │                │
      ▼                ▼                ▼
DeviceHandle     RenderTarget       Renderer
(GPU access)    (output target)   (execution)
      │                │                │
      └────────────────┼────────────────┘
                       │
                       ▼
               gg/core package
               (CPU rasterization)

Thread Safety

Renderers are NOT thread-safe. Each renderer should be used from a single goroutine, or external synchronization must be used.

References

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CapableRenderer

type CapableRenderer interface {
	Renderer

	// Capabilities returns the renderer's capabilities.
	Capabilities() RendererCapabilities
}

CapableRenderer is an optional interface for renderers that can report their capabilities.

type DeviceCapabilities

type DeviceCapabilities struct {
	// MaxTextureSize is the maximum texture dimension supported.
	MaxTextureSize uint32

	// MaxBindGroups is the maximum number of bind groups.
	MaxBindGroups uint32

	// SupportsCompute indicates if compute shaders are supported.
	SupportsCompute bool

	// SupportsStorageTextures indicates if storage textures are supported.
	SupportsStorageTextures bool

	// VendorName is the GPU vendor name.
	VendorName string

	// DeviceName is the GPU device name.
	DeviceName string
}

DeviceCapabilities describes the capabilities of a GPU device. Used to determine available features and limits for rendering decisions.

type DeviceHandle

type DeviceHandle = gpucontext.DeviceProvider

DeviceHandle provides GPU device access from the host application.

This interface is the primary integration point between gg and GPU frameworks like gogpu. The host application (e.g., gogpu.App) implements DeviceHandle and passes it to gg renderers, allowing gg to use the shared GPU device.

Key principle: gg RECEIVES the device from the host, it does NOT create one. This enables:

  • Shared GPU resources between gg and the host application
  • Zero device creation overhead in gg
  • Consistent resource management across the stack

Example implementation in gogpu:

type contextDeviceHandle struct {
    ctx *gogpu.Context
}

func (h *contextDeviceHandle) Device() gpucontext.Device {
    return h.ctx.device
}

func (h *contextDeviceHandle) Queue() gpucontext.Queue {
    return h.ctx.queue
}

DeviceHandle is an alias for gpucontext.DeviceProvider, providing a gg-specific name for the interface while maintaining full compatibility with the gpucontext ecosystem.

type DirtyRect

type DirtyRect struct {
	X, Y, Width, Height float64
}

DirtyRect represents a region that needs redraw. Used for damage tracking to enable efficient partial redraws.

type GPURenderer

type GPURenderer struct {
	// contains filtered or unexported fields
}

GPURenderer is a GPU-accelerated renderer using WebGPU.

This renderer uses the GPU device provided by the host application to perform hardware-accelerated 2D rendering. It leverages compute shaders for path rasterization and the render pipeline for compositing.

Note: This is a stub implementation for Phase 1. Full GPU rendering will be implemented in Phase 3.

Example:

app := gogpu.NewApp(gogpu.Config{...})
var renderer *render.GPURenderer
var initialized bool

app.OnDraw(func(dc *gogpu.Context) {
    if !initialized {
        provider := app.GPUContextProvider()
        if provider != nil {
            renderer, _ = render.NewGPURenderer(provider)
            initialized = true
        }
    }
    // Render scene (CPU target for now, GPU targets in Phase 3)
    target := render.NewPixmapTarget(800, 600)
    renderer.Render(target, scene)
})

func NewGPURenderer

func NewGPURenderer(handle DeviceHandle) (*GPURenderer, error)

NewGPURenderer creates a new GPU-accelerated renderer.

The DeviceHandle must be provided by the host application (e.g., gogpu.App). The renderer does NOT create its own GPU device.

Returns an error if the device handle is invalid or GPU rendering is not supported on this device.

Note: Phase 1 implementation falls back to software rendering.

Example

ExampleNewGPURenderer demonstrates creating a GPU renderer with a DeviceHandle.

In real usage, the DeviceHandle would come from the host application (e.g., gogpu.App.GPUContextProvider()). For testing without a GPU, use NullDeviceHandle.

package main

import (
	"fmt"
	"image/color"

	"github.com/gogpu/gg/render"
)

func main() {
	// Create renderer with null device (for testing without GPU)
	renderer, err := render.NewGPURenderer(render.NullDeviceHandle{})
	if err != nil {
		fmt.Println("failed to create renderer:", err)
		return
	}

	// Create a CPU target for software fallback rendering
	target := render.NewPixmapTarget(100, 100)

	// Create a scene with a red rectangle
	scene := render.NewScene()
	scene.Clear(color.White)
	scene.SetFillColor(color.RGBA{R: 255, G: 0, B: 0, A: 255})
	scene.Rectangle(10, 10, 80, 80)
	scene.Fill()

	// Render the scene (falls back to software in Phase 1)
	if err := renderer.Render(target, scene); err != nil {
		fmt.Println("render failed:", err)
		return
	}

	fmt.Println("rendered successfully")
}
Output:

rendered successfully

func (*GPURenderer) Capabilities

func (r *GPURenderer) Capabilities() RendererCapabilities

Capabilities returns the renderer's capabilities.

Example

ExampleGPURenderer_Capabilities demonstrates querying renderer capabilities.

package main

import (
	"fmt"

	"github.com/gogpu/gg/render"
)

func main() {
	renderer, err := render.NewGPURenderer(render.NullDeviceHandle{})
	if err != nil {
		fmt.Println("failed:", err)
		return
	}

	caps := renderer.Capabilities()
	fmt.Printf("GPU renderer: %v\n", caps.IsGPU)
	fmt.Printf("supports antialiasing: %v\n", caps.SupportsAntialiasing)
}
Output:

GPU renderer: true
supports antialiasing: true

func (*GPURenderer) CreateTextureTarget

func (r *GPURenderer) CreateTextureTarget(width, height int) (*TextureTarget, error)

CreateTextureTarget creates a GPU texture render target.

Note: Phase 1 implementation returns an error. Phase 3 will implement actual texture creation.

func (*GPURenderer) DeviceHandle

func (r *GPURenderer) DeviceHandle() DeviceHandle

DeviceHandle returns the underlying device handle. This allows advanced users to access the GPU device for custom rendering.

func (*GPURenderer) Flush

func (r *GPURenderer) Flush() error

Flush ensures all GPU commands are submitted and complete.

This method:

  • Submits any pending command buffers
  • Waits for GPU completion

For CPU targets, this is a no-op.

func (*GPURenderer) Render

func (r *GPURenderer) Render(target RenderTarget, scene *Scene) error

Render draws the scene to the target.

For GPU targets (TextureView != nil), rendering is performed on the GPU. For CPU targets (Pixels != nil), rendering falls back to software.

Note: Phase 1 implementation always uses software fallback.

type LayeredPixmapTarget

type LayeredPixmapTarget struct {
	// contains filtered or unexported fields
}

LayeredPixmapTarget is a CPU-backed implementation of LayeredTarget. It uses *image.RGBA for each layer and composites them in z-order.

func NewLayeredPixmapTarget

func NewLayeredPixmapTarget(width, height int) *LayeredPixmapTarget

NewLayeredPixmapTarget creates a new layered CPU render target.

func (*LayeredPixmapTarget) Clear

func (t *LayeredPixmapTarget) Clear(c color.Color)

Clear fills the base layer with the given color. Does not affect other layers.

func (*LayeredPixmapTarget) ClearLayer

func (t *LayeredPixmapTarget) ClearLayer(z int, c color.Color) error

ClearLayer fills a specific layer with a color. Returns error if the layer does not exist.

func (*LayeredPixmapTarget) Composite

func (t *LayeredPixmapTarget) Composite()

Composite blends all visible layers onto the base target in z-order. Layers are composited using standard alpha blending (source over).

func (*LayeredPixmapTarget) CreateLayer

func (t *LayeredPixmapTarget) CreateLayer(z int) (RenderTarget, error)

CreateLayer creates a new layer at the specified z-order. Returns a RenderTarget that can be used for drawing to the layer.

func (*LayeredPixmapTarget) Format

Format returns the pixel format (RGBA8).

func (*LayeredPixmapTarget) GetLayer

func (t *LayeredPixmapTarget) GetLayer(z int) RenderTarget

GetLayer returns the RenderTarget for a specific layer. Returns nil if the layer does not exist.

func (*LayeredPixmapTarget) Height

func (t *LayeredPixmapTarget) Height() int

Height returns the target height in pixels.

func (*LayeredPixmapTarget) Image

func (t *LayeredPixmapTarget) Image() *image.RGBA

Image returns the base layer image. Note: This returns the base layer, not the composited result. Call Composite() first, then Image() to get the composited image.

func (*LayeredPixmapTarget) Layers

func (t *LayeredPixmapTarget) Layers() []int

Layers returns all layer z-orders in render order (ascending).

func (*LayeredPixmapTarget) Pixels

func (t *LayeredPixmapTarget) Pixels() []byte

Pixels returns direct access to the base layer pixel data. Note: This returns the base layer, not the composited result. Call Composite() first to get the composited image.

func (*LayeredPixmapTarget) RemoveLayer

func (t *LayeredPixmapTarget) RemoveLayer(z int) error

RemoveLayer removes a layer by z-order.

func (*LayeredPixmapTarget) SetLayerVisible

func (t *LayeredPixmapTarget) SetLayerVisible(z int, visible bool)

SetLayerVisible controls layer visibility.

func (*LayeredPixmapTarget) Stride

func (t *LayeredPixmapTarget) Stride() int

Stride returns the number of bytes per row.

func (*LayeredPixmapTarget) TextureView

func (t *LayeredPixmapTarget) TextureView() TextureView

TextureView returns nil as this is a CPU-only target.

func (*LayeredPixmapTarget) Width

func (t *LayeredPixmapTarget) Width() int

Width returns the target width in pixels.

type LayeredTarget

type LayeredTarget interface {
	RenderTarget

	// CreateLayer creates a new layer at the specified z-order.
	// Higher z values are rendered on top of lower values.
	// Returns an error if a layer with the same z-order already exists.
	CreateLayer(z int) (RenderTarget, error)

	// RemoveLayer removes a layer by z-order.
	// Returns an error if the layer does not exist.
	RemoveLayer(z int) error

	// SetLayerVisible controls layer visibility without removing it.
	// Invisible layers are not composited but retain their content.
	SetLayerVisible(z int, visible bool)

	// Layers returns all layer z-orders in render order (ascending).
	Layers() []int

	// Composite blends all visible layers onto the base target.
	// This should be called after drawing to layers is complete.
	Composite()
}

LayeredTarget supports z-ordered layers for popups, dropdowns, and tooltips.

This interface extends RenderTarget with layer management capabilities. Layers are rendered in ascending z-order (lower z values behind higher ones). This is useful for UI frameworks that need to render overlays without managing separate surfaces.

type NullDeviceHandle

type NullDeviceHandle struct{}

NullDeviceHandle is a DeviceHandle that provides nil implementations. Used for CPU-only rendering where no GPU is available.

Example

ExampleNullDeviceHandle demonstrates the null device for testing.

package main

import (
	"fmt"

	"github.com/gogpu/gg/render"
)

func main() {
	handle := render.NullDeviceHandle{}

	// NullDeviceHandle returns nil for all GPU resources
	fmt.Printf("device: %v\n", handle.Device())
	fmt.Printf("queue: %v\n", handle.Queue())
	fmt.Printf("adapter: %v\n", handle.Adapter())
}
Output:

device: <nil>
queue: <nil>
adapter: <nil>

func (NullDeviceHandle) Adapter

Adapter returns nil for the null device.

func (NullDeviceHandle) Device

Device returns nil for the null device.

func (NullDeviceHandle) Queue

Queue returns nil for the null device.

func (NullDeviceHandle) SurfaceFormat

func (NullDeviceHandle) SurfaceFormat() gputypes.TextureFormat

SurfaceFormat returns undefined format for the null device.

type PixmapTarget

type PixmapTarget struct {
	// contains filtered or unexported fields
}

PixmapTarget is a CPU-backed render target using *image.RGBA.

This target supports software rendering and provides direct pixel access. It is the default target for pure CPU rendering workflows.

Example:

target := render.NewPixmapTarget(800, 600)
renderer.Render(target, scene)
img := target.Image()

func NewPixmapTarget

func NewPixmapTarget(width, height int) *PixmapTarget

NewPixmapTarget creates a new CPU-backed render target.

Example

ExampleNewPixmapTarget demonstrates creating and using a CPU render target.

package main

import (
	"fmt"

	"github.com/gogpu/gg/render"
)

func main() {
	// Create a 400x300 pixel render target
	target := render.NewPixmapTarget(400, 300)

	fmt.Printf("target size: %dx%d\n", target.Width(), target.Height())
	fmt.Printf("stride: %d bytes per row\n", target.Stride())
	fmt.Printf("pixels: %d bytes total\n", len(target.Pixels()))
}
Output:

target size: 400x300
stride: 1600 bytes per row
pixels: 480000 bytes total

func NewPixmapTargetFromImage

func NewPixmapTargetFromImage(img *image.RGBA) *PixmapTarget

NewPixmapTargetFromImage wraps an existing *image.RGBA as a render target. The image is used directly without copying.

func (*PixmapTarget) Clear

func (t *PixmapTarget) Clear(c color.Color)

Clear fills the entire target with the given color.

Example

ExamplePixmapTarget_Clear demonstrates clearing a target with a color.

package main

import (
	"fmt"
	"image/color"

	"github.com/gogpu/gg/render"
)

func main() {
	target := render.NewPixmapTarget(100, 100)

	// Clear to red
	target.Clear(color.RGBA{R: 255, G: 0, B: 0, A: 255})

	// Check a pixel
	pixel := target.GetPixel(50, 50).(color.RGBA)
	fmt.Printf("pixel at (50,50): R=%d, G=%d, B=%d, A=%d\n",
		pixel.R, pixel.G, pixel.B, pixel.A)
}
Output:

pixel at (50,50): R=255, G=0, B=0, A=255

func (*PixmapTarget) Format

func (t *PixmapTarget) Format() gputypes.TextureFormat

Format returns the pixel format (RGBA8).

func (*PixmapTarget) GetPixel

func (t *PixmapTarget) GetPixel(x, y int) color.Color

GetPixel returns the color at the given coordinates.

func (*PixmapTarget) Height

func (t *PixmapTarget) Height() int

Height returns the target height in pixels.

func (*PixmapTarget) Image

func (t *PixmapTarget) Image() *image.RGBA

Image returns the underlying *image.RGBA. The returned image shares memory with the target.

Example

ExamplePixmapTarget_Image demonstrates accessing the underlying image.

package main

import (
	"fmt"
	"image/color"

	"github.com/gogpu/gg/render"
)

func main() {
	target := render.NewPixmapTarget(100, 100)

	// Render something
	renderer := render.NewSoftwareRenderer()
	scene := render.NewScene()
	scene.Clear(color.RGBA{R: 128, G: 128, B: 128, A: 255})

	_ = renderer.Render(target, scene)

	// Get the image for further processing (e.g., saving to file)
	img := target.Image()
	bounds := img.Bounds()
	fmt.Printf("image bounds: %v\n", bounds)
}
Output:

image bounds: (0,0)-(100,100)

func (*PixmapTarget) Pixels

func (t *PixmapTarget) Pixels() []byte

Pixels returns direct access to the pixel data.

func (*PixmapTarget) Resize

func (t *PixmapTarget) Resize(width, height int)

Resize creates a new target with the given dimensions. The contents are not preserved.

func (*PixmapTarget) SetPixel

func (t *PixmapTarget) SetPixel(x, y int, c color.Color)

SetPixel sets a single pixel at the given coordinates.

func (*PixmapTarget) Stride

func (t *PixmapTarget) Stride() int

Stride returns the number of bytes per row.

func (*PixmapTarget) TextureView

func (t *PixmapTarget) TextureView() TextureView

TextureView returns nil as this is a CPU-only target.

func (*PixmapTarget) Width

func (t *PixmapTarget) Width() int

Width returns the target width in pixels.

type RenderTarget

type RenderTarget interface {
	// Width returns the target width in pixels.
	Width() int

	// Height returns the target height in pixels.
	Height() int

	// Format returns the pixel format of the target.
	Format() gputypes.TextureFormat

	// TextureView returns the GPU texture view for this target.
	// Returns nil for CPU-only targets.
	TextureView() TextureView

	// Pixels returns direct access to pixel data.
	// Returns nil for GPU-only targets.
	// For RGBA format, each pixel is 4 bytes: R, G, B, A.
	Pixels() []byte

	// Stride returns the number of bytes per row.
	// For RGBA, this is typically Width * 4, but may include padding.
	Stride() int
}

RenderTarget defines where rendering output goes.

A RenderTarget is an abstraction over different rendering destinations:

  • PixmapTarget: CPU-backed *image.RGBA for software rendering
  • TextureTarget: GPU texture for offscreen rendering
  • SurfaceTarget: Window surface from the host application

Targets may support CPU access (Pixels), GPU access (TextureView), or both. The Renderer implementation chooses the appropriate access method.

type Renderer

type Renderer interface {
	// Render draws the scene to the target.
	//
	// The scene is processed and drawn to the target in order of commands.
	// Returns an error if rendering fails (e.g., incompatible target format).
	//
	// The scene is not modified by this operation and can be rendered
	// multiple times to different targets.
	Render(target RenderTarget, scene *Scene) error

	// Flush ensures all pending rendering operations are complete.
	//
	// For CPU renderers, this is typically a no-op as operations are
	// synchronous. For GPU renderers, this may submit command buffers
	// and wait for completion.
	//
	// Returns an error if flushing fails.
	Flush() error
}

Renderer executes drawing commands to a render target.

The Renderer interface is the primary abstraction for rendering backends. Different implementations provide CPU or GPU rendering:

  • SoftwareRenderer: CPU-based rendering using core/ package algorithms
  • GPURenderer: GPU-accelerated rendering using WebGPU (Phase 3)

Renderers are stateless between Render calls, allowing the same renderer to be used with different targets and scenes.

Thread Safety: Renderers are NOT thread-safe. Each renderer should be used from a single goroutine, or external synchronization must be used.

Example:

// Create renderer
renderer := render.NewSoftwareRenderer()

// Create target
target := render.NewPixmapTarget(800, 600)

// Render scene
if err := renderer.Render(target, scene); err != nil {
    log.Printf("render failed: %v", err)
}

type RendererCapabilities

type RendererCapabilities struct {
	// IsGPU indicates if this is a GPU-accelerated renderer.
	IsGPU bool

	// SupportsAntialiasing indicates if anti-aliased rendering is supported.
	SupportsAntialiasing bool

	// SupportsBlendModes indicates if custom blend modes are supported.
	SupportsBlendModes bool

	// SupportsGradients indicates if gradient fills are supported.
	SupportsGradients bool

	// SupportsTextures indicates if texture sampling is supported.
	SupportsTextures bool

	// MaxTextureSize is the maximum texture dimension (0 = unlimited).
	MaxTextureSize int
}

RendererCapabilities describes the features supported by a renderer.

type Scene

type Scene struct {
	// contains filtered or unexported fields
}

Scene represents a retained-mode drawing tree.

Unlike immediate-mode drawing (Context.DrawCircle, etc.), a Scene captures drawing commands that can be:

  • Rendered multiple times without rebuilding
  • Partially invalidated for efficient UI updates
  • Optimized by the renderer for batching

Scene is designed to work with the Renderer interface, allowing both CPU and GPU rendering backends to process the same scene data.

Example:

scene := render.NewScene()
scene.SetFillColor(color.RGBA{255, 0, 0, 255})
scene.MoveTo(100, 50)
scene.LineTo(150, 150)
scene.LineTo(50, 150)
scene.ClosePath()
scene.Fill()

// Render to any target
renderer.Render(target1, scene)
renderer.Render(target2, scene)
Example

ExampleScene demonstrates building a scene with various drawing commands.

package main

import (
	"fmt"
	"image/color"

	"github.com/gogpu/gg/render"
)

func main() {
	scene := render.NewScene()

	// Clear background
	scene.Clear(color.White)

	// Draw a red triangle
	scene.SetFillColor(color.RGBA{R: 255, G: 0, B: 0, A: 255})
	scene.MoveTo(100, 50)
	scene.LineTo(150, 150)
	scene.LineTo(50, 150)
	scene.ClosePath()
	scene.Fill()

	// Draw a blue circle
	scene.SetFillColor(color.RGBA{R: 0, G: 0, B: 255, A: 255})
	scene.Circle(100, 100, 30)
	scene.Fill()

	// Draw a green rectangle outline
	scene.SetStrokeColor(color.RGBA{R: 0, G: 255, B: 0, A: 255})
	scene.SetStrokeWidth(2.0)
	scene.Rectangle(20, 20, 60, 40)
	scene.Stroke()

	fmt.Printf("scene has %d commands\n", scene.CommandCount())
}
Output:

scene has 4 commands
Example (Damage)

ExampleScene_damage demonstrates damage tracking for efficient redraws.

package main

import (
	"fmt"

	"github.com/gogpu/gg/render"
)

func main() {
	scene := render.NewScene()

	// Initially no dirty regions
	fmt.Printf("has dirty: %v\n", scene.HasDirtyRegions())

	// Invalidate a region
	scene.Invalidate(render.DirtyRect{X: 10, Y: 10, Width: 100, Height: 50})
	fmt.Printf("has dirty: %v\n", scene.HasDirtyRegions())
	fmt.Printf("dirty rects: %d\n", len(scene.DirtyRects()))

	// Clear dirty state after rendering
	scene.ClearDirty()
	fmt.Printf("has dirty after clear: %v\n", scene.HasDirtyRegions())
}
Output:

has dirty: false
has dirty: true
dirty rects: 1
has dirty after clear: false

func NewScene

func NewScene() *Scene

NewScene creates a new empty Scene.

func (*Scene) Circle

func (s *Scene) Circle(cx, cy, r float64)

Circle adds a circle to the current path using cubic Bezier approximation.

func (*Scene) Clear

func (s *Scene) Clear(c color.Color)

Clear adds a clear operation to fill the entire target.

func (*Scene) ClearDirty

func (s *Scene) ClearDirty()

ClearDirty resets the dirty state after rendering. This should be called after each render pass.

func (*Scene) ClosePath

func (s *Scene) ClosePath()

ClosePath closes the current subpath.

func (*Scene) CommandCount

func (s *Scene) CommandCount() int

CommandCount returns the number of drawing commands in the scene.

func (*Scene) CubicTo

func (s *Scene) CubicTo(c1x, c1y, c2x, c2y, x, y float64)

CubicTo draws a cubic Bezier curve.

func (*Scene) DirtyRects

func (s *Scene) DirtyRects() []DirtyRect

DirtyRects returns the accumulated dirty rectangles. Returns nil if the scene needs a full redraw (check NeedsFullRedraw first). The returned slice should not be modified by the caller.

func (*Scene) Fill

func (s *Scene) Fill()

Fill fills the current path and clears it.

func (*Scene) HasDirtyRegions

func (s *Scene) HasDirtyRegions() bool

HasDirtyRegions returns true if there are any dirty regions to redraw. This includes both individual rects and full redraw state.

func (*Scene) Invalidate

func (s *Scene) Invalidate(rect DirtyRect)

Invalidate marks a rectangular region as needing redraw. This is used for damage tracking to enable efficient partial redraws. If the accumulated dirty rects exceed maxDirtyRects, the scene switches to full redraw mode for efficiency.

func (*Scene) InvalidateAll

func (s *Scene) InvalidateAll()

InvalidateAll marks the entire scene as needing redraw. This forces a full redraw on the next render pass.

func (*Scene) IsEmpty

func (s *Scene) IsEmpty() bool

IsEmpty returns true if the scene has no commands.

func (*Scene) LineTo

func (s *Scene) LineTo(x, y float64)

LineTo draws a line from the current point to the given point.

func (*Scene) MoveTo

func (s *Scene) MoveTo(x, y float64)

MoveTo starts a new subpath at the given point.

func (*Scene) NeedsFullRedraw

func (s *Scene) NeedsFullRedraw() bool

NeedsFullRedraw returns true if the scene should be fully redrawn. This is true when InvalidateAll was called or when too many dirty rects have accumulated (more than maxDirtyRects).

func (*Scene) QuadTo

func (s *Scene) QuadTo(cx, cy, x, y float64)

QuadTo draws a quadratic Bezier curve.

func (*Scene) Rectangle

func (s *Scene) Rectangle(x, y, width, height float64)

Rectangle adds a rectangle to the current path.

func (*Scene) Reset

func (s *Scene) Reset()

Reset clears the scene for reuse.

func (*Scene) SetFillColor

func (s *Scene) SetFillColor(c color.Color)

SetFillColor sets the color for subsequent fill operations.

func (*Scene) SetFillRule

func (s *Scene) SetFillRule(rule raster.FillRule)

SetFillRule sets the fill rule for subsequent fill operations.

func (*Scene) SetStrokeColor

func (s *Scene) SetStrokeColor(c color.Color)

SetStrokeColor sets the color for subsequent stroke operations.

func (*Scene) SetStrokeWidth

func (s *Scene) SetStrokeWidth(width float64)

SetStrokeWidth sets the width for subsequent stroke operations.

func (*Scene) Stroke

func (s *Scene) Stroke()

Stroke strokes the current path and clears it.

type SoftwareRenderer

type SoftwareRenderer struct {
	// contains filtered or unexported fields
}

SoftwareRenderer is a CPU-based renderer using the core/ package algorithms.

This renderer provides anti-aliased 2D rendering without any GPU dependencies. It uses AnalyticFiller for high-quality coverage-based anti-aliasing.

Performance characteristics:

  • Single-threaded (future: parallel scanline processing)
  • O(n) where n is the number of pixels covered
  • Memory: O(width) for scanline buffers

Example:

renderer := render.NewSoftwareRenderer()
target := render.NewPixmapTarget(800, 600)
scene := render.NewScene()

scene.SetFillColor(color.RGBA{255, 0, 0, 255})
scene.Circle(400, 300, 100)
scene.Fill()

renderer.Render(target, scene)
img := target.Image()

func NewSoftwareRenderer

func NewSoftwareRenderer() *SoftwareRenderer

NewSoftwareRenderer creates a new CPU-based software renderer.

Example

ExampleNewSoftwareRenderer demonstrates CPU-based software rendering.

package main

import (
	"fmt"
	"image/color"

	"github.com/gogpu/gg/render"
)

func main() {
	// Create software renderer (no GPU required)
	renderer := render.NewSoftwareRenderer()

	// Create a CPU-backed render target
	target := render.NewPixmapTarget(200, 200)

	// Build a scene
	scene := render.NewScene()
	scene.Clear(color.White)
	scene.SetFillColor(color.RGBA{R: 0, G: 0, B: 255, A: 255})
	scene.Circle(100, 100, 50)
	scene.Fill()

	// Render the scene
	if err := renderer.Render(target, scene); err != nil {
		fmt.Println("render failed:", err)
		return
	}

	// Access the rendered image
	img := target.Image()
	fmt.Printf("rendered %dx%d image\n", img.Bounds().Dx(), img.Bounds().Dy())
}
Output:

rendered 200x200 image

func (*SoftwareRenderer) Capabilities

func (r *SoftwareRenderer) Capabilities() RendererCapabilities

Capabilities returns the renderer's capabilities.

Example

ExampleSoftwareRenderer_Capabilities demonstrates querying software renderer capabilities.

package main

import (
	"fmt"

	"github.com/gogpu/gg/render"
)

func main() {
	renderer := render.NewSoftwareRenderer()

	caps := renderer.Capabilities()
	fmt.Printf("GPU renderer: %v\n", caps.IsGPU)
	fmt.Printf("supports antialiasing: %v\n", caps.SupportsAntialiasing)
}
Output:

GPU renderer: false
supports antialiasing: true

func (*SoftwareRenderer) Flush

func (r *SoftwareRenderer) Flush() error

Flush ensures all rendering is complete. For the software renderer, this is a no-op as operations are synchronous.

func (*SoftwareRenderer) Render

func (r *SoftwareRenderer) Render(target RenderTarget, scene *Scene) error

Render draws the scene to the target.

This method processes each drawing command in the scene and renders it to the target using CPU-based rasterization.

Returns an error if the target is GPU-only (no Pixels() support).

type SurfaceTarget

type SurfaceTarget struct {
	// contains filtered or unexported fields
}

SurfaceTarget wraps a window surface from the host application.

This target allows gg to render directly to a window surface provided by gogpu or another host framework. This enables zero-copy rendering where gg draws directly to the display surface.

Note: Full implementation requires GPU backend support (Phase 3).

func NewSurfaceTarget

func NewSurfaceTarget(width, height int, format gputypes.TextureFormat, view TextureView) *SurfaceTarget

NewSurfaceTarget creates a render target from a window surface.

Note: This is a stub. Full implementation in Phase 3 will accept a Surface interface from the host application.

func (*SurfaceTarget) Format

func (t *SurfaceTarget) Format() gputypes.TextureFormat

Format returns the surface pixel format.

func (*SurfaceTarget) Height

func (t *SurfaceTarget) Height() int

Height returns the surface height in pixels.

func (*SurfaceTarget) Pixels

func (t *SurfaceTarget) Pixels() []byte

Pixels returns nil as surfaces do not support CPU access.

func (*SurfaceTarget) Stride

func (t *SurfaceTarget) Stride() int

Stride returns 0 as surfaces do not support CPU access.

func (*SurfaceTarget) TextureView

func (t *SurfaceTarget) TextureView() TextureView

TextureView returns the current frame's texture view.

func (*SurfaceTarget) Width

func (t *SurfaceTarget) Width() int

Width returns the surface width in pixels.

type Texture

type Texture interface {
	// Width returns the texture width in pixels.
	Width() uint32

	// Height returns the texture height in pixels.
	Height() uint32

	// Format returns the texture pixel format.
	Format() gputypes.TextureFormat

	// CreateView creates a view for this texture.
	CreateView() TextureView

	// Destroy releases GPU resources associated with this texture.
	Destroy()
}

Texture represents a GPU texture resource. This interface wraps the underlying WebGPU texture.

type TextureDescriptor

type TextureDescriptor struct {
	// Label is an optional debug label for the texture.
	Label string

	// Width is the texture width in pixels.
	Width uint32

	// Height is the texture height in pixels.
	Height uint32

	// Depth is the texture depth for 3D textures, or array layer count.
	// Use 1 for regular 2D textures.
	Depth uint32

	// MipLevelCount is the number of mipmap levels.
	// Use 1 for no mipmaps.
	MipLevelCount uint32

	// SampleCount is the number of samples for multisampling.
	// Use 1 for no multisampling.
	SampleCount uint32

	// Format is the texture pixel format.
	Format gputypes.TextureFormat

	// Usage specifies how the texture will be used.
	Usage TextureUsage
}

TextureDescriptor describes parameters for creating a texture. This mirrors the WebGPU GPUTextureDescriptor specification.

func DefaultTextureDescriptor

func DefaultTextureDescriptor(width, height uint32, format gputypes.TextureFormat) TextureDescriptor

DefaultTextureDescriptor returns a TextureDescriptor with sensible defaults. Only Width, Height, and Format need to be set.

type TextureTarget

type TextureTarget struct {
	// contains filtered or unexported fields
}

TextureTarget is a GPU texture-backed render target.

This target wraps a GPU texture and allows rendering to offscreen surfaces for post-processing, texture caching, or multi-pass rendering.

Note: Full implementation requires GPU backend support (Phase 3).

func NewTextureTarget

func NewTextureTarget(handle DeviceHandle, width, height int, format gputypes.TextureFormat) (*TextureTarget, error)

NewTextureTarget creates a new GPU texture render target. Requires a DeviceHandle to create the texture.

Note: This is a stub. Full implementation in Phase 3.

func (*TextureTarget) Destroy

func (t *TextureTarget) Destroy()

Destroy releases GPU resources.

func (*TextureTarget) Format

func (t *TextureTarget) Format() gputypes.TextureFormat

Format returns the pixel format.

func (*TextureTarget) Height

func (t *TextureTarget) Height() int

Height returns the target height in pixels.

func (*TextureTarget) Pixels

func (t *TextureTarget) Pixels() []byte

Pixels returns nil as this is a GPU-only target. Use ReadPixels for GPU readback (expensive).

func (*TextureTarget) Stride

func (t *TextureTarget) Stride() int

Stride returns 0 as this is a GPU-only target.

func (*TextureTarget) TextureView

func (t *TextureTarget) TextureView() TextureView

TextureView returns the GPU texture view.

func (*TextureTarget) Width

func (t *TextureTarget) Width() int

Width returns the target width in pixels.

type TextureUsage

type TextureUsage uint32

TextureUsage specifies how a texture can be used. These flags can be combined with bitwise OR.

const (
	// TextureUsageCopySrc allows the texture to be used as a copy source.
	TextureUsageCopySrc TextureUsage = 1 << iota

	// TextureUsageCopyDst allows the texture to be used as a copy destination.
	TextureUsageCopyDst

	// TextureUsageTextureBinding allows the texture to be used in a texture binding.
	TextureUsageTextureBinding

	// TextureUsageStorageBinding allows the texture to be used in a storage binding.
	TextureUsageStorageBinding

	// TextureUsageRenderAttachment allows the texture to be used as a render attachment.
	TextureUsageRenderAttachment
)

type TextureView

type TextureView interface {
	// Destroy releases resources associated with this view.
	Destroy()
}

TextureView represents a view into a texture. Views are used to bind textures to shader stages.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL