Hi all,
I'm writing a software that receive data to USB port and draw same
graphics in same Windows TAB ( I'm using Visual Studio 2003 with
MFC ).
I have to draw the new scene only when the new data on USB port is
available and this data changing is not very fast (400 Hz - 400 sample
per second), on this I have an issue with the extra work to CPU, is
always upper than 90% probably because the WM_PAINT is so fast and the
software draws continuosly the same scene between two sample to USB
port.
To solve this issue I tried to eliminate the WM_PAINT in OpenGL and
call the OpenGL::OnPaint only when the new data occours but the
window's device context is 0 and I don't understand why.
Cau yuo help me?
Thank you
Alberto
|
|
0
|
|
|
|
Reply
|
Albe
|
5/19/2008 7:12:21 AM |
|
Albe wrote:
> Hi all,
> I'm writing a software that receive data to USB port and draw
> same graphics in same Windows TAB ( I'm using Visual Studio
> 2003 with MFC ).
> I have to draw the new scene only when the new data on USB port
> is available and this data changing is not very fast (400 Hz -
> 400 sample per second), on this I have an issue with the extra
> work to CPU, is always upper than 90% probably because the
> WM_PAINT is so fast and the software draws continuosly the same
> scene between two sample to USB port.
>
> To solve this issue I tried to eliminate the WM_PAINT in OpenGL
> and call the OpenGL::OnPaint only when the new data occours but
> the window's device context is 0 and I don't understand why.
>
> Cau yuo help me?
I don't know (anymore) why the DC in a manually issuied WM_PAINT
may be 0, however rest assured, that it doesn't matter to you:
Once created, the OpenGL context is independent of any DC, you
just have to make sure it's been made current (wglMakeCurrent).
Then you may use the context (i.e. render stuff) whenever you
see fit.
Wolfgang Draxinger
--
E-Mail address works, Jabber: hexarith@jabber.org, ICQ: 134682867
|
|
0
|
|
|
|
Reply
|
Wolfgang
|
5/19/2008 7:47:36 AM
|
|
Hi Wolfgang, thank you for reply but I'm sorry I don't understand your
message, I'm a newbie in OpenGL and I'm no expert in context ecc
ecc...
Just to be clear, I'm using this code
OGLPlo = new COpenGLControl();
....
CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW |
CS_OWNDC,NULL,(HBRUSH)StockObject(BLACK_BRUSH),NULL);
CreateEx( 0,className,"OpenGL",WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS
| WS_CLIPCHILDREN,
rect,parent,0);
....
dc = new CClientDC(this);
....
openGLDevice.create(dc->m_hDC);
bool OpenGLDevice::create(HDC& deviceContext,int stencil)
{
if (!deviceContext)
{
return false;
}
if (!setDCPixelFormat(deviceContext,stencil))
{
return false;
}
renderContext = wglCreateContext(deviceContext);
wglMakeCurrent(deviceContext, renderContext);
OpenGLDevice::deviceContext = deviceContext;
return true;
}
....
"COpenGLControl::InitGL"
....
"COpenGLControl::OnSize"
.... <---- ERROR dc=0
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
....
Disegna_Barre();
....
SwapBuffers(dc->m_hDC);
Here there are the main instruction used to create the OpenGL windows,
it works fine in normal way (when the OnPaint is called from WM_PAINT)
but when I try to call OnPaint without WM_PAINT (I'm calling OnPaint
from a function inside the ogl class each time a new data is
available) the dc is ok before the OnPaint calling, after the dc=0 and
an error occours in
SwapBuffers(dc->m_hDC);
I hope make clear, thank you in advance
Alberto
|
|
0
|
|
|
|
Reply
|
Albe
|
5/19/2008 8:47:07 AM
|
|
On May 19, 11:47=A0am, Albe <alberto_res...@tiscali.it> wrote:
> Hi Wolfgang, thank you for reply but I'm sorry I don't understand your
> message, I'm a newbie in OpenGL and I'm no expert in context ecc
> ecc...
> Just to be clear, I'm using this code
>
> OGLPlo =3D new COpenGLControl();
> ...
> CString className =3D AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW |
> CS_OWNDC,NULL,(HBRUSH)StockObject(BLACK_BRUSH),NULL);
>
> CreateEx( =A0 =A0 =A0 0,className,"OpenGL",WS_CHILD | WS_VISIBLE | WS_CLIP=
SIBLINGS
> | WS_CLIPCHILDREN,
> rect,parent,0);
> ...
> dc =3D new CClientDC(this);
> ...
> openGLDevice.create(dc->m_hDC);
>
> bool OpenGLDevice::create(HDC& deviceContext,int stencil)
> {
> =A0 =A0 =A0 =A0 if (!deviceContext)
> =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return false;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 if (!setDCPixelFormat(deviceContext,stencil))
> =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return false;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 renderContext =3D wglCreateContext(deviceContext);
> =A0 =A0 =A0 =A0 wglMakeCurrent(deviceContext, renderContext);
>
> =A0 =A0 =A0 =A0 OpenGLDevice::deviceContext =3D deviceContext;
>
> =A0 =A0 =A0 =A0 return true;}
>
> ...
> "COpenGLControl::InitGL"
> ...
> "COpenGLControl::OnSize"
> ... =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 <---- =A0ERROR dc=3D0
> glClear(GL_COLOR_BUFFER_BIT =A0 =A0 =A0| =A0GL_DEPTH_BUFFER_BIT);
> glLoadIdentity();
> ...
> Disegna_Barre();
> ...
> SwapBuffers(dc->m_hDC);
>
> Here there are the main instruction used to create the OpenGL windows,
> it works fine in normal way (when the OnPaint is called from WM_PAINT)
> but when I try to call OnPaint without WM_PAINT (I'm calling OnPaint
> from a function inside the ogl class each time a new data is
> available) the dc is ok before the OnPaint calling, after the dc=3D0 and
> an error occours in
>
> SwapBuffers(dc->m_hDC);
>
> I hope make clear, thank you in advance
>
> Alberto
Don't sweat over the paint messages, they are just artifact of
Microsoft's aged window manager. The window manager doesn't keep a
copy of the canvas contents so any time new portions of window are
revealed the window manager has to ask the application to
(re-)generate the content.
This is done much better on modern window managers, but that doesn't
help you much since it appears you are using the GDI (not a bad choise
since it caters for more flavours of windows than just the latest
Vista incarnations).
What you want to do is to beginpaint, do your rendering, endpaint and
repeat that as often as required. If you use FBO's and render-to-
texture, you can use the framebuffer object for the paint messages.
This would go into the category of useless optimizations as you need a
good performance (or so I would be inclined to guess) to begin with.
Might help with lower performance systems if you don't update the
image too frequently, go figure, could depend on how complex your
dataset is.
I didn't catch what you meant by 400 Hz, you want to update the scene
every time a new sample arrives, or batch updates? It will be rather
difficult to display your "signal" at 400 Hz, so it would make sense
to display snapshots of the data after specific time has elapsed for
example. This is kind of embarassingly trivial stuff but since you are
asking I'm forced to assume that there is something unstated in your
question. Care to be more specific what kind of trouble you are
experiencing again?
|
|
0
|
|
|
|
Reply
|
aku
|
5/19/2008 10:21:22 AM
|
|
Hi aku ankka,
my problem is that when the software shows the OpenGL the CPU works
around at 100% and I have to decrease this usage. I saw that if I
insert in the cycle the instruction
Sleep(1)
the CPU-usage decrease around 30% and it's right but the issue is that
the time to draw a scene is longer than the time between two sample
and, in this case, the software buffer the data.
My idea was to call the OnPaint only when a new data occours.
|
|
0
|
|
|
|
Reply
|
Albe
|
5/19/2008 12:57:37 PM
|
|
Albe wrote:
> Hi aku ankka,
> my problem is that when the software shows the OpenGL the CPU works
> around at 100% and I have to decrease this usage. I saw that if I
> insert in the cycle the instruction
>
> Sleep(1)
>
> the CPU-usage decrease around 30% and it's right but the issue is that
> the time to draw a scene is longer than the time between two sample
> and, in this case, the software buffer the data.
>
> My idea was to call the OnPaint only when a new data occours.
You shouldn't call OnPaint directly (or send WM_PAINT).
Instead, call InvalidateRect to tell Windows that you window needs
redrawing. Then Windows will post a WM_PAINT message. Call UpdateWindow
if you want the window to update immediately.
|
|
0
|
|
|
|
Reply
|
Jonno
|
5/19/2008 1:23:06 PM
|
|
Ok Jonno,
in the message manage I have deleted the WM_PAINT -> OnPaint in opengl
class and for each new data I call UpdateWindows, unfortunatly the
software don't draw the opengl windows.
:(
|
|
0
|
|
|
|
Reply
|
Albe
|
5/19/2008 2:27:09 PM
|
|
Albe wrote:
> Ok Jonno,
> in the message manage I have deleted the WM_PAINT -> OnPaint in opengl
> class and for each new data I call UpdateWindows, unfortunatly the
> software don't draw the opengl windows.
>
> :(
You still need the WM_PAINT message handler.
You wrote:
> I'm calling OnPaint from a function inside the ogl class each time a new data is
> available
Don't call OnPaint, call InvalidateRect (and optionally UpdateWindow)
instead.
|
|
0
|
|
|
|
Reply
|
Jonno
|
5/19/2008 2:54:39 PM
|
|
Hi Jonno,
probably owing to my bad english I did't explain correctly my problem:
I have an application named EKXXX with 3 classes
CEKXXXApp
CEKXXXDlg
COpenGLControl
in CEKXXXDlg there is a function named OnPaint associate at WM_PAINT
message and is
void CEKXXXDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
if (IsIconic())
{
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
in COpenGLControl there is a function named OnPaint associate at
WM_PAINT message and is
void COpenGLControl::OnPaint()
{
if(*datoOK)
{
/** OpenGL section **/
openGLDevice.makeCurrent();
DrawGLScene();
*datoOK=false;
temp_stato_old=tab;
}
}
When the software don't show opengl (there are two tab, in the first
there is a text box with the program description, in the second there
is an opengl windows that draw the data received from USB) the CPU
usage is about 10%, when the opengl is showed the CPU usage is about
98%, MORE.
I think that WM_PAINT is the same windows message and when it comes
the software runs OnPaint in CEKXXXDlg and OnPaint in COpenGLControl.
I can't use Sleep(x) becuse the system became too late, how I can do
to decrease CPU usage when the software shows OpenGL windows???
Sorry and thank you
Alberto
|
|
0
|
|
|
|
Reply
|
Albe
|
5/19/2008 3:47:09 PM
|
|
> void COpenGLControl::OnPaint()
> {
> if(*datoOK)
> {
> /** OpenGL section **/
>
> openGLDevice.makeCurrent();
> DrawGLScene();
> *datoOK=false;
>
> temp_stato_old=tab;
> }
> }
You're not validating your window here.
You need this line:
CPaintDC dc(this);
Even though you don't use the DC, the CPaintDC constructor calls
BeginPaint which tells Windows you have handled the WM_PAINT message.
Otherwise it will just keep sending more WM_PAINTs.
|
|
0
|
|
|
|
Reply
|
Jonno
|
5/19/2008 4:00:35 PM
|
|
On May 19, 3:57=A0pm, Albe <alberto_res...@tiscali.it> wrote:
> Hi aku ankka,
> my problem is that when the software shows the OpenGL the CPU works
> around at 100% and I have to decrease this usage. I saw that if I
> insert in the cycle the instruction
>
> Sleep(1)
>
> the CPU-usage decrease around 30% and it's right but the issue is that
> the time to draw a scene is longer than the time between two sample
> and, in this case, =A0the software buffer the data.
It doesn't benefit you to render faster than the refresh rate of the
display; rendering snapshots of the data shouldn't be a problem.
You got me hooked already, what's the data?
|
|
0
|
|
|
|
Reply
|
aku
|
5/20/2008 6:29:33 AM
|
|
I agree aku ankka, it doesn't benefit render faster than the refresh
rate of the display, I have to refresh only when a new data occours
but the WM_PAINT message is faster than the data. I have associated
the high CPU usage with the faster WM_PAINT message, I'm not sure that
it is correct, I tried to eliminate the WM_PAINT function in
OpenGLControl::OnPaint and the CPU usage decrease to 15-25%, I tried
to comment the code in OpenGLControl::OnPaint (I create the
openglwindows but I don't draw aniting) the CPU usage stay to 95-98%.
To USB I read a serial data composed to 10 bytes, the time betwenn two
samples is settable at 50 Hz, 100Hz, 400Hz and 1000Hz. My driver
maximum speed is 600 Hz (I have same problem when the device write at
1000 Hz but is not my priority now).
Thank you for support
|
|
0
|
|
|
|
Reply
|
Albe
|
5/20/2008 7:25:21 AM
|
|
On May 20, 4:25 am, Albe <alberto_res...@tiscali.it> wrote:
> I agree aku ankka, it doesn't benefit render faster than the refresh
> rate of the display, I have to refresh only when a new data occours
> but the WM_PAINT message is faster than the data. I have associated
> the high CPU usage with the faster WM_PAINT message, I'm not sure that
> it is correct, I tried to eliminate the WM_PAINT function in
> OpenGLControl::OnPaint and the CPU usage decrease to 15-25%, I tried
> to comment the code in OpenGLControl::OnPaint (I create the
> openglwindows but I don't draw aniting) the CPU usage stay to 95-98%.
>
> To USB I read a serial data composed to 10 bytes, the time betwenn two
> samples is settable at 50 Hz, 100Hz, 400Hz and 1000Hz. My driver
> maximum speed is 600 Hz (I have same problem when the device write at
> 1000 Hz but is not my priority now).
>
> Thank you for support
you must be pooling when reading from USB
can you switch to a blocking I/O ? this will save CPU resources a lot
|
|
0
|
|
|
|
Reply
|
Diego
|
5/21/2008 4:33:15 PM
|
|
On 21 Mag, 18:33, Diego <jose.di...@gmail.com> wrote:
> On May 20, 4:25 am, Albe <alberto_res...@tiscali.it> wrote:
>
> > I agree aku ankka, it doesn't benefit render faster than the refresh
> > rate of the display, I have to refresh only when a new data occours
> > but the WM_PAINT message is faster than the data. I have associated
> > the high CPU usage with the faster WM_PAINT message, I'm not sure that
> > it is correct, I tried to eliminate the WM_PAINT function in
> > OpenGLControl::OnPaint and the CPU usage decrease to 15-25%, I tried
> > to comment the code in OpenGLControl::OnPaint (I create the
> > openglwindows but I don't draw aniting) the CPU usage stay to 95-98%.
>
> > To USB I read a serial data composed to 10 bytes, the time betwenn two
> > samples is settable at 50 Hz, 100Hz, 400Hz and 1000Hz. My driver
> > maximum speed is 600 Hz (I have same problem when the device write at
> > 1000 Hz but is not my priority now).
>
> > Thank you for support
>
> you must be pooling when reading from USB
> can you switch to a blocking I/O ? this will save CPU resources a lot
My problem is to control the WM_PAINT, this message arrives also when
the data is not available and this probably overload the CPU
|
|
0
|
|
|
|
Reply
|
Albe
|
5/22/2008 9:33:00 AM
|
|
> My problem is to control the WM_PAINT, this message arrives also when
> the data is not available and this probably overload the CPU
I already told you how to fix this. Add this line to
COpenGLControl::OnPaint()...
CPaintDC dc(this);
Otherwise Windows will keep sending more WM_PAINT messages.
|
|
0
|
|
|
|
Reply
|
Jonno
|
5/22/2008 10:24:50 AM
|
|
"Albe" <alberto_ressia@tiscali.it> schrieb im Newsbeitrag
news:53f0110b-6d35-4e32-9a57-8c7834c86e19@d1g2000hsg.googlegroups.com...
> Hi all,
> I'm writing a software that receive data to USB port and draw same
> graphics in same Windows TAB ( I'm using Visual Studio 2003 with
> MFC ).
> I have to draw the new scene only when the new data on USB port is
> available and this data changing is not very fast (400 Hz - 400 sample
> per second), on this I have an issue with the extra work to CPU, is
> always upper than 90% probably because the WM_PAINT is so fast and the
> software draws continuosly the same scene between two sample to USB
> port.
The problem with 90% CPU power and unneeded draws is that a bug in command
sequence.
Use one of these
- ValidateRect()
- DefWindowProc()
- [MFC] CWnd::OnPaint()
to stop WM_PAINT sending until new content.
Use InvalidateRect() to refresh area. Do not send manual WM_PAINT with
SendEvent() !!
>
> To solve this issue I tried to eliminate the WM_PAINT in OpenGL and
> call the OpenGL::OnPaint only when the new data occours but the
> window's device context is 0 and I don't understand why.
>
> Cau yuo help me?
>
> Thank you
>
> Alberto
Hope this helps.
Clemens
|
|
0
|
|
|
|
Reply
|
Clemens
|
5/24/2008 7:56:44 AM
|
|
Hi Clemens,
thak you very much for reply, probably I understand your suggestion, I
have implemented new instruction in the code
void COpenGLControl::OnPaint()
{
if(*datoOK)
{
InvalidateRect(Prova, true);
openGLDevice.makeCurrent();
DrawGLScene();
*datoOK=false;
temp_stato_old=tab;
}
else
{
ValidateRect(Prova);
}
}
"Prova" is CRect ogl windows where i draw with "DrawGLScene"
My idea based on Clemens's suggestion is that when the new data is
available I use InvalidateRect and when windows call WM_PAINT but the
data is not availabe I use ValidateRect.
Unfortunally, with this code the ogl is freezed, probably I don't use
correctly InvalidateRect.
|
|
0
|
|
|
|
Reply
|
Albe
|
5/26/2008 9:43:17 AM
|
|
Albe wrote:
> Hi Clemens,
> thak you very much for reply, probably I understand your suggestion, I
> have implemented new instruction in the code
>
> void COpenGLControl::OnPaint()
> {
> if(*datoOK)
> {
> InvalidateRect(Prova, true);
> openGLDevice.makeCurrent();
> DrawGLScene();
> *datoOK=false;
> temp_stato_old=tab;
> }
> else
> {
> ValidateRect(Prova);
> }
>
> }
Try this:
void COpenGLControl::OnPaint()
{
openGLDevice.makeCurrent();
DrawGLScene();
ValidateRect(Prova);
}
When you want to redraw, call InvalidateRect(Prova, true);
|
|
0
|
|
|
|
Reply
|
Jonno
|
5/27/2008 8:09:26 AM
|
|
|
17 Replies
190 Views
(page loaded in 0.201 seconds)
Similiar Articles:7/13/2012 10:55:43 AM
|