detached 94546f0

chore(deps): pin cef2gtk dmabuf churn

commit
94546f0ee3810084d5588fabd7481b1aabb9136a
author
brice · · 2026-07-14 16:10 UTC
parent
c5ad8c0
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
6 files · +165 -127
M go.mod +1 -1
@@ -7,7 +7,7 @@ require (
77 github.com/andybalholm/brotli v1.2.2
88 github.com/bnema/purego v0.11.0-bnema.4
99 github.com/bnema/purego-cef v0.13.4-0.20260714140305-f0b7414af67e
10- github.com/bnema/purego-cef2gtk v0.8.4
10+ github.com/bnema/purego-cef2gtk v0.8.4-0.20260714160309-bbd397409ebe
1111 github.com/bnema/purego-pipewire v0.1.5-0.20260714124450-6504b9cdf02a
1212 github.com/bnema/purego-sqlite v0.1.4-0.20260714131321-3614fe683b9c
1313 github.com/bnema/puregotk v0.7.0
@@ -7,7 +7,7 @@ require (
7 github.com/andybalholm/brotli v1.2.27 github.com/andybalholm/brotli v1.2.2
8 github.com/bnema/purego v0.11.0-bnema.48 github.com/bnema/purego v0.11.0-bnema.4
9 github.com/bnema/purego-cef v0.13.4-0.20260714140305-f0b7414af67e9 github.com/bnema/purego-cef v0.13.4-0.20260714140305-f0b7414af67e
10- github.com/bnema/purego-cef2gtk v0.8.410+ github.com/bnema/purego-cef2gtk v0.8.4-0.20260714160309-bbd397409ebe
11 github.com/bnema/purego-pipewire v0.1.5-0.20260714124450-6504b9cdf02a11 github.com/bnema/purego-pipewire v0.1.5-0.20260714124450-6504b9cdf02a
12 github.com/bnema/purego-sqlite v0.1.4-0.20260714131321-3614fe683b9c12 github.com/bnema/purego-sqlite v0.1.4-0.20260714131321-3614fe683b9c
13 github.com/bnema/puregotk v0.7.013 github.com/bnema/puregotk v0.7.0
M go.sum +2 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef2gtk/internal/cefadapter/accelerated_paint.go +34 -37 generated file: collapsed
M vendor/github.com/bnema/purego-cef2gtk/internal/dmabuf/frame.go +38 -19 generated file: collapsed
M vendor/github.com/bnema/purego-cef2gtk/internal/gtkgdk/renderer.go +89 -69
@@ -96,29 +96,10 @@ type ownedFrame struct {
9696 SourceSize dmabuf.Size
9797 Format dmabuf.FourCC
9898 Modifier uint64
99- Planes []ownedPlane
99+ Plane ownedPlane
100100 onError func(error)
101101 }
102102
103-func (f *ownedFrame) borrowed() dmabuf.BorrowedFrame {
104- if f == nil {
105- return dmabuf.BorrowedFrame{}
106- }
107- planes := make([]dmabuf.Plane, len(f.Planes))
108- for i, plane := range f.Planes {
109- planes[i] = dmabuf.Plane{FD: plane.FD, Stride: plane.Stride, Offset: plane.Offset, Size: plane.Size}
110- }
111- return dmabuf.BorrowedFrame{
112- CodedSize: f.CodedSize,
113- VisibleRect: f.VisibleRect,
114- ContentRect: f.ContentRect,
115- SourceSize: f.SourceSize,
116- Format: f.Format,
117- Modifier: f.Modifier,
118- Planes: planes,
119- }
120-}
121-
122103 // Renderer owns a GtkPicture presenter and imports callback-scoped CEF DMABUFs
123104 // as GdkDmabufTexture instances. The initial implementation supports only
124105 // single-plane RGB frames. Duplicated FDs are handed to GTK with a native
@@ -132,7 +113,9 @@ type Renderer struct {
132113 formats dmabufFormatSet
133114 builder dmabufTextureBuilder
134115 current *ownedTexture
135- retired []*ownedTexture
116+ retired [retiredTextureLimit]*ownedTexture
117+ retiredStart int
118+ retiredCount int
136119 pictureSetPaintable func(*gdk.Texture)
137120 firstTextureSwapMu sync.Mutex
138121 firstTextureSwap func()
@@ -367,11 +350,11 @@ func (r *Renderer) ImportAndQueueAsync(info *cef.AcceleratedPaintInfo, onError f
367350 if r == nil {
368351 return ErrNilRenderer
369352 }
370- frame, err := cefadapter.BorrowedFrameFromAcceleratedPaint(info)
353+ frame, err := cefadapter.SinglePlaneFrameFromAcceleratedPaint(info)
371354 if err != nil {
372355 return err
373356 }
374- owned, err := r.duplicateFrame(frame)
357+ owned, err := r.duplicateSinglePlaneFrame(frame)
375358 if err != nil {
376359 return err
377360 }
@@ -385,11 +368,11 @@ func (r *Renderer) ImportAndQueueAsync(info *cef.AcceleratedPaintInfo, onError f
385368 // on the GTK main loop.
386369 func (r *Renderer) ImportAndQueueOnGTKThread(info *cef.AcceleratedPaintInfo) (queued gtkgl.QueuedFrame, retErr error) {
387370 start := time.Now()
388- frame, err := cefadapter.BorrowedFrameFromAcceleratedPaint(info)
371+ frame, err := cefadapter.SinglePlaneFrameFromAcceleratedPaint(info)
389372 if err != nil {
390373 return gtkgl.QueuedFrame{}, err
391374 }
392- owned, err := r.duplicateFrame(frame)
375+ owned, err := r.duplicateSinglePlaneFrame(frame)
393376 if err != nil {
394377 return gtkgl.QueuedFrame{}, err
395378 }
@@ -535,7 +518,24 @@ func (r *Renderer) importAndSwapOwnedFrame(frame *ownedFrame) error {
535518 return nil
536519 }
537520
538-func (r *Renderer) duplicateFrame(frame dmabuf.BorrowedFrame) (_ *ownedFrame, retErr error) {
521+// duplicateFrame keeps the slice-backed compatibility path for callers outside
522+// the GDK import hot path.
523+func (r *Renderer) duplicateFrame(frame dmabuf.BorrowedFrame) (*ownedFrame, error) {
524+ if err := frame.Validate(); err != nil {
525+ return nil, err
526+ }
527+ return r.duplicateSinglePlaneFrame(dmabuf.SinglePlaneFrame{
528+ CodedSize: frame.CodedSize,
529+ VisibleRect: frame.VisibleRect,
530+ ContentRect: frame.ContentRect,
531+ SourceSize: frame.SourceSize,
532+ Format: frame.Format,
533+ Modifier: frame.Modifier,
534+ Plane: frame.Planes[0],
535+ })
536+}
537+
538+func (r *Renderer) duplicateSinglePlaneFrame(frame dmabuf.SinglePlaneFrame) (_ *ownedFrame, retErr error) {
539539 if r == nil {
540540 return nil, ErrNilRenderer
541541 }
@@ -553,24 +553,19 @@ func (r *Renderer) duplicateFrame(frame dmabuf.BorrowedFrame) (_ *ownedFrame, re
553553 SourceSize: frame.SourceSize,
554554 Format: frame.Format,
555555 Modifier: frame.Modifier,
556- Planes: make([]ownedPlane, len(frame.Planes)),
557- }
558- for i := range owned.Planes {
559- owned.Planes[i].FD = -1
556+ Plane: ownedPlane{FD: -1},
560557 }
561558 defer func() {
562559 if retErr != nil {
563560 r.releaseOwnedFrame(owned)
564561 }
565562 }()
566- for i, plane := range frame.Planes {
567- ownedFD, err := dup(plane.FD)
568- if err != nil {
569- r.recordFDDupFailure()
570- return nil, err
571- }
572- owned.Planes[i] = ownedPlane{FD: ownedFD, Stride: plane.Stride, Offset: plane.Offset, Size: plane.Size}
563+ ownedFD, err := dup(frame.Plane.FD)
564+ if err != nil {
565+ r.recordFDDupFailure()
566+ return nil, err
573567 }
568+ owned.Plane = ownedPlane{FD: ownedFD, Stride: frame.Plane.Stride, Offset: frame.Plane.Offset, Size: frame.Plane.Size}
574569 return owned, nil
575570 }
576571
@@ -584,27 +579,26 @@ func (r *Renderer) buildTextureFromOwnedFrame(frame *ownedFrame) (built *ownedTe
584579 if frame == nil {
585580 return nil, dmabuf.ErrInvalidPlaneFD
586581 }
587- borrowed := frame.borrowed()
588- if err := borrowed.Validate(); err != nil {
582+ if err := frame.validate(); err != nil {
589583 return nil, err
590584 }
591- gdkFormat := gdkTextureFormat(borrowed.Format)
592- if r.formats != nil && !r.formats.Contains(uint32(gdkFormat), borrowed.Modifier) {
585+ gdkFormat := gdkTextureFormat(frame.Format)
586+ if r.formats != nil && !r.formats.Contains(uint32(gdkFormat), frame.Modifier) {
593587 r.recordUnsupportedFormat()
594- return nil, fmt.Errorf("%w: %s as %s modifier 0x%x", ErrUnsupportedFormat, borrowed.Format, gdkFormat, borrowed.Modifier)
588+ return nil, fmt.Errorf("%w: %s as %s modifier 0x%x", ErrUnsupportedFormat, frame.Format, gdkFormat, frame.Modifier)
595589 }
596- r.traceFrame(borrowed, gdkFormat)
590+ r.traceFrame(frame, gdkFormat)
597591 closeFD := r.closeFD
598592 if closeFD == nil {
599593 closeFD = unix.Close
600594 }
601595
602- ownedFD := borrowed.Planes[0].FD
596+ ownedFD := frame.Plane.FD
603597 textureOwnsFD := false
604598 defer func() {
605599 if !textureOwnsFD {
606600 _ = closeFD(ownedFD)
607- frame.Planes[0].FD = -1
601+ frame.Plane.FD = -1
608602 }
609603 }()
610604 destroyNotify, destroyNotifyErr := resolveDestroyNotify()
@@ -613,11 +607,11 @@ func (r *Renderer) buildTextureFromOwnedFrame(frame *ownedFrame) (built *ownedTe
613607 return nil, fmt.Errorf("%w: native close GDestroyNotify unavailable: %w", ErrTextureBuildFailed, destroyNotifyErr)
614608 }
615609
616- plane := borrowed.Planes[0]
617- r.builder.SetWidth(uint(borrowed.CodedSize.Width))
618- r.builder.SetHeight(uint(borrowed.CodedSize.Height))
610+ plane := frame.Plane
611+ r.builder.SetWidth(uint(frame.CodedSize.Width))
612+ r.builder.SetHeight(uint(frame.CodedSize.Height))
619613 r.builder.SetFourcc(uint32(gdkFormat))
620- r.builder.SetModifier(borrowed.Modifier)
614+ r.builder.SetModifier(frame.Modifier)
621615 r.builder.SetPremultiplied(false)
622616 r.builder.SetNPlanes(1)
623617 if r.display != nil {
@@ -653,9 +647,9 @@ func (r *Renderer) buildTextureFromOwnedFrame(frame *ownedFrame) (built *ownedTe
653647 return nil, ErrTextureBuildFailed
654648 }
655649 textureOwnsFD = true
656- frame.Planes[0].FD = -1
650+ frame.Plane.FD = -1
657651 r.recordTextureBuilt()
658- r.traceTexturePresent(borrowed, gdkFormat, texture)
652+ r.traceTexturePresent(frame, gdkFormat, texture)
659653 return &ownedTexture{texture: texture}, nil
660654 }
661655
@@ -698,6 +692,22 @@ func (r *Renderer) releaseOwnedFrame(frame *ownedFrame) {
698692 closeOwnedFrame(frame, closeFD)
699693 }
700694
695+func (f *ownedFrame) validate() error {
696+ if f == nil {
697+ return dmabuf.ErrInvalidPlaneFD
698+ }
699+ return (dmabuf.SinglePlaneFrame{
700+ CodedSize: f.CodedSize,
701+ Format: f.Format,
702+ Plane: dmabuf.Plane{
703+ FD: f.Plane.FD,
704+ Stride: f.Plane.Stride,
705+ Offset: f.Plane.Offset,
706+ Size: f.Plane.Size,
707+ },
708+ }).Validate()
709+}
710+
701711 func closeOwnedFrame(frame *ownedFrame, closeFD func(int) error) {
702712 if frame == nil {
703713 return
@@ -705,11 +715,9 @@ func closeOwnedFrame(frame *ownedFrame, closeFD func(int) error) {
705715 if closeFD == nil {
706716 closeFD = unix.Close
707717 }
708- for i := range frame.Planes {
709- if frame.Planes[i].FD >= 0 {
710- _ = closeFD(frame.Planes[i].FD)
711- frame.Planes[i].FD = -1
712- }
718+ if frame.Plane.FD >= 0 {
719+ _ = closeFD(frame.Plane.FD)
720+ frame.Plane.FD = -1
713721 }
714722 }
715723
@@ -717,25 +725,37 @@ func (r *Renderer) retireOwnedTexture(owned *ownedTexture) {
717725 if r == nil || owned == nil {
718726 return
719727 }
720- r.retired = append(r.retired, owned)
721- for len(r.retired) > retiredTextureLimit {
722- oldest := r.retired[0]
723- copy(r.retired, r.retired[1:])
724- r.retired[len(r.retired)-1] = nil
725- r.retired = r.retired[:len(r.retired)-1]
728+ if r.retiredCount == retiredTextureLimit {
729+ oldest := r.retired[r.retiredStart]
730+ r.retired[r.retiredStart] = owned
731+ r.retiredStart = (r.retiredStart + 1) % retiredTextureLimit
726732 r.releaseOwnedTexture(oldest)
733+ return
734+ }
735+ index := (r.retiredStart + r.retiredCount) % retiredTextureLimit
736+ r.retired[index] = owned
737+ r.retiredCount++
738+}
739+
740+func (r *Renderer) retiredAt(offset int) *ownedTexture {
741+ if r == nil || offset < 0 || offset >= r.retiredCount {
742+ return nil
727743 }
744+ return r.retired[(r.retiredStart+offset)%retiredTextureLimit]
728745 }
729746
730747 func (r *Renderer) releaseRetiredTextures() {
731748 if r == nil {
732749 return
733750 }
734- for _, owned := range r.retired {
735- r.releaseOwnedTexture(owned)
751+ for r.retiredCount > 0 {
752+ index := r.retiredStart
753+ r.releaseOwnedTexture(r.retired[index])
754+ r.retired[index] = nil
755+ r.retiredStart = (r.retiredStart + 1) % retiredTextureLimit
756+ r.retiredCount--
736757 }
737- clear(r.retired)
738- r.retired = nil
758+ r.retiredStart = 0
739759 }
740760
741761 func (r *Renderer) releaseOwnedTexture(owned *ownedTexture) {
@@ -762,11 +782,11 @@ func gdkTextureFormat(format dmabuf.FourCC) dmabuf.FourCC {
762782 }
763783 }
764784
765-func (r *Renderer) traceFrame(frame dmabuf.BorrowedFrame, gdkFormat dmabuf.FourCC) {
785+func (r *Renderer) traceFrame(frame *ownedFrame, gdkFormat dmabuf.FourCC) {
766786 if os.Getenv("PUREGO_CEF2GTK_GDK_TRACE") == "" || r == nil || r.frameTraces.Add(1) > 8 {
767787 return
768788 }
769- plane := frame.Planes[0]
789+ plane := frame.Plane
770790 fmt.Fprintf(os.Stderr,
771791 "cef2gtk-gdk-dmabuf frame coded=%dx%d visible=%dx%d+%d+%d content=%dx%d+%d+%d source=%dx%d cef_format=%s gdk_format=%s modifier=0x%x fd=%d stride=%d offset=%d size=%d\n",
772792 frame.CodedSize.Width, frame.CodedSize.Height,
@@ -776,7 +796,7 @@ func (r *Renderer) traceFrame(frame dmabuf.BorrowedFrame, gdkFormat dmabuf.FourC
776796 frame.Format, gdkFormat, frame.Modifier, plane.FD, plane.Stride, plane.Offset, plane.Size)
777797 }
778798
779-func (r *Renderer) traceTexturePresent(frame dmabuf.BorrowedFrame, gdkFormat dmabuf.FourCC, texture *gdk.Texture) {
799+func (r *Renderer) traceTexturePresent(frame *ownedFrame, gdkFormat dmabuf.FourCC, texture *gdk.Texture) {
780800 if os.Getenv("PUREGO_CEF2GTK_GDK_TRACE") == "" || r == nil || r.textureTraces.Add(1) > 8 {
781801 return
782802 }
@@ -96,29 +96,10 @@ type ownedFrame struct {
96 SourceSize dmabuf.Size96 SourceSize dmabuf.Size
97 Format dmabuf.FourCC97 Format dmabuf.FourCC
98 Modifier uint6498 Modifier uint64
99- Planes []ownedPlane99+ Plane ownedPlane
100 onError func(error)100 onError func(error)
101 }101 }
102 102
103-func (f *ownedFrame) borrowed() dmabuf.BorrowedFrame {
104- if f == nil {
105- return dmabuf.BorrowedFrame{}
106- }
107- planes := make([]dmabuf.Plane, len(f.Planes))
108- for i, plane := range f.Planes {
109- planes[i] = dmabuf.Plane{FD: plane.FD, Stride: plane.Stride, Offset: plane.Offset, Size: plane.Size}
110- }
111- return dmabuf.BorrowedFrame{
112- CodedSize: f.CodedSize,
113- VisibleRect: f.VisibleRect,
114- ContentRect: f.ContentRect,
115- SourceSize: f.SourceSize,
116- Format: f.Format,
117- Modifier: f.Modifier,
118- Planes: planes,
119- }
120-}
121-
122 // Renderer owns a GtkPicture presenter and imports callback-scoped CEF DMABUFs103 // Renderer owns a GtkPicture presenter and imports callback-scoped CEF DMABUFs
123 // as GdkDmabufTexture instances. The initial implementation supports only104 // as GdkDmabufTexture instances. The initial implementation supports only
124 // single-plane RGB frames. Duplicated FDs are handed to GTK with a native105 // single-plane RGB frames. Duplicated FDs are handed to GTK with a native
@@ -132,7 +113,9 @@ type Renderer struct {
132 formats dmabufFormatSet113 formats dmabufFormatSet
133 builder dmabufTextureBuilder114 builder dmabufTextureBuilder
134 current *ownedTexture115 current *ownedTexture
135- retired []*ownedTexture116+ retired [retiredTextureLimit]*ownedTexture
117+ retiredStart int
118+ retiredCount int
136 pictureSetPaintable func(*gdk.Texture)119 pictureSetPaintable func(*gdk.Texture)
137 firstTextureSwapMu sync.Mutex120 firstTextureSwapMu sync.Mutex
138 firstTextureSwap func()121 firstTextureSwap func()
@@ -367,11 +350,11 @@ func (r *Renderer) ImportAndQueueAsync(info *cef.AcceleratedPaintInfo, onError f
367 if r == nil {350 if r == nil {
368 return ErrNilRenderer351 return ErrNilRenderer
369 }352 }
370- frame, err := cefadapter.BorrowedFrameFromAcceleratedPaint(info)353+ frame, err := cefadapter.SinglePlaneFrameFromAcceleratedPaint(info)
371 if err != nil {354 if err != nil {
372 return err355 return err
373 }356 }
374- owned, err := r.duplicateFrame(frame)357+ owned, err := r.duplicateSinglePlaneFrame(frame)
375 if err != nil {358 if err != nil {
376 return err359 return err
377 }360 }
@@ -385,11 +368,11 @@ func (r *Renderer) ImportAndQueueAsync(info *cef.AcceleratedPaintInfo, onError f
385 // on the GTK main loop.368 // on the GTK main loop.
386 func (r *Renderer) ImportAndQueueOnGTKThread(info *cef.AcceleratedPaintInfo) (queued gtkgl.QueuedFrame, retErr error) {369 func (r *Renderer) ImportAndQueueOnGTKThread(info *cef.AcceleratedPaintInfo) (queued gtkgl.QueuedFrame, retErr error) {
387 start := time.Now()370 start := time.Now()
388- frame, err := cefadapter.BorrowedFrameFromAcceleratedPaint(info)371+ frame, err := cefadapter.SinglePlaneFrameFromAcceleratedPaint(info)
389 if err != nil {372 if err != nil {
390 return gtkgl.QueuedFrame{}, err373 return gtkgl.QueuedFrame{}, err
391 }374 }
392- owned, err := r.duplicateFrame(frame)375+ owned, err := r.duplicateSinglePlaneFrame(frame)
393 if err != nil {376 if err != nil {
394 return gtkgl.QueuedFrame{}, err377 return gtkgl.QueuedFrame{}, err
395 }378 }
@@ -535,7 +518,24 @@ func (r *Renderer) importAndSwapOwnedFrame(frame *ownedFrame) error {
535 return nil518 return nil
536 }519 }
537 520
538-func (r *Renderer) duplicateFrame(frame dmabuf.BorrowedFrame) (_ *ownedFrame, retErr error) {521+// duplicateFrame keeps the slice-backed compatibility path for callers outside
522+// the GDK import hot path.
523+func (r *Renderer) duplicateFrame(frame dmabuf.BorrowedFrame) (*ownedFrame, error) {
524+ if err := frame.Validate(); err != nil {
525+ return nil, err
526+ }
527+ return r.duplicateSinglePlaneFrame(dmabuf.SinglePlaneFrame{
528+ CodedSize: frame.CodedSize,
529+ VisibleRect: frame.VisibleRect,
530+ ContentRect: frame.ContentRect,
531+ SourceSize: frame.SourceSize,
532+ Format: frame.Format,
533+ Modifier: frame.Modifier,
534+ Plane: frame.Planes[0],
535+ })
536+}
537+
538+func (r *Renderer) duplicateSinglePlaneFrame(frame dmabuf.SinglePlaneFrame) (_ *ownedFrame, retErr error) {
539 if r == nil {539 if r == nil {
540 return nil, ErrNilRenderer540 return nil, ErrNilRenderer
541 }541 }
@@ -553,24 +553,19 @@ func (r *Renderer) duplicateFrame(frame dmabuf.BorrowedFrame) (_ *ownedFrame, re
553 SourceSize: frame.SourceSize,553 SourceSize: frame.SourceSize,
554 Format: frame.Format,554 Format: frame.Format,
555 Modifier: frame.Modifier,555 Modifier: frame.Modifier,
556- Planes: make([]ownedPlane, len(frame.Planes)),556+ Plane: ownedPlane{FD: -1},
557- }
558- for i := range owned.Planes {
559- owned.Planes[i].FD = -1
560 }557 }
561 defer func() {558 defer func() {
562 if retErr != nil {559 if retErr != nil {
563 r.releaseOwnedFrame(owned)560 r.releaseOwnedFrame(owned)
564 }561 }
565 }()562 }()
566- for i, plane := range frame.Planes {563+ ownedFD, err := dup(frame.Plane.FD)
567- ownedFD, err := dup(plane.FD)564+ if err != nil {
568- if err != nil {565+ r.recordFDDupFailure()
569- r.recordFDDupFailure()566+ return nil, err
570- return nil, err
571- }
572- owned.Planes[i] = ownedPlane{FD: ownedFD, Stride: plane.Stride, Offset: plane.Offset, Size: plane.Size}
573 }567 }
568+ owned.Plane = ownedPlane{FD: ownedFD, Stride: frame.Plane.Stride, Offset: frame.Plane.Offset, Size: frame.Plane.Size}
574 return owned, nil569 return owned, nil
575 }570 }
576 571
@@ -584,27 +579,26 @@ func (r *Renderer) buildTextureFromOwnedFrame(frame *ownedFrame) (built *ownedTe
584 if frame == nil {579 if frame == nil {
585 return nil, dmabuf.ErrInvalidPlaneFD580 return nil, dmabuf.ErrInvalidPlaneFD
586 }581 }
587- borrowed := frame.borrowed()582+ if err := frame.validate(); err != nil {
588- if err := borrowed.Validate(); err != nil {
589 return nil, err583 return nil, err
590 }584 }
591- gdkFormat := gdkTextureFormat(borrowed.Format)585+ gdkFormat := gdkTextureFormat(frame.Format)
592- if r.formats != nil && !r.formats.Contains(uint32(gdkFormat), borrowed.Modifier) {586+ if r.formats != nil && !r.formats.Contains(uint32(gdkFormat), frame.Modifier) {
593 r.recordUnsupportedFormat()587 r.recordUnsupportedFormat()
594- return nil, fmt.Errorf("%w: %s as %s modifier 0x%x", ErrUnsupportedFormat, borrowed.Format, gdkFormat, borrowed.Modifier)588+ return nil, fmt.Errorf("%w: %s as %s modifier 0x%x", ErrUnsupportedFormat, frame.Format, gdkFormat, frame.Modifier)
595 }589 }
596- r.traceFrame(borrowed, gdkFormat)590+ r.traceFrame(frame, gdkFormat)
597 closeFD := r.closeFD591 closeFD := r.closeFD
598 if closeFD == nil {592 if closeFD == nil {
599 closeFD = unix.Close593 closeFD = unix.Close
600 }594 }
601 595
602- ownedFD := borrowed.Planes[0].FD596+ ownedFD := frame.Plane.FD
603 textureOwnsFD := false597 textureOwnsFD := false
604 defer func() {598 defer func() {
605 if !textureOwnsFD {599 if !textureOwnsFD {
606 _ = closeFD(ownedFD)600 _ = closeFD(ownedFD)
607- frame.Planes[0].FD = -1601+ frame.Plane.FD = -1
608 }602 }
609 }()603 }()
610 destroyNotify, destroyNotifyErr := resolveDestroyNotify()604 destroyNotify, destroyNotifyErr := resolveDestroyNotify()
@@ -613,11 +607,11 @@ func (r *Renderer) buildTextureFromOwnedFrame(frame *ownedFrame) (built *ownedTe
613 return nil, fmt.Errorf("%w: native close GDestroyNotify unavailable: %w", ErrTextureBuildFailed, destroyNotifyErr)607 return nil, fmt.Errorf("%w: native close GDestroyNotify unavailable: %w", ErrTextureBuildFailed, destroyNotifyErr)
614 }608 }
615 609
616- plane := borrowed.Planes[0]610+ plane := frame.Plane
617- r.builder.SetWidth(uint(borrowed.CodedSize.Width))611+ r.builder.SetWidth(uint(frame.CodedSize.Width))
618- r.builder.SetHeight(uint(borrowed.CodedSize.Height))612+ r.builder.SetHeight(uint(frame.CodedSize.Height))
619 r.builder.SetFourcc(uint32(gdkFormat))613 r.builder.SetFourcc(uint32(gdkFormat))
620- r.builder.SetModifier(borrowed.Modifier)614+ r.builder.SetModifier(frame.Modifier)
621 r.builder.SetPremultiplied(false)615 r.builder.SetPremultiplied(false)
622 r.builder.SetNPlanes(1)616 r.builder.SetNPlanes(1)
623 if r.display != nil {617 if r.display != nil {
@@ -653,9 +647,9 @@ func (r *Renderer) buildTextureFromOwnedFrame(frame *ownedFrame) (built *ownedTe
653 return nil, ErrTextureBuildFailed647 return nil, ErrTextureBuildFailed
654 }648 }
655 textureOwnsFD = true649 textureOwnsFD = true
656- frame.Planes[0].FD = -1650+ frame.Plane.FD = -1
657 r.recordTextureBuilt()651 r.recordTextureBuilt()
658- r.traceTexturePresent(borrowed, gdkFormat, texture)652+ r.traceTexturePresent(frame, gdkFormat, texture)
659 return &ownedTexture{texture: texture}, nil653 return &ownedTexture{texture: texture}, nil
660 }654 }
661 655
@@ -698,6 +692,22 @@ func (r *Renderer) releaseOwnedFrame(frame *ownedFrame) {
698 closeOwnedFrame(frame, closeFD)692 closeOwnedFrame(frame, closeFD)
699 }693 }
700 694
695+func (f *ownedFrame) validate() error {
696+ if f == nil {
697+ return dmabuf.ErrInvalidPlaneFD
698+ }
699+ return (dmabuf.SinglePlaneFrame{
700+ CodedSize: f.CodedSize,
701+ Format: f.Format,
702+ Plane: dmabuf.Plane{
703+ FD: f.Plane.FD,
704+ Stride: f.Plane.Stride,
705+ Offset: f.Plane.Offset,
706+ Size: f.Plane.Size,
707+ },
708+ }).Validate()
709+}
710+
701 func closeOwnedFrame(frame *ownedFrame, closeFD func(int) error) {711 func closeOwnedFrame(frame *ownedFrame, closeFD func(int) error) {
702 if frame == nil {712 if frame == nil {
703 return713 return
@@ -705,11 +715,9 @@ func closeOwnedFrame(frame *ownedFrame, closeFD func(int) error) {
705 if closeFD == nil {715 if closeFD == nil {
706 closeFD = unix.Close716 closeFD = unix.Close
707 }717 }
708- for i := range frame.Planes {718+ if frame.Plane.FD >= 0 {
709- if frame.Planes[i].FD >= 0 {719+ _ = closeFD(frame.Plane.FD)
710- _ = closeFD(frame.Planes[i].FD)720+ frame.Plane.FD = -1
711- frame.Planes[i].FD = -1
712- }
713 }721 }
714 }722 }
715 723
@@ -717,25 +725,37 @@ func (r *Renderer) retireOwnedTexture(owned *ownedTexture) {
717 if r == nil || owned == nil {725 if r == nil || owned == nil {
718 return726 return
719 }727 }
720- r.retired = append(r.retired, owned)728+ if r.retiredCount == retiredTextureLimit {
721- for len(r.retired) > retiredTextureLimit {729+ oldest := r.retired[r.retiredStart]
722- oldest := r.retired[0]730+ r.retired[r.retiredStart] = owned
723- copy(r.retired, r.retired[1:])731+ r.retiredStart = (r.retiredStart + 1) % retiredTextureLimit
724- r.retired[len(r.retired)-1] = nil
725- r.retired = r.retired[:len(r.retired)-1]
726 r.releaseOwnedTexture(oldest)732 r.releaseOwnedTexture(oldest)
733+ return
734+ }
735+ index := (r.retiredStart + r.retiredCount) % retiredTextureLimit
736+ r.retired[index] = owned
737+ r.retiredCount++
738+}
739+
740+func (r *Renderer) retiredAt(offset int) *ownedTexture {
741+ if r == nil || offset < 0 || offset >= r.retiredCount {
742+ return nil
727 }743 }
744+ return r.retired[(r.retiredStart+offset)%retiredTextureLimit]
728 }745 }
729 746
730 func (r *Renderer) releaseRetiredTextures() {747 func (r *Renderer) releaseRetiredTextures() {
731 if r == nil {748 if r == nil {
732 return749 return
733 }750 }
734- for _, owned := range r.retired {751+ for r.retiredCount > 0 {
735- r.releaseOwnedTexture(owned)752+ index := r.retiredStart
753+ r.releaseOwnedTexture(r.retired[index])
754+ r.retired[index] = nil
755+ r.retiredStart = (r.retiredStart + 1) % retiredTextureLimit
756+ r.retiredCount--
736 }757 }
737- clear(r.retired)758+ r.retiredStart = 0
738- r.retired = nil
739 }759 }
740 760
741 func (r *Renderer) releaseOwnedTexture(owned *ownedTexture) {761 func (r *Renderer) releaseOwnedTexture(owned *ownedTexture) {
@@ -762,11 +782,11 @@ func gdkTextureFormat(format dmabuf.FourCC) dmabuf.FourCC {
762 }782 }
763 }783 }
764 784
765-func (r *Renderer) traceFrame(frame dmabuf.BorrowedFrame, gdkFormat dmabuf.FourCC) {785+func (r *Renderer) traceFrame(frame *ownedFrame, gdkFormat dmabuf.FourCC) {
766 if os.Getenv("PUREGO_CEF2GTK_GDK_TRACE") == "" || r == nil || r.frameTraces.Add(1) > 8 {786 if os.Getenv("PUREGO_CEF2GTK_GDK_TRACE") == "" || r == nil || r.frameTraces.Add(1) > 8 {
767 return787 return
768 }788 }
769- plane := frame.Planes[0]789+ plane := frame.Plane
770 fmt.Fprintf(os.Stderr,790 fmt.Fprintf(os.Stderr,
771 "cef2gtk-gdk-dmabuf frame coded=%dx%d visible=%dx%d+%d+%d content=%dx%d+%d+%d source=%dx%d cef_format=%s gdk_format=%s modifier=0x%x fd=%d stride=%d offset=%d size=%d\n",791 "cef2gtk-gdk-dmabuf frame coded=%dx%d visible=%dx%d+%d+%d content=%dx%d+%d+%d source=%dx%d cef_format=%s gdk_format=%s modifier=0x%x fd=%d stride=%d offset=%d size=%d\n",
772 frame.CodedSize.Width, frame.CodedSize.Height,792 frame.CodedSize.Width, frame.CodedSize.Height,
@@ -776,7 +796,7 @@ func (r *Renderer) traceFrame(frame dmabuf.BorrowedFrame, gdkFormat dmabuf.FourC
776 frame.Format, gdkFormat, frame.Modifier, plane.FD, plane.Stride, plane.Offset, plane.Size)796 frame.Format, gdkFormat, frame.Modifier, plane.FD, plane.Stride, plane.Offset, plane.Size)
777 }797 }
778 798
779-func (r *Renderer) traceTexturePresent(frame dmabuf.BorrowedFrame, gdkFormat dmabuf.FourCC, texture *gdk.Texture) {799+func (r *Renderer) traceTexturePresent(frame *ownedFrame, gdkFormat dmabuf.FourCC, texture *gdk.Texture) {
780 if os.Getenv("PUREGO_CEF2GTK_GDK_TRACE") == "" || r == nil || r.textureTraces.Add(1) > 8 {800 if os.Getenv("PUREGO_CEF2GTK_GDK_TRACE") == "" || r == nil || r.textureTraces.Add(1) > 8 {
781 return801 return
782 }802 }
M vendor/modules.txt +1 -1 generated file: collapsed

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close