News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

GDI Vertical blank and vertical retrace test

Started by Siekmanski, April 16, 2018, 11:04:05 AM

Previous topic - Next topic

LordAdef

Quote from: Siekmanski on April 25, 2018, 05:10:33 AM
Own the window,  wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect

I have tested this and it works ( although still without a backbuffer )


According to my research, they don't use the ==TIMER also. The coder controls everything from the outside. ==TIMER has a fluctuation. I was doing my animation with ==TIMER and ==PAINT. It's a lot more steady without the two Marinus.

LordAdef

Quote from: caballero on April 25, 2018, 04:58:00 AM
W7 here, but you could post it here any way and we may have a look to it.


no problems. Tonight.


But I'll chase the win7 bug and send the exe too.

LordAdef

Quote from: Siekmanski on April 25, 2018, 05:10:33 AM
Own the window,  wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect

I have tested this and it works ( although still without a backbuffer )


Marinus,


According to msdn, using OWNED you also don't need to release the DC.




Siekmanski

How nice is that.
But this is logical, we own the DC.

Already spend hours reading MSDN to learn all about GDI and taking notes if I think it is useful. ( and all the different types of BitMaps   :icon_eek: )

from my notes I made,

    invoke  GetDC,hWnd
    mov     hFrontBufferDC,eax      ; Note that the handle to the DC can only be used by a single thread at any one time.
                                                 ; see GetDCEx function for clipping control.

MSDN: private DCs do not have to be released
Creative coders use backward thinking techniques as a strategy.


avcaballero

Quote from: Siekmanski on April 25, 2018, 05:10:33 AM
Own the window,  wc.style, CS_HREDRAW or CS_VREDRAW or CS_OWNDC
Call your routines from the timer and the hdc from the owned window
Don't use WM_PAINT, BeginPaint and EndPaint
Don't use InvalidateRect

I have tested this and it works ( although still without a backbuffer )
Didn't work to me

/* ----------------------------------------------------------------------------
   -       Plantilla Programación Gráfica - SWGPTG -  Tiny C                  -
   -----                                                                  -----
   -       AUTOR   : Alfonso Víctor Caballero Hurtado                         -
   -----                                                                  -----
   -       VERSION : 1.0                                                      -
   -----                                                                  -----
   -      (c) 2018. http://www.abreojosensamblador.net                        -
   -                Small Windows Graphics Programming Tutorial with GDI      -
   ---------------------------------------------------------------------------- */

#define cdXPos          CW_USEDEFAULT
#define cdYPos          CW_USEDEFAULT
#define cdYSize         400
#define cdXSize         640 //cdYSize*1.6
#define cdColFondo      0
#define MAIN_ICON       100    //  IDI_APPLICATION
#define cdVCursor       IDC_ARROW
#define cdVBarTipo      0
#define cdVBtnTipo      WS_OVERLAPPEDWINDOW
#define cdIdTimer       1
#define DIB_RGB_COLORS  0

#include <windows.h>

// Prototipos de funciones
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

// Variables globales
int               *pMainDIB    = NULL;
int                vdxClient, vdyClient, motion = 0;
BITMAPINFOHEADER   bi = {sizeof(BITMAPINFOHEADER),cdXSize,-cdYSize,1,32,0,0,0,0,0,0};

void PintaObjeto (void) {
  int x, y, k, a;
  for (y = 0; y < cdYSize; y++)
    for (x = 0; x < cdXSize; x++, k++) {
      a = ((x-motion)^(y+motion))&255;
      *(pMainDIB + k) =  0x400000 | (a<<8) | a;
    }
  motion++;
}

void Inicio (void) {
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static   HDC               bufDIBDC;
     static   HBITMAP           hMainDIB;
     static   HDC               hMainDC ;
              PAINTSTRUCT       ps ;
     static   HGDIOBJ           hOldDIB=0, hGDITmp;
              int               bResult;

     switch (message)
     {
     case WM_CHAR :
          if (wParam == VK_ESCAPE) {
            goto     wmDestruimos;
          } 
          return 0 ;

     case WM_CREATE:
          hMainDC = GetDC(hWnd);
         
          // Crea un búfer dib para PintaObjeto. pMainDIB es un puntero a él
          bufDIBDC = CreateCompatibleDC (hMainDC);
          hMainDIB = CreateDIBSection(hMainDC, (BITMAPINFO *) &bi, DIB_RGB_COLORS, (void **) &pMainDIB, NULL, 0);
          hOldDIB  = SelectObject (bufDIBDC, hMainDIB);
       
          //ReleaseDC (hWnd, hMainDC);   // Libera device context
         
          Inicio ();
          SetTimer (hWnd, cdIdTimer, 20, NULL) ;
          return 0 ;

     case WM_TIMER :
          //InvalidateRect (hWnd, NULL, FALSE) ;
          PintaObjeto ();
          //bResult = StretchBlt (GetDC(hWnd), 0, 0, vdxClient, vdyClient, bufDIBDC, 0, 0, cdXSize, cdYSize, SRCCOPY);
          bResult = StretchBlt (hMainDC, 0, 0, vdxClient, vdyClient, bufDIBDC, 0, 0, cdXSize, cdYSize, SRCCOPY);
          return 0 ;

     case WM_SIZE :
          vdxClient = lParam & 0xFFFF;
          vdyClient = lParam >> 0x10;
          return 0 ;

     /*case WM_PAINT :
          hMainDC = BeginPaint(hWnd, &ps);
          EndPaint(hWnd, &ps);
          return 0 ; */

     case WM_DESTROY :
          wmDestruimos:
          KillTimer (hWnd, cdIdTimer) ;
          hGDITmp = SelectObject (bufDIBDC, hOldDIB);
          bResult = DeleteDC (bufDIBDC);
          bResult = DeleteObject (hMainDIB);
          bResult = DestroyWindow (hWnd);
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hWnd, message, wParam, lParam) ;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     RECT   WRect;
     static TCHAR szAppName[] = TEXT ("SWGPTG") ;
     HWND         hWnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hbrBackground = cdColFondo ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     wndclass.hInstance     = GetModuleHandle (NULL) ;
     wndclass.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(MAIN_ICON)) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      TEXT ("Error"), MB_ICONERROR) ;
          return 0 ;
     }

     SetRect (&WRect, 0, 0, cdXSize, cdYSize);
     AdjustWindowRectEx (&WRect, cdVBtnTipo, 0, cdVBarTipo);
     WRect.bottom += GetSystemMetrics (SM_CYCAPTION) + 1;
     WRect.bottom += GetSystemMetrics (SM_CYFIXEDFRAME)*2 + 1;
     WRect.right  += (GetSystemMetrics(SM_CXFIXEDFRAME) + 1) * 2;
     WRect.left    = (GetSystemMetrics (SM_CXSCREEN) - WRect.right)/2;
     WRect.top     = (GetSystemMetrics (SM_CYSCREEN) - WRect.bottom) / 3;
     
     hWnd = CreateWindow (szAppName, TEXT ("Plantilla SWGPTG - (c) abreojosensamblador.net"),
                          cdVBtnTipo,//WS_OVERLAPPEDWINDOW,
                          WRect.left,WRect.top,WRect.right,WRect.bottom,
                          NULL, NULL, hInstance, NULL) ;

     ShowWindow (hWnd, iCmdShow) ;
     UpdateWindow (hWnd) ;

     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

Siekmanski

It works for me,  no WM_PAINT BeginPaint and EndPaint in my source.
Although only tested with DrawText directly to the Window.

Got the interrupt timer implemented and synchronized it with the VerticalBlank.
It stays nicely within the VerticalBlank period at 60 Hz.  :eusa_dance:

Is FillRect the fastest way to clear a buffer?
Or are there different ways to clear buffers in SytemMem and VideoMem.

Next step is the double buffering and drawing some graphics.
Study the DIB and DDB first, there are so many possibilities in GDI.  :dazzled:

Hope it works....

EDIT: When done drawing I validate the window with " invoke  ValidateRect,hWnd,NULL "

MSDN: Handle to the window whose update region is to be modified. If this parameter is NULL, the system invalidates and redraws all windows.
Creative coders use backward thinking techniques as a strategy.

Siekmanski

Made some adjustments to the interrupt timer routine.
It now checks if the vertical blank signal is found.
If it is not supported by the video card it tries to sets the most accurate stable timer value possible.
Probably a bit faster than the monitor refresh rate.

Hope it works now for FORTRANS too on Windows XP.

Alex could you test it on XP too?

I'm very satisfied with the result and hope it runs stable on other machines too.

Feedback would be nice, thanks in advance.  :t
Creative coders use backward thinking techniques as a strategy.

felipe

Seems to be all ok here in my machine (the desktop one).  :t

jj2007

Quote from: Siekmanski on April 26, 2018, 10:48:23 PMFeedback would be nice, thanks in advance.  :t
Win7-64: 59.838, 0.0166, pretty stable

On my XP VM, it chokes with "a problem" at offset 163b :(

FORTRANS

Hi,

   Tried it and got the same error pop-up offering to send an error
report to Microsoft.  Should I try and copy some of the information
out of a window?

Regards,

Steve N.

Siekmanski

I've got all error handling active.
I think maybe an old video card issue or XP doesn't support it?

QuoteShould I try and copy some of the information
out of a window?

That would be nice, with that info I can track down the error, I hope.  :icon14:

BTW I've got the backbuffer running and blitting to the frontbuffer, no flickering anymore.
Up to some graphics drawing.  :biggrin:
Creative coders use backward thinking techniques as a strategy.

FORTRANS

Hi,

   Well, here are some screen shots of the pop-up.  And a file
that was to be sent.  They don't make it easy to copy stuff.

HTH,

Steve N.

jj2007

Quote from: jj2007 on April 27, 2018, 12:38:00 AMOn my XP VM, it chokes with "a problem" at offset 163b :(

00401627            ³.  C3                   retn
00401628            ³>  0BDB                 or ebx, ebx
0040162A            ³. 74 06                jz short 00401632
0040162C            ³.  53                   push ebx                          ; ÚhModule
0040162D            ³.  E8 ECF9FFFF          call <jmp.&kernel32.FreeLibrary>  ; ÀKERNEL32.FreeLibrary
00401632            ³>  0BFF                 or edi, edi
00401634            ³. 74 0D                jz short 00401643
00401636            ³.  8BC7                 mov eax, edi
00401638            ³.  50                   push eax
00401639            ³.  8B00                 mov eax, [eax]
0040163B            ³.  FF50 08              call near [eax+8]                 ; ####### This is offset 163b  #######
0040163E            ³.  BF 00000000          mov edi, 0

Siekmanski

Thanks Steve.

Jochen ,I see, it's the realease of an interface. I'll have a look tomorrow.

Thanks guys.
Creative coders use backward thinking techniques as a strategy.