Зависание уведомления о событии XShmPutImage

Я использую расширение XShm для рисования и управления изображениями в Linux.

Чтобы не было мерцания экрана, прохожу send_event = TRUE в XShmPutImage и затем ожидание события с XIfEvent, сразу после вызова XScmPutImage.

Таким образом, я делаю блокировку рисования изображения, чтобы не изменять изображение, пока оно не отобразится на поверхности окна.

Обычно все отлично работает. Но иногда, когда я интенсивно рисую изображение, кажется, что событие никогда не наступает и процедура рисования зависает.

Где посмотреть на проблему? Подходит ли использование XIfEvent для этой задачи? Как событие может исчезнуть из очереди сообщений?

Возможно ли XShmPutImage не отправлять событие (если send_event = TRUE) или отправлять событие, отличное от ShmCompletion на каких обстоятельствах? (например на какую-то внутреннюю ошибку или что-то?)

РЕДАКТИРОВАТЬ:

После еще одного исследования я обнаружил, что такие зависания происходят только тогда, когда оконный менеджер интенсивно генерирует события для окна. Например, когда я изменяю размер окна, перетаскивая его углы.

EDIT2:

Я пробовал несколько способов решить эту проблему, но безуспешно. В конце я был вынужден использовать тайм-аут и через некоторое время отменить ожидание. Но, конечно, это грязный взлом, и я все равно хочу это исправить.

Итак, что может быть причиной того, что XShmPutImage не отправляет событие, если send_event = TRUE, или это событие может исчезнуть из очереди сообщений?

EDIT3:

Вот сомнительный код (FASM):

        cinvoke XShmPutImage, ......, TRUE

.loop:
lea     eax, [.event]
cinvoke XCheckTypedEvent, [Display], [ShmCompletionEvent], eax

test    eax, eax
jz      .loop      ; there is no message

Примечание: XShmPutImage всегда возвращает TRUE, независимо от того, зависла ли проверка события, поэтому я не ставил проверку ошибок после нее.

EDIT4:

Из-за запроса я выкладываю весь код функции рисования. Код использует некоторые макробиблиотеки FASM, но по крайней мере идеи ясны (я надеюсь)

Обратите внимание, что этот код содержит обходной код, который ограничивает событие, ожидающее только 20 мс. Без этого таймаута цикл ожидания просто зависает навсегда. Номер события XShm получается путем вызова XShmGetEventBase как рекомендовано в документации Xshm.

; Draws the image on a OS provided window surface.
proc DrawImageRect, .where, .pImage, .xDst, .yDst, .xSrc, .ySrc, .width, .height
.event XEvent
rb 256
begin
pushad

mov     esi, [.pImage]
test    esi, esi
jz      .exit

mov     ebx, [esi+TImage.ximage]

cinvoke XCreateGC, [hApplicationDisplay], [.where], 0, 0
mov     edi, eaxcinvoke XShmPutImage, [hApplicationDisplay], [.where], edi, [esi+TImage.ximage], [.xSrc], [.ySrc], [.xDst], [.yDst], [.width], [.height], TRUE

stdcall GetTimestamp
lea     esi, [eax+20]    ; 20ms timeout

.loop:
lea     eax, [.event]
cinvoke XCheckTypedEvent, [hApplicationDisplay], [ShmCompletionEvent], eax
test    eax, eax
jnz     .finish

stdcall GetTimestamp
cmp     eax, esi
jb      .loop

.finish:
cinvoke XFreeGC, [hApplicationDisplay], edi

.exit:
popad
return

endp

А вот и код основного цикла событий приложения.

Процедура __ProcessOneSystemEvent просто отправляет события в объекты GUI и игнорирует все события, которые он не использует. Не обрабатывает ShmCompletionEvent совсем.

Все окна, созданные в приложении, имеют маску событий:
ExposureMask+FocusChangeMask+KeyPressMask+KeyReleaseMask+ButtonPressMask+ButtonReleaseMask+EnterWindowMask+LeaveWindowMask+PointerMotionMask+StructureNotifyMask

proc ProcessSystemEvents
.event  XEvent
rb 256
begin
push    ebx ecx edx

.event_loop:
; check for quit

get     eax, [pApplication], TApplication:MainWindow

test    eax, eax
jz      .continue

cmp     dword [eax], 0
jne     .continue

cinvoke XFlush, [hApplicationDisplay]
xor     eax, eax
mov     [fGlobalTerminate], 1
stc
pop     edx ecx ebx
return

.continue:
cinvoke XPending, [hApplicationDisplay]
test    eax, eax
jz      .noevents

push    edi ecx
lea     edi, [.event]
mov     ecx, sizeof.XEvent/4
xor     eax, eax
rep stosd
pop     ecx edi

lea     ebx, [.event]

cinvoke  XNextEvent, [hApplicationDisplay], ebx
stdcall  __ProcessOneSystemEvent, ebx
jmp      .event_loop

.noevents:
clc
pop     edx ecx ebx
return

endp

Полный исходный код доступен в хранилище но это очень большой проект, нелегкий для навигации. Обсуждаемый источник находится в регистрации 8453c99b1283def8,

Файлы: «Freshlib / графика / images.asm» а также «Freshlib / графика / Linux / images.asm» о рисовании изображения.

Файлы: «Freshlib / гуй / main.asm» а также «Freshlib / GUI / Linux / main.asm» об общей обработке событий в приложении.

12

Решение

Что делает X-сервер?

X сервер Можно а также будут подавить ShmCompletionEvent если параметры переданы XShmPutImage превышать геометрию области общей памяти, прикрепленной к XImage в вызове. Сервер проверяет X / Y и width / height относительно ранее сохраненных ограничений для данной общей области, и если параметры вызова выходят за пределы, сервер вернется BadValue, подавлять операция рисования, и подавлять событие завершения.

Выше именно так что происходит в вашей библиотеке. Вот как:

  1. Основная процедура диспетчера событий ProcessSystemEvents, Выполняет XEventNextи на основе типа события, используя таблицу переходов .jump_table отправляет к определенной функции обработчика события.
  2. Специфичная для события функция для Expose событие .expose
  3. .expose функция, в свою очередь, вызовет DrawImageRect используя значения X / Y и ширины / высоты из XExposeEvent структура. Это неправильно и является истинным источником ошибки, как мы вскоре увидим.
  4. DrawImageRect передаст эти значения в вызове XShmPutImage
  5. Обработчик для XShmPutImage в икс сервер рассмотрим эти параметры и отклонять если они вне границ.

Параметры отклоняются, потому что они происходят от события воздействия и связаны с геометрией окно а также не геометрия общей памяти, прикрепленной к XImage используется в XShmPutImage вызов.

В частности, если окно было только что изменено (например, оконным менеджером) и было увеличено, и ранее ConfigureNotify событие для изменения размера. Теперь с новым Expose событие будет иметь большую ширину / высоту, которая будет превышать ширину / высоту области общей памяти, о которой знает сервер.

Это ответственность клиент выставить в поле события изменения размера окна [и т. д.] и разорвать / воссоздать общую область памяти с увеличенным размером. Это не делается и является источником ошибки.

НОТА: Просто чтобы быть полностью ясным в этом, сервер может только доклад на ошибку и не сделать что-нибудь с этим по нескольким причинам:

  1. Сервер знает об окне [и его изменении размера].
  2. Он знает о XImage, его общей области памяти и размере
  3. Но они связаны только во время вызова XShmPutImage [AFAIK]
  4. Даже если сервер мог связать их, это не может отрегулировать shmarea
  5. Это потому, что у него нет способа связать shmarea с клиентской стороной.
  6. Только клиент может сделать это через XShmDetach/XShmAttach

Ниже приведены отредактированные версии соответствующих исходных файлов из c5c765bc7e совершить. Они были немного очищены, поэтому остались только самые германские детали. Некоторые строки были обрезаны или обернуты для устранения горизонтальной прокрутки.

Файлы были помечены NOTE а также NOTE/BUG что я и сделал, анализируя их.


гуй / main.asm Общий основной цикл верхнего уровня. Здесь нечего видеть.

; FILE: gui/Main.asm
; _____________________________________________________________________________
;|                                                                             |
;| ..::FreshLib::.. Free, open source. Licensed under "BSD 2-clause" license." |
;|_____________________________________________________________________________|
;
;  Description: Main procedure of GUI application library.
;
;  Target OS: Any
;
;  Dependencies:
;
;  Notes: Organize the main message/event loop needed by every GUI engine.
;         This file contains only OS independent part and includes OS dependent
;         files.
;______________________________________________________________________________

module "Main library"
proc Run
begin
.mainloop:
stdcall ProcessSystemEvents
jc      .terminate

mov     eax, [pApplication]
test    eax, eax
jz      .eventok

get     ecx, eax, TApplication:OnIdle
jecxz   .eventok

stdcall ecx, eax

.eventok:
stdcall WaitForSystemEvent
jmp     .mainloop

.terminate:
DebugMsg "Terminate GUI application!"return
endp

include '%TargetOS%/Main.asm'

endmodule

гуй / Linux / main.asm Обработчики событий

; FILE: gui/Linux/Main.asm
; _____________________________________________________________________________
;|                                                                             |
;| ..::FreshLib::.. Free, open source. Licensed under "BSD 2-clause" license." |
;|_____________________________________________________________________________|
;
;  Description: Main procedure of GUI application library.
;
;  Target OS: Linux
;
;  Dependencies:
;
;  Notes: Organize the main message/event loop needed by every GUI engine.
;______________________________________________________________________________

body ProcessSystemEvents
; NOTE: this is the storage for the dequeued event -- all dispatch routines
; should use it and process it
.event  XEvent
rb 256

begin
push    ebx ecx edx

.event_loop:
; check for quit

get     eax, [pApplication], TApplication:MainWindow

test    eax, eax
jz      .continue     ; ???????????

cmp     dword [eax], 0
jne     .continue

cinvoke XFlush, [hApplicationDisplay]
xor     eax, eax
mov     [fGlobalTerminate], 1
stc
pop     edx ecx ebx
return

; NOTE: it is wasteful for the main loop to call WaitForSystemEvent, then call
; us and we do XPending on the first loop -- we already know we have at least
; one event waiting in the queue
.continue:
cinvoke XPending, [hApplicationDisplay]
test    eax, eax
jz      .noevents

push    edi ecx
lea     edi, [.event]
mov     ecx, sizeof.XEvent/4
xor     eax, eax
rep stosd
pop     ecx edi

lea     ebx, [.event]

cinvoke  XNextEvent, [hApplicationDisplay], ebx
stdcall  __ProcessOneSystemEvent, ebx
jmp      .event_loop

.noevents:
clc
pop     edx ecx ebx
return

endp

body WaitForSystemEvent
.event XEvent
begin
push    eax ecx edx
lea     eax, [.event]
cinvoke XPeekEvent, [hApplicationDisplay], eax
pop     edx ecx eax
return
endp

proc __ProcessOneSystemEvent, .linux_event
begin
pushad

mov     ebx, [.linux_event]

;        mov     eax, [ebx+XEvent.type]
;        cmp     eax, [ShmCompletionEvent]
;        je      .shm_completion

stdcall _GetWindowStruct, [ebx+XEvent.window]
jc      .notprocessed

test    eax, eax
jz      .notprocessed

mov     esi, eax
mov     ecx, [ebx+XEvent.type]

cmp     ecx, LASTEvent
jae     .notprocessed

mov     ecx, [.jump_table+4*ecx]
jecxz   .notprocessed

jmp     ecx

.notprocessed:
popad
stc
return

.finish:
popad
clc
return

;.shm_completion:
;        DebugMsg "Put back completion event!";
;        int3
;        cinvoke XPutBackEvent, [hApplicationDisplay], ebx
;        jmp     .finish

;.........................................................................
; seMove and seResize events.
;-------------------------------------------------------------------------
.moveresize:

; NOTE/BUG!!!!: we must not only process a resize/move request, but we must also
; adjust the size of the shmarea attached to the XImage -- that is _not_ being
; done. (e.g.) if the window is enlarged, the shmarea must be enlarged

cinvoke XCheckTypedWindowEvent, [hApplicationDisplay],
[ebx+XConfigureEvent.window], ConfigureNotify, ebx
test    eax, eax
jnz     .moveresize

; resize event...
mov     eax, [esi+TWindow._width]
mov     edx, [esi+TWindow._height]
cmp     eax, [ebx+XConfigureEvent.width]
jne     .resize
cmp     edx, [ebx+XConfigureEvent.height]
je      .is_move

.resize:
exec    esi, TWindow:EventResize, [ebx+XConfigureEvent.width],
[ebx+XConfigureEvent.height]

; move event...
.is_move:
mov     eax, [esi+TWindow._x]
mov     edx, [esi+TWindow._y]
cmp     eax, [ebx+XConfigureEvent.x]
jne     .move
cmp     eax, [ebx+XConfigureEvent.y]
je      .finish

.move:
exec    esi, TWindow:EventMove,
[ebx+XConfigureEvent.x], [ebx+XConfigureEvent.y]

jmp     .finish

;.........................................................................
; DestroyNotify handler it invalidates the handle in TWindow structure and
; then destroys TWindow.
.destroy:
test    esi, esi
jz      .finish

mov     [esi+TWindow.handle], 0

destroy esi
jmp     .finish

;.........................................................................
; Window paint event

.expose:
get     edi, esi, TWindow:ImgScreen

; NOTE:BUG!!!!!
;
; if the window has been resized (e.g. enlarged), these values are wrong!
; they relate to the _window_ but _not_ the shmarea that is attached to the
; XImage
;
; however, DrawImageRect will call XShmPutImage with these values, they
; will exceed the geometry of what the X server knows about the shmarea and
; it will return BadValue and _suppress_ the completion event for XShmPutImage

stdcall DrawImageRect, [esi+TWindow.handle], edi,
[ebx+XExposeEvent.x],[ebx+XExposeEvent.y],
[ebx+XExposeEvent.x], [ebx+XExposeEvent.y],
[ebx+XExposeEvent.width], [ebx+XExposeEvent.height]

jmp     .finish

;.........................................................................
; Mouse event handlers

.mousemove:

cinvoke XCheckTypedWindowEvent, [hApplicationDisplay],
[ebx+XConfigureEvent.window], MotionNotify, ebx
test    eax, eax
jnz     .mousemove

stdcall ServeMenuMouseMove, [ebx+XMotionEvent.window],
[ebx+XMotionEvent.x], [ebx+XMotionEvent.y],
[ebx+XMotionEvent.state]
jc      .finish

cinvoke XCheckTypedWindowEvent, [hApplicationDisplay],
[ebx+XMotionEvent.window], MotionNotify, ebx
test    eax, eax
jnz     .mousemove

mov     edi, [__MouseTarget]
test    edi, edi
jz      .search_target_move

stdcall __GetRelativeXY, edi, [ebx+XMotionEvent.x], [ebx+XMotionEvent.y]
jmp     .target_move

.search_target_move:
exec    esi, TWindow:ChildByXY, [ebx+XMotionEvent.x],
[ebx+XMotionEvent.y], TRUE
mov     edi, eax

.target_move:
cmp     edi, [__LastPointedWindow]
je      .move_event

cmp     [__LastPointedWindow], 0
je      .leave_ok

exec    [__LastPointedWindow], TWindow:EventMouseLeave

.leave_ok:

mov     [__LastPointedWindow], edi
exec    edi, TWindow:EventMouseEnter

.move_event:
exec    edi, TWindow:EventMouseMove, ecx, edx, [ebx+XMotionEvent.state]
jmp     .finish

;.........................................................................
; event jump table
.jump_table dd  0                       ; event 0
dd  0                       ; event 1
dd  .key_press              ; KeyPress = 2
dd  .key_release            ; KeyRelease = 3
dd  .mouse_btn_press        ; ButtonPress = 4
dd  .mouse_btn_release      ; ButtonRelease = 5
dd  .mousemove              ; MotionNotify = 6
dd  0                       ; EnterNotify = 7
dd  0                       ; LeaveNotify = 8
dd  .focusin                ; FocusIn = 9
dd  .focusout               ; FocusOut = 10
dd  0                       ; KeymapNotify = 11
dd  .expose                 ; Expose = 12
dd  0                       ; GraphicsExpose = 13
dd  0                       ; NoExpose = 14
dd  0                       ; VisibilityNotify = 15
dd  0                       ; CreateNotify = 16
dd  .destroy                ; DestroyNotify = 17
dd  0                       ; UnmapNotify = 18
dd  0                       ; MapNotify = 19
dd  0                       ; MapRequest = 20
dd  0                       ; ReparentNotify = 21
dd  .moveresize             ; ConfigureNotify = 22
dd  0                       ; ConfigureRequest = 23
dd  0                       ; GravityNotify = 24
dd  0                       ; ResizeRequest = 25
dd  0                       ; CirculateNotify = 26
dd  0                       ; CirculateRequest = 27
dd  0                       ; PropertyNotify = 28
dd  0                       ; SelectionClear = 29
dd  0                       ; SelectionRequest = 30
dd  0                       ; SelectionNotify = 31
dd  0                       ; ColormapNotify = 32
dd  .clientmessage          ; ClientMessage = 33
dd  .mapping_notify         ; MappingNotify = 34

графика / Linux / images.asm Код рисования изображения [включая DrawImageRect функция] и разделяемая память создают / уничтожают код.

; FILE: graphics/Linux/images.asm
; _____________________________________________________________________________
;|                                                                             |
;| ..::FreshLib::.. Free, open source. Licensed under "BSD 2-clause" license." |
;|_____________________________________________________________________________|
;
;  Description: Memory based images manipulation library.
;
;  Target OS: Linux
;
;  Dependencies: memory.asm
;
;  Notes:
;______________________________________________________________________________

uses libX11, xshm

struct TImage
.width   dd ?  ; width in pixels.
.height  dd ?  ; height in pixels.
.pPixels dd ?  ; pointer to the pixel memory.

; os dependent data
.ximage  dd ?
.shminfo XShmSegmentInfo
ends

body CreateImage
begin
pushad

stdcall GetMem, sizeof.TImage
jc      .finish
mov     esi, eax

xor     eax, eax
inc     eax

mov     ecx, [.width]
mov     edx, [.height]

cmp     ecx, 0
cmovle  ecx, eax

cmp     edx, 0
cmovle  edx, eax

mov     [esi+TImage.width], ecx
mov     [esi+TImage.height], edx

lea     eax, [4*ecx]
imul    eax, edx

cinvoke shmget, IPC_PRIVATE, eax, IPC_CREAT or 777o
test    eax, eax
js      .error

mov     [esi+TImage.shminfo.ShmID], eax

cinvoke shmat, eax, 0, 0
cmp     eax, -1
je      .error_free

mov     [esi+TImage.shminfo.Addr], eax
mov     [esi+TImage.pPixels], eax
mov     [esi+TImage.shminfo.fReadOnly], 1

lea     ebx, [esi+TImage.shminfo]
cinvoke XShmCreateImage, [hApplicationDisplay], 0, $20, ZPixmap, eax,
ebx, [esi+TImage.width], [esi+TImage.height]
mov     [esi+TImage.ximage], eax

cinvoke XShmAttach, [hApplicationDisplay], ebx

clc
mov     [esp+4*regEAX], esi

.finish:
popad
return

.error_free:
cinvoke shmctl, [ebx+XShmSegmentInfo.ShmID], IPC_RMID, 0

.error:
stdcall FreeMem, esi
stc
jmp     .finish

endp

body DestroyImage
begin
pushad

mov     esi, [.ptrImage]
test    esi, esi
jz      .finish

lea     eax, [esi+TImage.shminfo]
cinvoke XShmDetach, [hApplicationDisplay], eax

cinvoke XDestroyImage, [esi+TImage.ximage]

cinvoke shmdt, [esi+TImage.shminfo.Addr]
cinvoke shmctl, [esi+TImage.shminfo.ShmID], IPC_RMID, 0
stdcall FreeMem, esi

.finish:
popad
return
endp

;if used ___CheckCompletionEvent
;___CheckCompletionEvent:
;
;virtual at esp+4
;  .display dd ?
;  .pEvent  dd ?
;  .user    dd ?
;end virtual
;
;; timeout
;        stdcall GetTimestamp
;        cmp     eax, [.user]
;        jbe     @f
;
;        DebugMsg "Timeout!";
;        mov     eax, 1
;        retn
;
;@@:
;        mov     eax, [.pEvent]      ;.pEvent
;        mov     eax, [eax+XEvent.type]
;
;        cmp     eax, [ShmCompletionEvent]
;        sete    al
;        movzx   eax, al
;        retn
;end if

body DrawImageRect
.event XEvent
rb 256
begin
pushad

mov     esi, [.pImage]
test    esi, esi
jz      .exit

mov     ebx, [esi+TImage.ximage]

; NOTE: is this necessary? it seems wasteful to create and destroy a GC
; repeatedly.  Dunno, does this _have_ to be done here, _every_ time?
cinvoke XCreateGC, [hApplicationDisplay], [.where], 0, 0
mov     edi, eax

; NOTE/BUG: The return ShmCompletionEvent will be suppressed due to a BadValue
; if the X/Y and width/height parameters given to us by caller exceed the
; geometry/range of the shmarea attached to .ximage
;
; the routine that calls us is .expose and it _is_ giving us bad values.  it is
; passing us X/Y width/height related to an exposure event of the .where
; _window_ which we put in the call.  The X server will compare these against
; the size of the shmarea of TImage.xmage and complain if we exceed the bounds

cinvoke XShmPutImage, [hApplicationDisplay], [.where], edi,
[esi+TImage.ximage], [.xSrc], [.ySrc], [.xDst], [.yDst],
[.width], [.height], TRUE

; NOTE/BUG: this code should _not_ be looping on XCheckTypedEvent because it
; disrupts the normal event processing.  if we want to be "synchronous" on this
; we should loop on the main event dispatcher (ProcessSystemEvents) and let it
; dispatch to a callback we create.  we can set a "pending" flag that our [not
; yet existent] dispatch routine can clear

; THIS CODE SOMETIMES CAUSES HANGS!

stdcall GetTimestamp
lea     esi, [eax+20]

.loop:
lea     eax, [.event]
cinvoke XCheckTypedEvent, [hApplicationDisplay], [ShmCompletionEvent],
eax
test    eax, eax
jnz     .finish

stdcall GetTimestamp
cmp     eax, esi
jb      .loop

.finish:
cinvoke XFreeGC, [hApplicationDisplay], edi

.exit:
popad
return

endp

Xext / shm.c Код X-сервера, который проверяет и обрабатывает XShmPutImage вызов.

// FILE: Xext/shm.c

static int
ProcShmPutImage(ClientPtr client)
{
GCPtr pGC;
DrawablePtr pDraw;
long length;
ShmDescPtr shmdesc;

REQUEST(xShmPutImageReq);

REQUEST_SIZE_MATCH(xShmPutImageReq);
VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);

// NOTE: value must be _exactly_ 0/1
if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
return BadValue;

if (stuff->format == XYBitmap) {
if (stuff->depth != 1)
return BadMatch;
length = PixmapBytePad(stuff->totalWidth, 1);
}
else if (stuff->format == XYPixmap) {
if (pDraw->depth != stuff->depth)
return BadMatch;
length = PixmapBytePad(stuff->totalWidth, 1);
length *= stuff->depth;
}
else if (stuff->format == ZPixmap) {
if (pDraw->depth != stuff->depth)
return BadMatch;
length = PixmapBytePad(stuff->totalWidth, stuff->depth);
}
else {
client->errorValue = stuff->format;
return BadValue;
}

// NOTE/BUG: The following block is the "check parameters" code.  If the
// given drawing parameters of the request (e.g. X, Y, width, height) [or
// combinations thereof] exceed the geometry/size of the shmarea, the
// BadValue error is being returned here and the code to send a return
// event will _not_ be executed.  The bug isn't really here, it's on the
// client side, but it's the client side bug that causes the event to be
// suppressed

/*
* There's a potential integer overflow in this check:
* VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
*                client);
* the version below ought to avoid it
*/
if (stuff->totalHeight != 0 &&
length > (shmdesc->size - stuff->offset) / stuff->totalHeight) {
client->errorValue = stuff->totalWidth;
return BadValue;
}
if (stuff->srcX > stuff->totalWidth) {
client->errorValue = stuff->srcX;
return BadValue;
}
if (stuff->srcY > stuff->totalHeight) {
client->errorValue = stuff->srcY;
return BadValue;
}
if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) {
client->errorValue = stuff->srcWidth;
return BadValue;
}
if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) {
client->errorValue = stuff->srcHeight;
return BadValue;
}

// NOTE: this is where the drawing takes place
if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
((stuff->format != ZPixmap) &&
(stuff->srcX < screenInfo.bitmapScanlinePad) &&
((stuff->format == XYBitmap) ||
((stuff->srcY == 0) &&
(stuff->srcHeight == stuff->totalHeight))))) &&
((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
(*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
stuff->dstX, stuff->dstY,
stuff->totalWidth, stuff->srcHeight,
stuff->srcX, stuff->format,
shmdesc->addr + stuff->offset +
(stuff->srcY * length));
else
doShmPutImage(pDraw, pGC, stuff->depth, stuff->format,
stuff->totalWidth, stuff->totalHeight,
stuff->srcX, stuff->srcY,
stuff->srcWidth, stuff->srcHeight,
stuff->dstX, stuff->dstY, shmdesc->addr + stuff->offset);

// NOTE: this is where the return event gets sent
if (stuff->sendEvent) {
xShmCompletionEvent ev = {
.type = ShmCompletionCode,
.drawable = stuff->drawable,
.minorEvent = X_ShmPutImage,
.majorEvent = ShmReqCode,
.shmseg = stuff->shmseg,
.offset = stuff->offset
};
WriteEventsToClient(client, 1, (xEvent *) &ev);
}

return Success;
}
4

Другие решения

Ваш исходный код будет конечной частью, которую мы можем проанализировать, но, поскольку я очень плохо понимаю сборку, я дам вам ответ на макроуровне. Точный ответ мне пока неизвестен.

В случае слишком большого количества событий только это создает эту проблему, но не при нормальном возникновении событий, что означает, что вашей инфраструктуре не хватает виртуальной памяти или другой кадр событий запускается до того, как предыдущий освободит свою память. В таких ситуациях вы можете сделать несколько вещей

  1. Попробуйте проверить, есть ли утечка памяти или нет. После того, как закончился один кадр события, попробуйте очистить память или правильно завершить этот объект кадра, прежде чем запускать новый.
  2. Вы также можете разработать механизм, позволяющий второму кадру ждать окончания первого кадра. В C / C ++ мы делаем это, используя так много методов синхронизации, как Mutex или же select системные вызовы. Если вы разрабатываете дизайн по такой схеме, вы можете сделать это
  3. Если у вас есть права на изменение выделенной памяти, выделенной вашему окну, попробуйте увеличить ее. Потому что одно точно (согласно твоим объяснениям), что это какая-то проблема с памятью.

Ответ на Править 3 Похоже, вы вызываете какой-то метод cinvoke, Как это внутренне обрабатывает даже неизвестно мне. Почему бы вам не реализовать это непосредственно в C. Я уверен, что для любой цели, над которой вы работаете, вы получите кросс-компилятор.

3

По вопросам рекламы [email protected]