Closed piranna closed 9 years ago
I've modified the simple_fbdev.js script to allow to set the framebuffer device from command line and yes, the problem of not seeing anything on the screen was due to having two framebuffers and two graphic cards on my laptop :-P
The green lines seems to be related to the hardcoded framebuffer configuration, the same way of the gray squares on QEmu :-)
(Now I'm thinking about a Javascript-only backend capable of combine several FBDev devices and create and extended desktop like Xinerama... :-P)
The configuration should be correct. It seems that the stride is messed up. I also had the issue at some point, but somehow managed to fix it on my pc.
The .png files are correct, both for fb0 and fb1. Seems it's related with the screen output only.
Please try 78fffe268b0c7b2b1ac7754eb9a08b5f4fdc3e36, maybe it fixes it.
I have tried it and result is the same :-( Also I've tried to test it on NodeOS on QEmu and it failed due to lack of X11 headers. I'll try to see if I can add a gyp variable to disable it.
Hmm...
I will fix the problem with the headers in https://github.com/ReneHollander/node-canvas/issues/6 in the next days.
Ok, if you need help/beta-testing send me an email ;-) El 05/07/2015 22:27, "Rene Hollander" notifications@github.com escribió:
Hmm...
I will fix the problem with the headers in #6 https://github.com/ReneHollander/node-canvas/issues/6 in the next days.
— Reply to this email directly or view it on GitHub https://github.com/ReneHollander/node-canvas/issues/2#issuecomment-118665456 .
I've changed simple_fbdev.js to paint it at 0,0 and seems like it's eating 24 pixels for each line, since it start to paint the second line at the end of the first one. Also there's a lot more variables, also offsets that maybe should be taken in account...
I will look into the issue, but first have to find a device that produces the error. That will be fun...
01:00.0 VGA compatible controller: NVIDIA Corporation GT216M [GeForce GT 330M](rev a2)
It's a MacBook Pro 6.2 (circa 2012). Hope this helps... :-)
Anyway I'm looking for it myself, too :-)
Confirmed: first line is right, but after that, each one is printed 24 fixels to left, and at the end of the previous row if they move too much to the left. There's a gap of 48 pixels between each row, thought, but I don't believe this would be related to hsync or any other similar low-level thing.... Maybe it's needed to configure it with some kind of offset? Seems there are values both for the real and the visible screen region...
I've been reviewing the code and the FBDev data structures... Shouldn't be used the next one instead of being calculated?
struct fb_fix_screeninfo {
...
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
...
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
...
};
I think mmio_len
is specially useful to define the size of the mmap...
I am now using smem_len
on the branch fixing_fbdev
Cool :+1:
I have been looking info for my problem, according to http://www.ummon.eu/Linux/API/Devices/framebuffer.html seems the line_length entry would be bigger than my real screen size (1680x1050) but data is copied directly from Cairo on the framebuffer memory region. Maybe Cairo surface width should be set to the line_length value? In any case, when painting out of the screen in the gap between rows, the generated file gets a lot of garbage that don't happen when painting in the correct place...
According to http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-image-surface-create-for-data, "Note that the stride may be larger than width*bytes_per_pixel to provide proper alignment for each pixel and row. This alignment is required to allow high-performance rendering within cairo. The correct way to obtain a legal stride value is to call cairo_format_stride_for_width() with the desired format and maximum image width value, and then use the resulting stride value to allocate the data and to create the image surface. See cairo_format_stride_for_width() for example code", I think that my problem could be related to a bad format that makes stride to be 48 pixels smaller...
Can you check the output of fbset --show
again?
Mine is
mode "1920x1080"
geometry 1920 1080 1920 1080 32 <-- This should be the bbp
timings 0 0 0 0 0 0 0
rgba 8/16,8/8,8/0,8/24
endmode
If it's not 32 bbp, try to set it with fbset -depth 32
. Maybe it helps somehow...
I have just tested on another machine and got a similar result:
mode "1366x768"
geometry 1366 768 1920 1080 32
timings 0 0 0 0 0 0 0
accel true
rgba 8/16,8/8,8/0,0/0
endmode
In fact, in this machine the gap between rows seems to be bigger, so probably it's something related to the differences between real visible size vs virtual size (yours are the same).
Please try the following code in a tty:
gcc -o fbdev fbdev.c
./fbdev
#include <linux/fb.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
inline uint32_t pixel_color(uint8_t r, uint8_t g, uint8_t b, struct fb_var_screeninfo *vinfo)
{
return (r<<vinfo->red.offset) | (g<<vinfo->green.offset) | (b<<vinfo->blue.offset);
}
int main()
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int fb_fd = open("/dev/fb0",O_RDWR);
//Get variable screen information
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
vinfo.grayscale=0;
vinfo.bits_per_pixel=32;
ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
long screensize = vinfo.yres_virtual * finfo.line_length;
uint8_t *fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, (off_t)0);
int x,y;
for (x = 50; x < 50 + 50; x++)
for (y = 50; y < 50 + 50; y++)
{
long location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((uint32_t*)(fbp + location)) = pixel_color(0xFF,0x00,0xFF, &vinfo);
}
return 0;
}
Please try the following code in a tty:
It paints me a pink square :-) The machine is a Lenovo Z500 with an Intel graphic card (although it has a sticker about a NVidia GeForce, so maybe it's a dual graphic card machine too but with the secondary one disabled...).
I'll test the code on the MacBook later.
Thats good news! I implemented the changes into the fbdev backend. Maybe f348fb4ca0f4007cbd9874148bd8e071e537ba9a does the job...
I've just check your fixing_fbdev branch on the Lenovo and I'm still getting the same result... :-/
I've checked the stride value, it's 5464 bytes, that at 32bpp it's 1366 pixels wide, that's the wide of my screen without the gap... :-/ I don't know where could it be comming... :-(
Ok, by using this->fb_vinfo.xres_virtual instead of this->fb_vinfo.xres not only it worked but also it gave me an stride of 7680, that means 1920 pixels, the width of Full HD screen, so seems this is the value that's need to be used. I'll send you a pull-request.
Is this completely fixed now?
I've only checked it on the Lenovo laptop, need to test it too on MacBook Pro and on QEmu, but seems it's the correct way to do it. Could you be able to test it on your machine? The more the merrier... :-)
I tested it before I merged :)
Ah cool, then I'll try to test it later or tomorrow.
I need to fix the FbDev support on my MacBook by using directly fb_finfo.line_length instead of calculating it, now it works there and also here on the Lenovo, but QEmu throw an error about "bad stride value" and crash, but seems this is the correct way. We would need to inspect the other values to find one valid for FbDev on QEmu, but seems the framebuffer line length is always fixed and the same independtly of the resolution and color depth being used.
Curiously, the error is being thrown on the PNGStream, so maybe the error is not directly related to the FbDev itself?
I've improved X11 support :-) Only thing createPNGStream() throw an error about "invalid surface for operation" that maybe is somewhat related to the problem of FbDev on QEmu. I've commented the line about take an screenshoot to a file and it works, only that closes to quickly. After putting a setTimeout() of 10 seconds I can see the window is correctly created, but nothing is drawn. Maybe it needs a command to flush the operations to the screen on X11, like swapBuffers() or something?
Another thing: it creates a Window, but maybe it would be more useful to allow it work as a widget embeded on other X11 apps, for example using node-x11 module...
I initially added the X11 backend to be able to test dynamic rendering without the need to switch to a tty. Everythink I implemented worked on my side. I also needed a setTimeout to be able to look at the X11 window for longer than a split second.
Everythink I implemented worked on my side.
I've just tested the "animated clock" and it works, only thing that when clossing the window the app doesn't end, but seems easy to fix (just listen to WM_DESTROY_MESSAGE). I was testing before was a copy of simple_fbdev.js but using X11 instead, I'll review it.
I have been checking the animated clock example and stripped it down, and seems in X11 it's doing all the paint steps inside the clock sphere. They can be painted outside it, but the clock sphere needs to be painted first and in fact it's shown on top of the rectangles... :-/ Also I needed to add an stroke() operation at the end that's not necesary on FbDev:
#!/usr/bin/env node
var fs = require('fs');
var Canvas = require('..');
var backend = new Canvas.backends.X11Backend(800, 600);
var canvas = new Canvas(backend);
var ctx = canvas.getContext('2d');
const squareSize = 100
// Clock sphere, if I remove or change any of this lines, nothing is showed
ctx.lineWidth = 14;
ctx.strokeStyle = '#325FA2';
ctx.arc(0, 0, 142, 0, Math.PI * 2);
ctx.stroke();
ctx.fill();
var offsetX = canvas.width-squareSize
var offsetY = canvas.height-squareSize
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, squareSize, squareSize);
ctx.fillStyle = "#00FF00";
ctx.fillRect(offsetX, 0, squareSize, squareSize);
ctx.fillStyle = "#0000FF";
ctx.fillRect(0, offsetY, squareSize, squareSize);
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(offsetX, offsetY, squareSize, squareSize);
// This is not necesary on FbDev
ctx.stroke();
console.log("Width: " + canvas.width + ", Height: " + canvas.height);
setInterval(function() {
console.log('tick')
}, 1000);
//var outPath = __dirname + '/rectangle.png';
//canvas.createPNGStream().pipe(fs.createWriteStream(outPath));
On my Ubuntu machine (the one where FBDev doesn't work) I've found the next:
I have two framebuffer devices and it's hardcoded to use
/dev/fb0
, so probably the problem is that I'm using the high-end NVidia one, and that's the reason why nothing it's shown in the screen. Could be?