Files
Mahdi ramezaan zaade 1f4cb74fae gg: pure-V sgl renderer (gg/render) with CPU rasterizer backend (#31067)
* gg: pure-V sgl renderer (gg/render) with CPU rasterizer backend

* gg: add per-corner rounded rect, 9-slice, CPU output equality test

* gg: add multiply/screen blend modes to renderer and CPU rasterizer

* gg: add multiply/screen to ImageEffect enum

* gg: fix review defects in V renderer (font crash, api break, leaks)

- text_rendering: add FonsRenderTarget allocated before
  fonsCreateInternal, since fontstash calls renderCreate
  synchronously; fixes invalid memory access crash on startup.
  renderUpdate now copies only the dirty atlas region.
- draw: rewrite draw_rounded_rect_filled_4 as a single convex
  triangle strip (removes nonexistent begin_triangle_fan calls
  that broke compilation of any user of the new API, removes
  double-blend overlaps); add clamp_radius/clamp_slice helpers.
- draw_9slice: remove dead slices array/loop, clamp dest slices
  proportionally, use clamped UVs.
- render: do not create pipeline object 5 (quads reuse triangles
  pipeline, matching sgl); push_pipeline uses max_stack_depth-1;
  add is_image_registered/update_image_region/destroy.
- image: register textures once per image; streaming updates
  refresh the CPU copy via update_image_region.
- gg: call ctx.r.destroy() before gfx.shutdown(); drop unused
  gg.render imports; add .vv compile samples for the new APIs.
- flush: pass [4]int dirty rect to validate_texture (was &int,
  heap overwrite causing delayed crash in begin()).

* gg: migrate examples off sokol.sgl to ctx.r

gg no longer submits an sgl context after the pure-V renderer migration, so direct sgl calls in gg examples either failed to typecheck (rotating_textured_quad passed render.Pipeline to sgl.load_pipeline) or silently recorded nothing. Route matrix, pipeline, texture and primitive calls through ctx.r instead.

* x.ttf.render_sokol: draw through ctx.r instead of sgl

draw_text_bmp took ctx &gg.Context but issued its matrix, pipeline, texture and quad calls to sokol.sgl. After the pure-V renderer migration gg no longer submits an sgl context, and the mixed types made the function (and every ttf_font example) fail to compile: cannot use render.Pipeline as sgl.Pipeline in argument 1 to sgl.load_pipeline.

* gg: add a compile-test for all gg based examples

Compiles every examples/gg program, plus breakout, viewer and both ttf_font examples, so examples that keep referencing sokol.sgl directly fail the suite instead of the renderer migration (render.Pipeline is not sgl.Pipeline) going unnoticed. The samples are compiled in parallel with VJOBS-style workers into a private vcache directory.
2026-10-26 05:30:48 +03:00
..
2026-10-12 01:01:13 +03:00
2026-10-12 01:01:13 +03:00
2026-10-12 01:01:13 +03:00
2026-10-12 01:01:13 +03:00
2026-10-12 01:01:13 +03:00

vviewer

Image viewer for V, built with gg/sokol and the pure-V decoders from vlib/image/decoders. No stbi/stb_image is involved: JPEG, PNG, BMP, WEBP, TIFF, and GIF bytes are decoded by our own V code.

Build and run

From this directory:

v run .            # run
v -prod .          # optimized build

A C compiler is required (the sokol backend is C). The viewer renders through the standard sokol backend (OpenGL on Linux, D3D11 on Windows, Metal on macOS); no custom shader compilation is needed.

Usage

Command line — mix files, folders, and zip archives:

viewer img1.jpg img2.bmp folder1 folder2.zip

All folders and zips are scanned for images. You can also start the viewer with no arguments and drag and drop files, folders, or zips onto the window.

Accepted extensions: .jpg, .jpeg, .png, .bmp, .gif, .webp, .tiff, and .zip archives containing them.

Controls

Input Action
ESC / q Quit
right / left Next / previous image
up / down Next / previous folder
F Toggle full screen
R Rotate 90 degrees
I Toggle info text
P Pause / play animation
H Toggle help
1 / 2 / 3 Sort by name / date / as loaded
Mouse wheel Next / previous image
Left mouse button (hold) Pan
Right mouse button (hold) Zoom
Middle mouse button Reset view / fill window

Animation players and their encoded input are released when switching images, including builds with -gc none.

Limitations

  • Animated GIF and animated WEBP are played back frame by frame. APNG files decode, but the viewer shows the static (first) frame only.
  • Multi-page TIFF files show the first page only.
  • 16-bit PNG and 12-bit JPEG are scaled down to 8-bit RGBA for display.
  • Zip archives opened through the bundled miniz library cannot be opened directly from paths with non-ASCII characters on Windows; the viewer works around this by copying the archive to an ASCII-only temp file.
  • The viewer displays images; it does not write or convert them. Use the decoder packages directly for that.