question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

WriteableBitmap: doesn't display anything on Linux (and I don't know about other platforms)

See original GitHub issue

Describe the bug

WriteableBitmap doesn’t display anything on Linux. The same code does display an image on Windows. No platform-specific code is used.

To Reproduce Steps to reproduce the behavior:

  1. Clone this repo: https://github.com/OpenRakis/Spice86
  2. Grab a supported DOS game, like Dune or Prince of Persia
  3. Run it with the following command line
Spice86 -e /path/to/executable
  1. See a black image.

Expected behavior

The same image should display on every supported platform.

Screenshots

✓ Windows:

image

❌ WSL2 (Ubuntu 20.04) and Xubuntu 20.04 (or any other desktop Linux distro):

image

Same result on a desktop PC with a nvidia GPU, and a laptop with a nvidia GPU.

? - Other platforms

I don’t have a Mac for example.

Desktop (please complete the following information):

  • OS: [Ubuntu 20.04]
  • Version [0.10.13]

Additional context

Here is the code that updates the image, and at the end invalidates the visual on the UI thread (VideoBufferViewModel, view is VideoBufferView.xaml with the associated code-behind file) :


public unsafe void Draw(byte[] memory, Rgb[] palette) {
        if (_disposedValue || UIUpdateMethod is null || Bitmap is null) {
            return;
        }
        int size = Width * Height;
        long endAddress = Address + size;

        if (_appClosing == false) {
            using ILockedFramebuffer buf = Bitmap.Lock();
            uint* dst = (uint*)buf.Address;
            switch (buf.Format) {
                case PixelFormat.Rgba8888:
                    for (long i = Address; i < endAddress; i++) {
                        byte colorIndex = memory[i];
                        Rgb pixel = palette[colorIndex];
                        uint rgba = pixel.ToRgba();
                        dst[i - Address] = rgba;
                    }
                    break;
                case PixelFormat.Bgra8888:
                    for (long i = Address; i < endAddress; i++) {
                        byte colorIndex = memory[i];
                        Rgb pixel = palette[colorIndex];
                        uint argb = pixel.ToArgb();
                        dst[i - Address] = argb;
                    }
                    break;
                default:
                    throw new NotImplementedException($"{buf.Format}");
            }
            Dispatcher.UIThread.Post(() => UIUpdateMethod?.Invoke(), DispatcherPriority.MaxValue);
        }
    }

Both on Linux and Windows, the case being run is always PixelFormat.Bgra8888.

Using another pixel format (pixel.ToRgba, or pixel.ToBgra) only breaks the Windows use case.

Using random values does display something, so bindings and invalidation are OK.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ahoppercommented, Mar 31, 2022
unsafe
  {
      fixed(uint* pPallete = pallete)
      fixed (byte* pBuffer = buffer)
      {
          byte* src = pBuffer;
          uint* pal = pPallete;
          using (var pixels = bm.Lock())
          {
              uint* p0 = (uint*)pixels.Address;
              int stride = pixels.RowBytes / 4;

              for (int y = 0; y < h; y++)
              {
                  uint* p = p0 + y * stride;
                  byte* endp = src + w;
                  while (src < endp)
                  {
                      var val = *src++;
                      *p++ = *(pal+val);
                  }
              }
          }
      }
  }
0reactions
maximilien-noalcommented, Mar 31, 2022

Corrected on my end.

Previously I was able to reproduce this issue with WSL2 and the proprietary nvidia driver.

The issue doesn’t manifest itself anymore with this new code:


    public unsafe void Draw(byte[] memory, Rgb[] palette) {
        if (_appClosing || _disposedValue || UIUpdateMethod is null || Bitmap is null) {
            return;
        }
        int size = Width * Height;
        long endAddress = Address + size;

        using ILockedFramebuffer pixels = Bitmap.Lock();
        uint* firstPixelAddress = (uint*)pixels.Address;
        int rowBytes = Width;
        long memoryAddress = Address;
        uint* currentRow = firstPixelAddress;
        for(int row = 0; row < Height; row++) {
            uint* startOfLine = currentRow;
            uint* endOfLine = currentRow + Width;
            for(uint* column = startOfLine; column < endOfLine; column++) {
                byte colorIndex = memory[memoryAddress];
                Rgb pixel = palette[colorIndex];
                uint argb = pixel.ToArgb();
                if(pixels.Format == PixelFormat.Rgba8888) {
                    argb = pixel.ToRgba();
                }
                *column = argb;
                memoryAddress++;
            }
            currentRow += rowBytes;
        }
        if (!IsDrawing) {
            IsDrawing = true;
        }
        Dispatcher.UIThread.Post(() => UIUpdateMethod?.Invoke(), DispatcherPriority.MaxValue);
    }

it also still works on Windows and on Linux with the nouveau driver for nvidia hardware.

https://github.com/OpenRakis/Spice86/pull/85

Issue closed. Thank you !

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - WriteableBitmap doesn't render on Linux but works on ...
WriteableBitmap doesn't render on Linux but works on UWP and Wasm ; Class · "test.Uno.MainPage" ; "http://schemas.microsoft.com/winfx/2006/xaml/ ...
Read more >
WriteableBitmap Class (System.Windows.Media.Imaging)
The WriteableBitmap class uses two buffers. The back buffer is allocated in system memory and accumulates content that is not currently displayed. The...
Read more >
Silverlight 3 – The Bitmap API / WriteableBitmap
Silverlight 3 introduces the new Bitmap API useful for accomplishing three primary goals:Creation of a bitmap completely from scratch, ...
Read more >
UWP x64 Release Compilation Variation
I wrote a program, part of which does compositing for display. When I run the program under x64-Release compilation the composited overlays ...
Read more >
Skbitmap to maui image. You can find the source code for ...
Resize with all of the different SKBitmapResizeMethods, but it doesn't resize it. at SkiaSharp. Assembly; using (Stream stream = assembly.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found