7

OSがディスプレイ出力用に自動的に構成することなく、アプリケーションからのHDMI出力を排他的に駆動することはどのように可能でしょうか?

たとえば、プライマリディスプレイとして標準のDVI / VGAを使用しますが、デバイスファイルを使用してMplayerビデオ出力をHDMIに送信します。

Googleで答えるのは難しい質問です。ほとんどすべての結果は、HDMI経由でオーディオを機能させることに関係しています。

(ここで編集)

以下のコメントは、個別のXorgサーバーを使用して言及されています。これは有用なアイデアですが、私が尋ねた1つの質問と、私が暗示した1つの質問には答えません。

1)他のディスプレイの前にコンソールがロードされている場合、またはそれが唯一のディスプレイである場合(ログインにSSHのみが使用されている場合)、Linuxがコンソールをそのディスプレイに配置したくないようにするにはどうすればよいですか?2)Xがない場合はどうなりますか?グラフィックをアダプタに直接駆動したい。ドライバーと直接対話することなく(おそらく古いですが、SVGALibまたは他の非Xグラフィックレイヤーを使用して)、標準機能を使用してコードからこれを行うことはできますか?

(ここで編集)

SVGALib(古い)とSDLを見ました。後者はXの内外で機能し、OpenGLへのアクセスも提供します。どこかのフォーラムリンクからバージョン1.3を見つけましたが、WebサイトとFTPの両方に最大1.2しか含まれていないようです。SDLは一般的に美しいソリューションですが、次の2つの特定の欠点があります。

1)一般的なcreate-device呼び出しはデバイスインデックスを受け入れますが、それを完全に無視します。

(src/video/bwindow/SDL_bvideo.cc)
BE_CreateDevice(int devindex)

ドライバー固有の呼び出しにも同じ欠陥があるようです。たとえば、DirectFB(私が思うに、コンソールの下にグラフィックスを提供します):

(src/video/directfb/SDL_DirectFB_video.c)
DirectFB_CreateDevice(int devindex)

これらの関数の本体には、デバイスインデックスを設定するための既存の場所がないようです...それらが構築されている標準インターフェイスでのサポートが不足しているため、間違いありません。

2)アダプターが選択された場合、SDLはすべてのディスプレイを自動的に接続するようです。例「testsprite2.c」(ライブラリに付属)は、「common.c」(すべての例に共通の機能)内で処理される「--display」パラメーターを受け入れます。「--display」パラメータで行うのは、1つの大きな結合されたキャンバス内のその画面のX/Y座標を計算することだけであることがわかります。

if (SDL_strcasecmp(argv[index], "--display") == 0) {
    ++index;
    if (!argv[index]) {
        return -1;
    }
    state->display = SDL_atoi(argv[index]);
    if (SDL_WINDOWPOS_ISUNDEFINED(state->window_x)) {
        state->window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
        state->window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(state->display);
    }
    if (SDL_WINDOWPOS_ISCENTERED(state->window_x)) {
        state->window_x = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
        state->window_y = SDL_WINDOWPOS_CENTERED_DISPLAY(state->display);
    }
    return 2;
}

したがって、同じアダプタ上にある場合、あるディスプレイを別のディスプレイから分離する方法はありません。SDLは機能しません。

SDLに匹敵する解決策がない限り、または特定のデバイス(devindex)を適切な場所に設定するのが簡単であることが判明しない限り(おそらくそうではなく、したがって、おそらく実装されないままにされた理由)、画面を排他的かつ完全に専用に使用するための最良のオプションは、2番目のデバイスに割り当てられた別のXorgインスタンスの下に独自のウィンドウマネージャーを作成することです。

4

1 に答える 1

4

フレームバッファデバイス/dev/ fbに直接書き込むことができます(コンソールがデフォルトで1つを使用すると仮定します)。コンソールが表示されないようにするには、すべての仮想端末を無効にするだけです(その後は、リモートでのみログインできます)。複数のアダプタがある場合は、複数のフレームバッファデバイスを入手する必要があります(これは確認する必要があります)。

フレームバッファに長方形を描画するACの例は次のとおりです。

LinuxFrameBufferを介して画面にピクセルをペイントする

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

int main()
{
    int fbfd = 0;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    char *fbp = 0;
    int x = 0, y = 0;
    long int location = 0;

    // Open the file for reading and writing
    fbfd = open("/dev/fb0", O_RDWR);
    if (fbfd == -1) {
        perror("Error: cannot open framebuffer device");
        exit(1);
    }
    printf("The framebuffer device was opened successfully.\n");

    // Get fixed screen information
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
        perror("Error reading fixed information");
        exit(2);
    }

    // Get variable screen information
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
        perror("Error reading variable information");
        exit(3);
    }

    printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

    // Figure out the size of the screen in bytes
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

    // Map the device to memory
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ((int)fbp == -1) {
        perror("Error: failed to map framebuffer device to memory");
        exit(4);
    }
    printf("The framebuffer device was mapped to memory successfully.\n");

    x = 100; y = 100;       // Where we are going to put the pixel

    // Figure out where in memory to put the pixel
    for (y = 100; y < 300; y++)
        for (x = 100; x < 300; x++) {

            location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
                       (y+vinfo.yoffset) * finfo.line_length;

            if (vinfo.bits_per_pixel == 32) {
                *(fbp + location) = 100;        // Some blue
                *(fbp + location + 1) = 15+(x-100)/2;     // A little green
                *(fbp + location + 2) = 200-(y-100)/5;    // A lot of red
                *(fbp + location + 3) = 0;      // No transparency
        //location += 4;
            } else  { //assume 16bpp
                int b = 10;
                int g = (x-100)/6;     // A little green
                int r = 31-(y-100)/16;    // A lot of red
                unsigned short int t = r<<11 | g << 5 | b;
                *((unsigned short int*)(fbp + location)) = t;
            }

        }
    munmap(fbp, screensize);
    close(fbfd);
    return 0;
}

ビルドツールとシステムのヘッダーが利用可能である限り、コンパイルする必要があります。スリルを味わうには、SSHから実行し、ログインしていない物理画面に描画されるのを見てください。

X11の外部には、フレームバッファに対して機能するさまざまなツールがありますが、それらはフレームバッファに直接アクセスしないことに注意してください。代わりに、DirectFBと呼ばれる追加の抽象化レイヤーを介して機能します。DirectFBを使用すると、同じアプリケーションをX11の内外で実行できます... MPlayer、GStreamer、SDL(DirectFBと呼ばれる)を組み込んだアプリ、およびXDirectFBと呼ばれる軽量で人気のある偽のX11コンテナー(私は信じています)の両方を含みますX11アプリを実行する必要がありますが、通常のウィンドウマネージャーほど負担がかからないようにする必要があります)。

于 2013-02-07T02:59:09.220 に答える