Skip to content

Commit

Permalink
Don't use webgl if custom markers are involved
Browse files Browse the repository at this point in the history
  • Loading branch information
mattpap committed Nov 26, 2024
1 parent d8328c1 commit 8ff1898
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 17 deletions.
8 changes: 8 additions & 0 deletions bokehjs/src/lib/core/uniforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@ export function min(u: Uniform<number>): number {
export function max(u: Uniform<number>): number {
return u.is_Scalar() ? u.value : arrayable.max((u as UniformVector<number>).array)
}

export function some<T>(u: Uniform<T>, predicate: (item: T) => boolean): boolean {
return u.is_Scalar() ? predicate(u.value) : arrayable.some((u as UniformVector<T>).array, predicate)
}

export function every<T>(u: Uniform<T>, predicate: (item: T) => boolean): boolean {
return u.is_Scalar() ? predicate(u.value) : arrayable.every((u as UniformVector<T>).array, predicate)
}
27 changes: 21 additions & 6 deletions bokehjs/src/lib/models/glyphs/glyph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,13 @@ export abstract class GlyphView extends DOMComponentView {

async load_glglyph?(): Promise<typeof BaseGLGlyph>

get has_webgl(): boolean {
return this.glglyph != null
has_webgl(): this is {glglyph: BaseGLGlyph} {
return this.glglyph != null && this._can_use_webgl
}

private _can_use_webgl: boolean = false
protected _compute_can_use_webgl(): boolean {
return true
}

private _index: SpatialIndex | null = null
Expand Down Expand Up @@ -119,7 +124,7 @@ export abstract class GlyphView extends DOMComponentView {
}

paint(ctx: Context2d, indices: number[], data?: Partial<Glyph.Data>): void {
if (this.glglyph != null) {
if (this.has_webgl()) {
this.glglyph.render(ctx, indices, this.base ?? this)
} else if (this.canvas.webgl != null && settings.force_webgl) {
throw new Error(`${this} doesn't support webgl rendering`)
Expand Down Expand Up @@ -358,7 +363,9 @@ export abstract class GlyphView extends DOMComponentView {
visual.update()
}

this.glglyph?.set_visuals_changed()
if (this.has_webgl()) {
this.glglyph.set_visuals_changed()
}
}

protected _transform_array<T>(prop: p.BaseCoordinateSpec<T>, array: Arrayable<unknown>) {
Expand Down Expand Up @@ -439,7 +446,13 @@ export abstract class GlyphView extends DOMComponentView {
decoration.marking.set_data(source, indices)
}

this.glglyph?.set_data_changed()
if (this.glglyph != null) {
this._can_use_webgl = this._compute_can_use_webgl()
}

if (this.has_webgl()) {
this.glglyph.set_data_changed()
}

if (base == null) {
this.index_data()
Expand Down Expand Up @@ -506,7 +519,9 @@ export abstract class GlyphView extends DOMComponentView {
}

this._map_data()
this.glglyph?.set_data_mapped()
if (this.has_webgl()) {
this.glglyph.set_data_mapped()
}
}

// This is where specs not included in coords are computed, e.g. radius.
Expand Down
4 changes: 3 additions & 1 deletion bokehjs/src/lib/models/glyphs/hex_tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ export class HexTileView extends GlyphView {
this._define_attr<HexTile.Data>("svy", svy)

// From overridden GlyphView.map_data()
this.glglyph?.set_data_mapped()
if (this.has_webgl()) {
this.glglyph.set_data_mapped()
}
}

protected _get_unscaled_vertices(): [Vertices, Vertices] {
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/glyphs/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class ImageView extends ImageBaseView {
}

protected _update_image(): void {
if (this.glglyph != null) {
if (this.has_webgl()) {
this.glglyph.set_image_changed()
}

Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/glyphs/image_stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class ImageStackView extends ImageBaseView {
}

protected _update_image(): void {
if (this.glglyph != null) {
if (this.has_webgl()) {
this.glglyph.set_image_changed()
}

Expand Down
9 changes: 7 additions & 2 deletions bokehjs/src/lib/models/glyphs/scatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import {marker_funcs} from "./defs"
import type {VectorVisuals} from "./defs"
import type {Rect, KeyVal} from "core/types"
import * as p from "core/properties"
import * as u from "core/uniforms"
import type {Context2d} from "core/util/canvas"
import type {MultiMarkerGL} from "./webgl/multi_marker"
import {CustomJS} from "../callbacks/customjs"
import {execute_sync} from "core/util/callbacks"
import type {SyncExecutableLike} from "core/util/callbacks"
import {dict} from "core/util/object"
import {dict, is_empty} from "core/util/object"

function is_MarkerType(type: string): type is MarkerType {
function is_MarkerType(type: string | null): type is MarkerType {
return MarkerType.valid(type)
}

Expand All @@ -28,6 +29,10 @@ export class ScatterView extends MarkerView {
return MultiMarkerGL
}

protected override _compute_can_use_webgl(): boolean {
return is_empty(this.model.defs) || u.every(this.marker, is_MarkerType)
}

protected async _update_defs(): Promise<void> {
for (const cb of dict(this.model.defs).values()) {
if (cb instanceof CustomJS) {
Expand Down
9 changes: 5 additions & 4 deletions bokehjs/src/lib/models/glyphs/webgl/multi_marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import {BaseMarkerGL} from "./base_marker"
import type {ReglWrapper} from "./regl_wrap"
import {interleave} from "./webgl_utils"
import type {ScatterView} from "../scatter"
import type {MarkerType} from "core/enums"
import {MarkerType} from "core/enums"
import type {Uniform} from "core/uniforms"
import type {ExtMarkerType} from "core/properties"

export class MultiMarkerGL extends BaseMarkerGL {

// data properties, either all or none are set.
protected _marker_types?: Uniform<MarkerType | null>
protected _marker_types?: Uniform<MarkerType | ExtMarkerType | null>
protected _unique_marker_types: (MarkerType | null)[]

constructor(regl_wrapper: ReglWrapper, override readonly glyph: ScatterView) {
Expand Down Expand Up @@ -85,8 +86,8 @@ export class MultiMarkerGL extends BaseMarkerGL {
this._widths.set_from_prop(this.glyph.size)
this._angles.set_from_prop(this.glyph.angle)

this._marker_types = this.glyph.marker as any // TODO
this._unique_marker_types = [...new Set(this._marker_types)]
this._marker_types = this.glyph.marker
this._unique_marker_types = [...new Set(this._marker_types)].filter((marker) => MarkerType.valid(marker))
}

protected override _set_once(): void {
Expand Down
2 changes: 1 addition & 1 deletion bokehjs/src/lib/models/renderers/glyph_renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ export class GlyphRendererView extends DataRendererView {
}

override get has_webgl(): boolean {
return this.glyph.has_webgl
return this.glyph.has_webgl()
}

protected _paint(ctx: Context2d): void {
Expand Down
24 changes: 23 additions & 1 deletion bokehjs/test/unit/core/uniforms.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {expect} from "assertions"

import {UniformScalar, UniformVector, min, max} from "@bokehjs/core/uniforms"
import {UniformScalar, UniformVector, min, max, some, every} from "@bokehjs/core/uniforms"

describe("core/uniforms", () => {

Expand All @@ -19,4 +19,26 @@ describe("core/uniforms", () => {
expect(max(u0)).to.be.equal(1.1)
expect(max(u1)).to.be.equal(20.2)
})

it("should support some() function", () => {
const u0 = new UniformScalar(1.1, 100)
const u1 = new UniformVector([0, 1.1, -10.2, 10.1, 20.2, 20.1, 2])

expect(some(u0, (v) => v >= 0)).to.be.true
expect(some(u0, (v) => v <= 0)).to.be.false

expect(some(u1, (v) => v >= 0)).to.be.true
expect(some(u1, (v) => v >= 100)).to.be.false
})

it("should support every() function", () => {
const u0 = new UniformScalar(1.1, 100)
const u1 = new UniformVector([0, 1.1, -10.2, 10.1, 20.2, 20.1, 2])

expect(every(u0, (v) => v >= 0)).to.be.true
expect(every(u0, (v) => v <= 0)).to.be.false

expect(every(u1, (v) => v >= 0)).to.be.false
expect(every(u1, (v) => v <= 100)).to.be.true
})
})
4 changes: 4 additions & 0 deletions src/bokeh/models/glyphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,10 @@ def __init__(self, *args, **kwargs) -> None:
Custom marker's names must start with `"@"` prefix, e.g. `"@my_marker"`.
.. note::
Custom markers are only supported with ``"canvas"`` and ``"svg"`` backends.
""")

class Segment(LineGlyph):
Expand Down

0 comments on commit 8ff1898

Please sign in to comment.