BBC BASIC
« Using GDIP with assembler »

Welcome Guest. Please Login or Register.
Jan 20th, 2018, 4:19pm


Cross-platform BBC BASIC (Win32, Linux x86, Android, Mac OS-X, Raspberry Pi)

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Using GDIP with assembler  (Read 85 times)
svein
New Member
Image


member is offline

Avatar




PM


Posts: 12
xx Using GDIP with assembler
« Thread started on: Oct 25th, 2017, 01:06am »

Hello Richard.
I hope you can help with a little problem.

It's about drawing a line in GDI+ from assembler code.

In the supplied demo, two figures are drawn, one by assembler and one by the regular library call, using the same pen for both.
With a width of one, they look the same, but as the width increases, the assembler drawn figure seems to use a different pen style.
Any idea why ?

The @memhdc% parameter causes a crash if included in the assembler call to 'GdipDrawLine'.
Any idea why ?

In fact, one can remove or replace @memhdc% in SYS 'GdipDrawLine' .... from the library.
And it still works, how come ??

This is for windows 10.
Svein

Code:
      INSTALL @lib$+"GDIPLIB" : PROC_gdipinit
      ON CLOSE PROCexit : QUIT
      Pen%=FN_gdipcreatepen(&FF000000,0,1)
      PROC_asm : OFF
      ON TIME PROCnewpen : RETURN

      *REFRESH OFF
      REPEAT : CLS
        Posx=500 : Posy=500
        A%+=1 : Angle=A%
        FOR I%=1 TO 12
          Angle+=30
          FOR J%=1 TO 6
            Posx+=100*SINRAD(Angle)
            Posy+=100*COSRAD(Angle)
            CALL antiline
            PROC_gdipline(Pen%,oldx+400,oldy,Posx+400,Posy)
            oldx=Posx : oldy=Posy
            Angle-=60
          NEXT
        NEXT
        *REFRESH
        WAIT 0
      UNTIL 0

      DEF PROCnewpen
      PRIVATE width,adj
      IF width=0 THEN width=2 : adj=0.25
      width+=adj
      IF width>5 OR width<1 THEN adj=-adj
      PROC_gdipdeletepen(Pen%)
      Pen%=FN_gdipcreatepen(&FF204080,0,width)
      ENDPROC

      DEF PROC_gdipline(P%, x1, y1, x2, y2)
      LOCAL rc{}
      DIM rc{l%,t%,r%,b%}
      PROC_bbc2api(x1,y1)
      PROC_bbc2api(x2,y2)
      SYS "SetBoundsRect", @memhdc%, 0, 5
      SYS `GdipDrawLine`, FN_gdipg, P%, FN_f4(x1), FN_f4(y1), FN_f4(x2), FN_f4(y2), @memhdc%
      SYS "GetBoundsRect", @memhdc%, rc{}, 0
      SYS "OffsetRect", rc{}, -@ox%, -@oy%
      SYS "InvalidateRect", @hwnd%, rc{}, 0
      ENDPROC

      DEF PROC_asm
      LOCAL var%,code%,pass%,P%,L%,size%
      size%=2048

      DIM var% NOTEND AND 3, var% 1023
      DIM code% NOTEND AND 2047, code% size%-1

      FOR pass%=8 TO 10 STEP 2
        P%=var% : L%=code%-1
        [OPT pass%
        .temprc
        dd 0 : dd 0 : dd 0 : dd 0
        .tempx
        dd 0
        .tempy
        dd 0
        .grhdc
        dd 0
        .two
        dd 2
        ]
  
        P%=code% : L%=code%+size%-1
        [OPT pass%
        .antiline
        cld
        finit
        ;SYS "SetBoundsRect", @memhdc%, 0, 5
        push 5 ; DCB_ENABLE OR DCB_RESET
        push 0
        push @memhdc%
        call "SetBoundsRect"
        ;
        ;SYS `GdipDrawLine`, FN_gdipg, P%, FN_f4(x1), FN_f4(y1), FN_f4(x2), FN_f4(y2), @memhdc%
        ; push @memhdc%
        fld tbyte [^Posy] : call y2api : fstp dword [tempy] : push [tempy]  ;real80 to real32 for gdi+
        fld tbyte [^Posx] : call x2api : fstp dword [tempx] : push [tempx]
        fld tbyte [^oldy] : call y2api : fstp dword [tempy] : push [tempy]
        fld tbyte [^oldx] : call x2api : fstp dword [tempx] : push [tempx]
        push Pen%
        push [grhdc]
        call `GdipDrawLine`
        ;
        ;SYS "GetBoundsRect", @memhdc%, rc{}, 0
        push 0
        push temprc
        push @memhdc%
        call "GetBoundsRect"
        ;
        ;SYS "OffsetRect", rc{}, -@ox%, -@oy%
        push -@oy%
        push -@ox%
        push temprc
        call "OffsetRect"
        ;
        ;SYS "InvalidateRect", @hwnd%, rc{}, 0
        push 0
        push temprc
        push @hwnd%
        call "InvalidateRect"
        ret
        ;
        .y2api
        ;y=@vdu%!212-(y+@vdu%!4)/2
        fiadd dword [@vdu%+4]
        fidiv dword [two]
        fild dword [@vdu%+212]
        fsub st0,st1
        ret
        ;
        .x2api
        ;x=(x+@vdu%!0)/2
        fiadd dword [@vdu%]
        fidiv dword [two]
        ret
        ]
      NEXT pass%
      !grhdc=FN_gdipg
      ENDPROC

      DEF PROCexit
      ON TIME OFF : WAIT 30
      PROC_gdipdeletepen(Pen%)
      PROC_gdipexit
      ENDPROC
 
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 689
xx Re: Using GDIP with assembler
« Reply #1 on: Oct 25th, 2017, 10:20am »

on Oct 25th, 2017, 01:06am, svein wrote:
Any idea why ?

As far as I can see, there are two principal faults in your code:
  1. Pen% is a variable (it's modified in PROCnewpen) but your assembler code treats it as a constant. To fix this:

    Change this Code:
            push Pen% 

    To this Code:
            push [^Pen%] 

  2. Your y2api subroutine corrupts the floating-point stack (there are more 'pushes' than 'pops'). To fix this:

    Change this Code:
            fsub st0,st1 

    To this Code:
            fsubr 
Quote:
In fact, one can remove or replace @memhdc% in SYS 'GdipDrawLine' .... from the library. And it still works, how come ??

It doesn't still work, or at least not reliably. The @memhdc% activates the Critical Section that protects against concurrent access to the DC from two different threads (Windows DCs are not thread-safe and must be accessed from only one thread at a time). If you omit the @memhdc% you are trusting to luck that the interpreter thread and the GUI thread will not try to access the DC at the same time, which would fail.

Richard.
« Last Edit: Oct 25th, 2017, 10:25am by Richard Russell » User IP Logged

svein
New Member
Image


member is offline

Avatar




PM


Posts: 12
xx Re: Using GDIP with assembler
« Reply #2 on: Oct 26th, 2017, 06:59am »

Thank you !
Went over the code a million times without spotting the errors.
Svein
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

Donate $6.99 for 50,000 Ad-Free Pageviews!


This forum powered for FREE by Conforums ©
Sign up for your own Free Message Board today!
Terms of Service | Privacy Policy | Conforums Support | Parental Controls