не удалось скопировать предварительно нарисованное растровое изображение (X Windows, xlib) - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь нарисовать растровое изображение, чтобы позже скопировать его в окно. Я делаю это из Standard ML, используя PolyWW XWindows / Motif.

Приблизительно следуя инструкциям Найя в C, мой код не выполнялся в 20-50% случаев. В качестве обходного пути я вставил XFlushes не только после каждого X-вызова, но и в начале любой функции. При этом программа с моими основными вызовами рисования успешно работает не менее 20 раз подряд. Однако добавление одного вызова XFillRectangle для очистки фона вновь приводит к моей первоначальной проблеме, и код выполняется всего 4 раза из 5 или менее.

Код сводится к следующему примеру. Проблемной частью c является вызов XFillRectangle. Без этого программа запускается после компиляции не менее 20 раз. включая его, он дает сбой 20% или более раз и не попадает в функцию set с отладочным сообщением «copy».

open XWindows;
open Motif;

val testWindow = fn () =>

let
  val rep     =  Option.valOf (Int.fromString (hd (CommandLine.arguments ())) );
  val dim     =  {tw=400,th=400}
  val shell   =  XtAppInitialise      ""    "test" "top" [] [ XmNwidth (#tw dim), XmNheight (#th dim) ] ;
  val dp      =  XtDisplay shell;
  val xf      =  XFlush ;
  val main    =  XmCreateMainWindow   shell    "main"       [ XmNmappedWhenManaged true ]   ;
  val canvas  =  XmCreateDrawingArea  main   "drawhere"     [ XmNwidth (#tw dim), XmNheight (#th dim) ] ;
  val usegc   =  DefaultGC (XtDisplay canvas) ;

  val buf     =  XCreatePixmap (RootWindow dp) (Area{x=0,y=0,w = #tw dim, h= #th dim}) 24 ;
  fun text1 n =  ( xf dp ; XDrawArc buf usegc (XArc (Area{x=10,y=10,w = #tw dim -20 , h= #th dim -20} , 0,360*64 ));
                   xf dp ) ;

  val _       =  ( xf dp; XSetForeground usegc 0x098809 ;xf dp;
    (* 20 % crash =>  *)   xf dp ; XFillRectangle buf usegc (Area{x=0,y=0,w = #tw dim, h= #th dim})   ; xf dp; 
                     List.app text1 (List.tabulate (rep ,fn i=> i)) ; xf dp;
                     print "done" )  ; 

  val set     = fn  (w,c,t)  =>(xf dp ;  
                      print "copy " ; TextIO.flushOut;
                      XCopyArea buf (XtWindow canvas) usegc ( XPoint {x=0,y=0} ) (Area{x=0,y=0,w = #tw dim , h= #th dim });
                      xf dp;  t ) 
  in

  ( XtSetCallbacks   canvas [ (XmNexposeCallback , set)  ] XmNarmCallback      ;
    XtManageChild    canvas ;
    XtManageChild    main   ; 
    XtRealizeWidget  shell ;
    xf dp ;
    while (true) do (OS.Process.sleep (Time.fromReal 1.0))
  )

end;

Мой вопрос: как это может быть? Или, скорее, как я могу подготовить Pixmap, которому нужно около 200 вызовов DrawAr c и фона, чтобы я мог скопировать его в окно позже ?? В растровом изображении все вызовы выполняются успешно, это обратный вызов set, который никогда не происходит.

Ошибки в основном являются одним из следующих 2:

shell$ ./demos 187
done[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
Assertion failed: (!xcb_xlib_threads_sequence_lost), function poll_for_event, file xcb_io.c, line 259.

shell$ ./demos 187
done
X Error BadIDChoice in XCreateWindow

XIO:  fatal IO error 35 (Resource temporarily unavailable) on X server ":0"
      after 360 requests (360 known processed) with 12 events remaining.
  • update. Я полностью закодировал тот же пример в X Windows (без мотивов). Проблема сохраняется с более высокой частотой отказов.
  • update 2. Я запрограммировал пример в C. Он не работает sh в том смысле, что я могу запустить его десятки раз без ошибок. Проблема должна исходить из того, как я использую X Windows или ML. Вот что я пытался сделать:
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>

Display *display;
int screen_num;

void text1 (Pixmap buffer, GC gc, int n);
void _     (Pixmap buffer, GC gc, int n);
void set   (Window win   , Pixmap b, GC gc);

int main(int argc,char ** argv){
 /* let */
    int rep = atoi(argv[1]);          /* need argument or will crash */
    Window win;
    unsigned int width=400, height=400;  
    int x=0, y=0; 
    unsigned int border_width = 0; 
    Pixmap buf;
    int count;
    XEvent report;
    GC usegc;
    char *display_name = NULL;

    display=XOpenDisplay(display_name) ;
    win = XCreateSimpleWindow(display, RootWindow(display,screen_num), 
            x, y, width, height, border_width, BlackPixel(display,
            screen_num), WhitePixel(display,screen_num));
    usegc=XCreateGC(display,win,0,NULL);

    buf  = XCreatePixmap ( display , RootWindow(display,screen_num)  , 400,400,24) ;
     _ (buf,usegc,rep);

 /* in */
    XSelectInput(display, win, ExposureMask );  
    XMapWindow(display, win);

    while (1)  {
        XNextEvent(display, &report);
        switch  (report.type) {
        case Expose:
            set(win, buf,usegc);
            break;
        default:
            break;
        } 
    }
}


void text1 (Pixmap buffer, GC gc,int n) { XDrawArc( display, buffer, gc, 10,10,380,380, 0,360*64 ) ; }

void _ (Pixmap buffer, GC gc,int n)
{ XSetForeground(display , gc,16777215);
  XFillRectangle(display,buffer,gc,0,0,400,400);
  XSetForeground(display , gc,624649 );
  for (int i=0;i<=n;i++)text1(buffer,gc,n);
}

void set(Window win, Pixmap b, GC gc){ XCopyArea (display,b,win,gc,0,0,400,400,0,0); }
...