Help - Search - Members - Calendar
Full Version: Some questions from a component noob :)
Hydrogenaudio Forums > Hosted Forums > foobar2000 > Development - (fb2k)
demalion
I'm working on a component as a way to learn C++ programming and Windows programming. I've got most of the backend functionality working (works as desired so far in a test implementation I've done as a simple windowed app), but I just started implementing it as a component and I'm having some difficulties. huh.gif

My questions come in a few categories:
  • Warnings from implementation based on foo_tutorial. What do these mean? There are some casts in the tutorial that I don't understand, and I want to make sure I don't have typos or impementation issues that will cause problems.
    • CODE
      foobar2000\helpers\win32_dialog.h(103) : warning C4312: 'reinterpret_cast' : conversion from 'LONG' to 'dialog_helper::dialog_modeless_v2 *' of greater size
    • CODE
      : warning C4312: 'reinterpret_cast' : conversion from 'LONG' to 'window_ffverse *' of greater size
    • CODE
      : warning C4244: 'argument' : conversion from 'LONG_PTR' to 'LONG', possible loss of data
  • t_font_description from shared library. I'm just learning some of the WinAPI fundamentals, so maybe the fields correspond directly to certain Windows font structures, but I'm using D3DXFont which takes pixel height. As it stands, it looks like some sort of conversion with the current display DPI and the m_height_dpi done manually, or some sort of data extraction using the font handle from create(), is what I need to do, but I haven't found the solution yet. Any hint?
  • Using ATL/WTL. I was planning to explore ATL/WTL for internet access functionality, as well as implementing the UI, but ran into an initial hurdle where it seems references to shared.lib functions weren't compatible. Is this expected behavior, or did I get something wrong in my attempt? How painful will it be to implement everything in, for example, foo_tutorial without shared.lib? Is it just u* functions used in your application, or are there many things like t_font_description in shared.h that will impact certain API function usage even without using any u* functions?
  • High Time Resolution. I'm going to be looking around some source code for ideas, but perhaps someone could point me in the direction of the simplest way to get high time resolution execution, i.e., get your component's function to be called very often.
    I'm trying to get this function code to execute often enough for decent animation:
    CODE

    static_api_ptr_t<play_control> pc;
    timeindex = static_cast<millisecond>(1000.0 * pc->playback_get_position());
    redraw_window();

    BTW, is the initalization of pc a slowdown? Would declaring it static help?
    I see on_playback_time, which would be exactly what I could use if it were called atleast every 10 milliseconds (I'd implement some type of quick evaluation to return without rendering if time had changed by a larger interval that allowed good animation) or some such instead of every second.
    I see on_playback_dynamic_info, which is either being slowed down by my foobar config, my improper use, or just doesn't have a high time resolution, as it doesn't perform well with the above code inside it. I also see on_playback_dynamic_info_track, which I'm ignoring at the moment since it is listed as being updated less often than dynamic_info, but perhaps I should experiment?
    I see on_playback_seek, and have it implemented.

    I have other ideas for how to tackle this, but am not sure how to go about them.
    Is there some sort of other hook I could place this code into that would be executed more often? I have just begun to know where to even look to find out about hooks in the foobar API, but this is something I plan on looking into.
    I don't know how to implement the equivalent of a message loop where I could control my own timing, as things are implemented by on_message and WndProc (as done in the tutorial). Should I experiment to see how often the WndProc calls are made, and try to implement something to render in that function? Is there a Windows API way to attach a timer to send timer events of a certain interval as messages so the message handler would get called more often?
    Some sort of solution that fits the above, or answers to some of the above questions that would help me remove the current issue I have with time chunkiness, are things I can implement right now. So how about it? smile.gif
    In terms of future reimplementation, I've thought that implementing a separate thread to handle animation, independent of foobar, and I could just have dynamic_info try to help keep the thread's timing in sync. But this would take quite a lot of work (for me) and things I don't know yet, I believe. I'll be looking into this anyway if I have reason to believe the above solutions are inefficient or performance hogs (even if I can get it to work), but that's a long term plan. However, if you can provide some info, or point me towards some, that makes it easy to understand how to do this, that would be appreciated.

Anyone one up with helping me with some of the above? It would be much appreciated.
demalion
OK, got a solution beginning to work with SetTimer/KillTimer and WM_TIMER (after struggling with and abandoning hacking class member callback with SetTimer as seeming to require at least as much overhead as process_message/switch), but I'm still interested in any info on efficiency drawbacks to this as well as any answers to other questions or other proposed solutions. smile.gif
david_dl
QUOTE(demalion @ Sep 21 2006, 11:24) *
I'm working on a component as a way to learn C++ programming and Windows programming. I've got most of the backend functionality working (works as desired so far in a test implementation I've done as a simple windowed app), but I just started implementing it as a component and I'm having some difficulties. huh.gif

My questions come in a few categories:
  • Warnings from implementation based on foo_tutorial. What do these mean? There are some casts in the tutorial that I don't understand, and I want to make sure I don't have typos or impementation issues that will cause problems.
    • CODE
      foobar2000\helpers\win32_dialog.h(103) : warning C4312: 'reinterpret_cast' : conversion from 'LONG' to 'dialog_helper::dialog_modeless_v2 *' of greater size
    • CODE
      : warning C4312: 'reinterpret_cast' : conversion from 'LONG' to 'window_ffverse *' of greater size
    • CODE
      : warning C4244: 'argument' : conversion from 'LONG_PTR' to 'LONG', possible loss of data
These are nothing to be concerned about, they will go away if you turn off 64-bit compatibility warnings in projects settings.
QUOTE
  • t_font_description from shared library. I'm just learning some of the WinAPI fundamentals, so maybe the fields correspond directly to certain Windows font structures, but I'm using D3DXFont which takes pixel height. As it stands, it looks like some sort of conversion with the current display DPI and the m_height_dpi done manually, or some sort of data extraction using the font handle from create(), is what I need to do, but I haven't found the solution yet. Any hint?
  • I've never used Direct3D, but i would suggest searching for CreateFont on the MSDN and having a read of that.
    QUOTE
  • Using ATL/WTL. I was planning to explore ATL/WTL for internet access functionality, as well as implementing the UI, but ran into an initial hurdle where it seems references to shared.lib functions weren't compatible. Is this expected behavior, or did I get something wrong in my attempt? How painful will it be to implement everything in, for example, foo_tutorial without shared.lib? Is it just u* functions used in your application, or are there many things like t_font_description in shared.h that will impact certain API function usage even without using any u* functions?
  • High Time Resolution. I'm going to be looking around some source code for ideas, but perhaps someone could point me in the direction of the simplest way to get high time resolution execution, i.e., get your component's function to be called very often.
    I'm trying to get this function code to execute often enough for decent animation:
    CODE

    static_api_ptr_t<play_control> pc;
    timeindex = static_cast<millisecond>(1000.0 * pc->playback_get_position());
    redraw_window();

    BTW, is the initalization of pc a slowdown? Would declaring it static help?
    I see on_playback_time, which would be exactly what I could use if it were called atleast every 10 milliseconds (I'd implement some type of quick evaluation to return without rendering if time had changed by a larger interval that allowed good animation) or some such instead of every second.
    I see on_playback_dynamic_info, which is either being slowed down by my foobar config, my improper use, or just doesn't have a high time resolution, as it doesn't perform well with the above code inside it. I also see on_playback_dynamic_info_track, which I'm ignoring at the moment since it is listed as being updated less often than dynamic_info, but perhaps I should experiment?
    I see on_playback_seek, and have it implemented.

    I have other ideas for how to tackle this, but am not sure how to go about them.
    Is there some sort of other hook I could place this code into that would be executed more often? I have just begun to know where to even look to find out about hooks in the foobar API, but this is something I plan on looking into.
    I don't know how to implement the equivalent of a message loop where I could control my own timing, as things are implemented by on_message and WndProc (as done in the tutorial). Should I experiment to see how often the WndProc calls are made, and try to implement something to render in that function?
  • Do NOT do this. It is most definately evil and will certainly backfire.
    QUOTE
    Is there a Windows API way to attach a timer to send timer events of a certain interval as messages so the message handler would get called more often?
    Yes, WM_TIMER/SetTimer/KillTimer. It is important to call KillTimer after receiving WM_TIMER and before doing your rendering, and calling SetTimer again afterwards so that the animation wont continue for an extra half hour whilst leaving foobar unresponsive on a slow system. tongue.gif
    QUOTE

    Some sort of solution that fits the above, or answers to some of the above questions that would help me remove the current issue I have with time chunkiness, are things I can implement right now. So how about it? smile.gif
    In terms of future reimplementation, I've thought that implementing a separate thread to handle animation, independent of foobar, and I could just have dynamic_info try to help keep the thread's timing in sync. But this would take quite a lot of work (for me) and things I don't know yet, I believe. I'll be looking into this anyway if I have reason to believe the above solutions are inefficient or performance hogs (even if I can get it to work), but that's a long term plan. However, if you can provide some info, or point me towards some, that makes it easy to understand how to do this, that would be appreciated.Anyone one up with helping me with some of the above? It would be much appreciated.
    foosion
    QUOTE(demalion @ Sep 21 2006, 00:24) *
    • Warnings from implementation based on foo_tutorial. What do these mean? There are some casts in the tutorial that I don't understand, and I want to make sure I don't have typos or impementation issues that will cause problems.
    You can ignore those as long as you are compiling a 32 bit DLL. Given that there is no 64 bit version of foobar2000, that is what you will need to do anyway.

    QUOTE(demalion @ Sep 21 2006, 00:24) *
    • t_font_description from shared library. I'm just learning some of the WinAPI fundamentals, so maybe the fields correspond directly to certain Windows font structures, but I'm using D3DXFont which takes pixel height. As it stands, it looks like some sort of conversion with the current display DPI and the m_height_dpi done manually, or some sort of data extraction using the font handle from create(), is what I need to do, but I haven't found the solution yet. Any hint?
    This structure corresponds to LOGFONT from the Windows Platform SDK. See its description on MSDN for a formula to obtain a pixel size for a given display.

    QUOTE(demalion @ Sep 21 2006, 00:24) *
    • Using ATL/WTL. I was planning to explore ATL/WTL for internet access functionality, as well as implementing the UI, but ran into an initial hurdle where it seems references to shared.lib functions weren't compatible. Is this expected behavior, or did I get something wrong in my attempt? How painful will it be to implement everything in, for example, foo_tutorial without shared.lib? Is it just u* functions used in your application, or are there many things like t_font_description in shared.h that will impact certain API function usage even without using any u* functions?
    Using ATL/WTL is entirely doable. foobar2000 internally uses UTF-8, so you need to take care to correctly convert strings. You can use pfc::stringcvt::string_os_from_utf8 to pass a UTF-8 string to ATL/WTL functions, and pfc::stringcvt::string_utf8_from_os for the other way.

    QUOTE(demalion @ Sep 21 2006, 00:24) *
    • High Time Resolution. I'm going to be looking around some source code for ideas, but perhaps someone could point me in the direction of the simplest way to get high time resolution execution, i.e., get your component's function to be called very often.
    I see you solved that already. The playback callbacks you mentioned aren't intended for use as timers. smile.gif

    QUOTE(demalion @ Sep 21 2006, 00:24) *
    BTW, is the initalization of pc a slowdown? Would declaring it static help?
    If you want to cache the pointer in a member or global variable, you should take care to release it in initquit::on_quit(). You'll have to use a manually initialised service_ptr_t instead of a static_api_ptr_t as well. Given that static_api_ptr_t is quite fast though, I wouldn't bother with that unless your code uses it really often.

    QUOTE(demalion @ Sep 21 2006, 00:24) *
    I don't know how to implement the equivalent of a message loop where I could control my own timing, as things are implemented by on_message and WndProc (as done in the tutorial). Should I experiment to see how often the WndProc calls are made, and try to implement something to render in that function? Is there a Windows API way to attach a timer to send timer events of a certain interval as messages so the message handler would get called more often?
    You could run your own message loop in a separate thread, but that prevents you from easily accessing foobar2000 APIs that can only be called from the main thread.
    demalion
    First, thanks a bunch to you both for the clear and very informative answers! biggrin.gif

    I'll be working on some debugging, clean up, and tracking down some issues (font requester problem and failing to let foobar paint while the plugin is running) that might or might not be related to the following question:


    OK, I still want to experiment with WM_TIMER for lowering CPU usage, but the fixes I made in the process of working on its implementation seem to allow fast updating without any timers at all, and just using WM_PAINT. I don't understand this and why WM_PAINT is updating so often...unless it is related to the above problems, it isn't undesirable, but it is unexpected so I can't evaluate whether it is or not ATM.
    AFAICS the tutorials "RedrawWindow" call is triggering WM_PAINT (is it done this way for any other reason? I'm planning to do otherwise to avoid all the messaging overhead, etc.), but the only playback_call functions I have ATM are stop and new_track and the updates are happening often enough to have low millisecond resolution. Could it be some program I have installed causing this, or should I have expected this? Educate me more please smile.gif.
    foosion
    QUOTE(demalion @ Sep 21 2006, 17:54) *
    AFAICS the tutorials "RedrawWindow" call is triggering WM_PAINT (is it done this way for any other reason? I'm planning to do otherwise to avoid all the messaging overhead, etc.)
    Indeed, RedrawWindow is used to trigger repainting via WM_PAINT. There might be other reasons why your window needs repainting, so you should do this with a WM_PAINT handler.

    Your descriptions makes me wonder if your WM_PAINT uses BeginPaint/EndPaint. Not using this would imply that the update region is not validated - marked as not needing repainting - which would cause the system to generate another WM_PAINT event as soon as your handler returns.
    demalion
    QUOTE(foosion @ Sep 21 2006, 12:14) *

    QUOTE(demalion @ Sep 21 2006, 17:54) *
    AFAICS the tutorials "RedrawWindow" call is triggering WM_PAINT (is it done this way for any other reason? I'm planning to do otherwise to avoid all the messaging overhead, etc.)
    Indeed, RedrawWindow is used to trigger repainting via WM_PAINT. There might be other reasons why your window needs repainting, so you should do this with a WM_PAINT handler.

    Your descriptions makes me wonder if your WM_PAINT uses BeginPaint/EndPaint. Not using this would imply that the update region is not validated - marked as not needing repainting - which would cause the system to generate another WM_PAINT event as soon as your handler returns.


    Ah, I think we're on the right trail. I have my WNDCLASSEX hbrBackground set to NULL, so I thought I didn't need to use BeginPaint/EndPaint. I didn't realize Windows had some sort of cooperative dependency on BeginPaint/EndPaint and letting it know the WM_PAINT was validated...? So if this is the problem, thanks again! smile.gif

    Would any of the WNDCLASSEX CS_ flags have anything to do with this? One of the REDRAW ones or maybe OWNDC? (EDIT: Nope AFAICS, but I'm recalling something about dirty region updating or such when I was researching WNDCLASS or something related. I guess I'll look, though it is working now with no apparent performance hit from overhead). In the meantime I'll try to fix things with adding a paint struct and BeginPaint/EndPaint, or maybe having BeginPaint/EndPaint in WM_PAINT (no other faster way to let windows know the WM_PAINT is validated? Does EndPaint do that?) with nothing else, and having the rendering done in WM_TIMER alone.

    Be sure to let me know if I'm wandering off that trail in any of the above. huh.gif
    foosion
    QUOTE(demalion @ Sep 21 2006, 18:37) *
    no other faster way to let windows know the WM_PAINT is validated?
    I'm not sure what you mean by faster way - one that involves slightly less typing or one where you can avoid reading the documentation on MSDN yourself (and thus understanding how and why certain things are done)?
    demalion
    QUOTE(foosion @ Sep 21 2006, 13:13) *

    QUOTE(demalion @ Sep 21 2006, 18:37) *
    no other faster way to let windows know the WM_PAINT is validated?
    I'm not sure what you mean by faster way - one that involves slightly less typing or one where you can avoid reading the documentation on MSDN yourself (and thus understanding how and why certain things are done)?

    huh.gif
    Well, neither was intended, but perhaps from your perspective the latter? I am reading the MSDN documentation, but I am missing things like the LOGFONT formula mentioned above since I had looked at LOGFONT before, and I'm sorry if that seems like I'm avoiding reading the documentation?

    Overall, I was seeking either a way to let Windows know not to worry about being concerned about painting my window, or to simply inform Windows as quickly as possible to "not worry, this WM_PAINT has been acknowledged and as far as my app is concerned the window is now validated" without what I perceive as window management overhead that might be occurring in BeginPaint/EndPaint. The sentence you quote was a musing that perhaps simply EndPaint by itself with an empty or clientrect sized paint structure would accomplish this, without a BeginPaint. I didn't understand the answer to this from the documentation, but perhaps I missed something (ah, ValidateRgn or ValidateRect I guess I'll have to look into?).

    In any case, what I have now is a WM_SIZE that updates my rendering size, a WM_PAINT that does the same within a BeginPaint/EndPaint pair, a WM_TIMER that executes diagnostic timing code and the rendering function with the retrieved playback_get_position , "beginrender/endrender" code that is always executed by the rendering function and now incorporates "KillTimer/SetTimer", and "init/cleanup" code for rendering that does "SetTimer/KillTimer". This all seems to hang together, so I guess I'll review at a later optimization stage. Thanks again for the help so far.
    david_dl
    QUOTE(demalion @ Sep 22 2006, 07:01) *
    QUOTE(foosion @ Sep 21 2006, 13:13) *

    QUOTE(demalion @ Sep 21 2006, 18:37) *
    no other faster way to let windows know the WM_PAINT is validated?
    I'm not sure what you mean by faster way - one that involves slightly less typing or one where you can avoid reading the documentation on MSDN yourself (and thus understanding how and why certain things are done)?

    huh.gif
    Well, neither was intended, but perhaps from your perspective the latter? I am reading the MSDN documentation, but I am missing things like the LOGFONT formula mentioned above since I had looked at LOGFONT before, and I'm sorry if that seems like I'm avoiding reading the documentation?

    Overall, I was seeking either a way to let Windows know not to worry about being concerned about painting my window, or to simply inform Windows as quickly as possible to "not worry, this WM_PAINT has been acknowledged and as far as my app is concerned the window is now validated" without what I perceive as window management overhead that might be occurring in BeginPaint/EndPaint. The sentence you quote was a musing that perhaps simply EndPaint by itself with an empty or clientrect sized paint structure would accomplish this, without a BeginPaint. I didn't understand the answer to this from the documentation, but perhaps I missed something (ah, ValidateRgn or ValidateRect I guess I'll have to look into?).

    Yes this is what ValidateRect does (use NULL for the RECT argument if you have painted the entire window.) I would only use ValidateRect if you are not using GDI to do the drawing (otherwise BeginPaint/EndPaint are no slower.) Make sure you return 0(? Check on the msdn) after calling EndPaint/ValidateRect to let windows know you've handled the message.

    BTW. RedrawWindow completely redraws the entire window, including erasing the background (depending on the flags you set). InvalidateRect may be better for what you want. In any case, use one of these or a similar function to trigger the WM_PAINT function from your WM_TIMER, manually sending WM_PAINT or calling your rendering code directly will cause unnecessary resource usage when the window is not visible.
    QUOTE


    In any case, what I have now is a WM_SIZE that updates my rendering size, a WM_PAINT that does the same within a BeginPaint/EndPaint pair, a WM_TIMER that executes diagnostic timing code and the rendering function with the retrieved playback_get_position , "beginrender/endrender" code that is always executed by the rendering function and now incorporates "KillTimer/SetTimer", and "init/cleanup" code for rendering that does "SetTimer/KillTimer". This all seems to hang together, so I guess I'll review at a later optimization stage. Thanks again for the help so far.
    demalion
    QUOTE(foosion @ Sep 21 2006, 04:30) *

    ...
    QUOTE(demalion @ Sep 21 2006, 00:24) *
    • t_font_description from shared library. I'm just learning some of the WinAPI fundamentals, so maybe the fields correspond directly to certain Windows font structures, but I'm using D3DXFont which takes pixel height. As it stands, it looks like some sort of conversion with the current display DPI and the m_height_dpi done manually, or some sort of data extraction using the font handle from create(), is what I need to do, but I haven't found the solution yet. Any hint?
    This structure corresponds to LOGFONT from the Windows Platform SDK. See its description on MSDN for a formula to obtain a pixel size for a given display.
    ...


    OK, back to this. After wasting lots of time (going down false trails due to unexpected casting issues and general uncertainty), I want to make it so an easily searchable solution to this question can be found here (assuming my conclusion is correct, which it seems to be so far, it should make it pretty unambiguous too).
    Skip to Conclusion to skip my discussion.

    The t_font_description structure stores a size (at least, when returned from the font requester) in m_height that is the "dots"(points?) of a character corresponding to its own assumed rendering space to remove ambiguity to the data (AFAICS). In other words, it is the size of the font in the same "dots" that m_height_dpi tells you "how many of them are in an inch" (m_height_Dots Per Inch), so that m_height/m_height_dpi is the fraction of an inch that the preview took up on your screen, assuming your windows screen DPI setting (tells it how many pixels in an inch) was accurate.

    What this means is that to render the font in the same size, the piece of data you need besides what t_font_description stores is the DPI of what you want to render to. Since the font requester previews in screen space, to get the same pixel size font as the preview, you need the screen DPI that the font requester was using to render:
    CODE
    int ScreenDPI = GetDeviceCaps(GetDC(window handle), LOGPIXELSY);

    Basically, you use it to calculate the pixels required to render a certain fraction of an inch that the ratio of m_height/m_height_dpi tells you, by ScreenDPI * m_height/m_height_dpi (or, using a Windows API function designed to do this accurately with 32 bit ints in integer space, MulDiv(ScreenDPI, m_height, m_height_dpi); ).


    The next step is to give this data in a way compatible with what it was measuring the height of exactly (there are only 2 methods of measuring height here to worry about..in the wider world of measuring font height there seems to be a jungle of methods ohmy.gif). This isn't actually complicated (again, if my conclusions are correct), merely a pitfall you have to avoid...you have to pass the calculated value to CreateFont functions as a negative (the size matching we want) instead of a positive (not what we want) so it knows to match against (EDIT:character height, not cell height, seems I misread before).

    Conclusion

    So, when creating a font based on t_font_description data stored by the shared.lib popup font requester, as done in foo_tutorial1, and using a different CreateFont function so you can get something besides HFONT (the create font built into t_font_description can already give you an HFONT without worrying about all this), like D3DXCreateFont, simply use the equivalent of the following as the "Height" parameter (with a width of 0 to let windows handle proportional fonts, etc.):
    Pseudocode:
    CODE

    - ( ScreenDPI * m_height / m_height_dpi )


    Nice and simple...until someone points out that I went wrong somewhere. blink.gif
    EDIT: clearer wording
    demalion
    QUOTE(david_dl @ Sep 22 2006, 00:18) *

    ...
    BTW. RedrawWindow completely redraws the entire window, including erasing the background (depending on the flags you set). InvalidateRect may be better for what you want. In any case, use one of these or a similar function to trigger the WM_PAINT function from your WM_TIMER, manually sending WM_PAINT or calling your rendering code directly will cause unnecessary resource usage when the window is not visible.
    QUOTE


    In any case, what I have now is a WM_SIZE that updates my rendering size, a WM_PAINT that does the same within a BeginPaint/EndPaint pair, a WM_TIMER that executes diagnostic timing code and the rendering function with the retrieved playback_get_position , "beginrender/endrender" code that is always executed by the rendering function and now incorporates "KillTimer/SetTimer", and "init/cleanup" code for rendering that does "SetTimer/KillTimer". This all seems to hang together, so I guess I'll review at a later optimization stage. Thanks again for the help so far.




    So, basically, I need to call InvalidateRect from my WM_TIMER instead of the rendering function, and then have the rendering function followed by a ValidateRect under WM_PAINT. This way, when the window is completely occluded, WM_PAINT won't be called even though the clientrect is invalidated, since windows is smart enough to handle that, and so the render code won't be called, right? Thanks smile.gif
    Hmm, giving some thought, I don't like this solution, since it causes Windows to set a message (WM_PAINT in a roundabout way) in response to a message already given (WM_TIMER). I'm not sure this saves much in the way of resources since I think D3D would be holding onto its resources anyway? And it doubles message handling, however much code and parameter passing that entails. Did I misunderstand?
    I've started to search for a test occlusion type function so I can simply "if(!" for the rendering code in WM_TIMER or some such.

    I don't use RedrawWindow anywhere now, BTW, and foosion's tutorial is already set up to return 0 whenever a message matches a specified case, and return DefWindowProc otherwise.
    david_dl
    QUOTE(demalion @ Sep 22 2006, 18:17) *
    QUOTE(david_dl @ Sep 22 2006, 00:18) *

    ...
    BTW. RedrawWindow completely redraws the entire window, including erasing the background (depending on the flags you set). InvalidateRect may be better for what you want. In any case, use one of these or a similar function to trigger the WM_PAINT function from your WM_TIMER, manually sending WM_PAINT or calling your rendering code directly will cause unnecessary resource usage when the window is not visible.
    QUOTE


    In any case, what I have now is a WM_SIZE that updates my rendering size, a WM_PAINT that does the same within a BeginPaint/EndPaint pair, a WM_TIMER that executes diagnostic timing code and the rendering function with the retrieved playback_get_position , "beginrender/endrender" code that is always executed by the rendering function and now incorporates "KillTimer/SetTimer", and "init/cleanup" code for rendering that does "SetTimer/KillTimer". This all seems to hang together, so I guess I'll review at a later optimization stage. Thanks again for the help so far.




    So, basically, I need to call InvalidateRect from my WM_TIMER instead of the rendering function, and then have the rendering function followed by a ValidateRect under WM_PAINT. This way, when the window is completely occluded, WM_PAINT won't be called even though the clientrect is invalidated, since windows is smart enough to handle that, and so the render code won't be called, right? Thanks smile.gif
    Hmm, giving some thought, I don't like this solution, since it causes Windows to set a message (WM_PAINT in a roundabout way) in response to a message already given (WM_TIMER).
    There is nothing wrong with this. If look at the call stack somewhere within your message handler you will probably see that this has may have already happened tens of times before it even entered your code (more so with other messages)
    QUOTE
    I'm not sure this saves much in the way of resources since I think D3D would be holding onto its resources anyway?
    The main problem is CPU usage (which would probably be quite high considering you're using D3D) and calling InvalidateRect is many many times cheaper than just rendering blindly. Generally, if you do things the 'proper' way, ie. following everything in the MSDN, not making any assumptions about what functions do, then everything will work fine.

    As for memory resources, it's my understanding that windows is smart enough to swap most of an applications memory (that which is used for drawing the interface) to the pagefile when an application is minimised.
    QUOTE
    And it doubles message handling, however much code and parameter passing that entails. Did I misunderstand?
    I repeat again, do not worry about this, message handling is very efficient. Use Spy++ to view the messages for a window in any application and you will see hundreds of messages flooding through, especially when you move the mouse across the window or interact with it. Just think of sending a message like calling a native C/C++ function; when sent to a window in the same thread it's probably almost as fast.
    QUOTE

    I've started to search for a test occlusion type function so I can simply "if(!" for the rendering code in WM_TIMER or some such.

    I don't use RedrawWindow anywhere now, BTW, and foosion's tutorial is already set up to return 0 whenever a message matches a specified case, and return DefWindowProc otherwise.
    demalion
    Thanks, that information about messaging is an eye opener! smile.gif

    But I don't understand how the rendering would be cheaper on CPU usage...let me explain. Since I'm using Direct3D, I render to a cleared buffer and present, so any section of the window visible is the same for the render code. And Direct3D seems to be behaving intelligently...when I occlude my window completely without any changes to the code yet, CPU usage drops to where it is if my window is closed (System Idle Process jumps from ~8 to ~35).

    I do already have a member to deactivate rendering that is called in WM_SIZE for the MINIMIZED case you mentioned, and if DEVICE_LOST occurs when a Direct3D window is minimized, that turns off rendering too (as well as freeing resources from videocard memory) by my d3d rendering handling internal checking, since this is supposed to be handled anyways (though I'm not sure yet of all the cases that cause a DEVICE_LOST).

    I mention these not to dispute the important lesson about message handling you've provided, but to illustrate that I think the cases you mentioned are already covered so that if I'm mistaken about that you can tell me why. smile.gif I'm off to try a reimplement along the specified lines to compare behavior with partially occluded windows to see if Direct3D has some further hidden smarts that increase efficiency.

    BTW, with my VS help window crashing on searches now, I went to the website and searched in browser on MSDN, and found an extra Blogs tab that seems much more informative and discusses things in a broader sense when it comes to this type of topic. Perhaps that is where I was missing some of this info.

    EDIT: Ok, there doesn't seem to be any performance difference at all either way in any case with my current methods of testing. In fact, by fixing another problem (related to unecessarily calling some D3D handling), the CPU usage when running is typically much closer to CPU usage when not running (i.e., System Idle ~25 instead of ~8, peaking at ~30).
    Rasqual
    QUOTE(foosion @ Sep 21 2006, 10:30) *

    QUOTE(demalion @ Sep 21 2006, 00:24) *
    • Using ATL/WTL. I was planning to explore ATL/WTL for internet access functionality, as well as implementing the UI, but ran into an initial hurdle where it seems references to shared.lib functions weren't compatible. Is this expected behavior, or did I get something wrong in my attempt? How painful will it be to implement everything in, for example, foo_tutorial without shared.lib? Is it just u* functions used in your application, or are there many things like t_font_description in shared.h that will impact certain API function usage even without using any u* functions?
    Using ATL/WTL is entirely doable. foobar2000 internally uses UTF-8, so you need to take care to correctly convert strings. You can use pfc::stringcvt::string_os_from_utf8 to pass a UTF-8 string to ATL/WTL functions, and pfc::stringcvt::string_utf8_from_os for the other way.

    Note that if you are using conversion classes in ATL 7.1 to convert UTF-16 strings to UTF-8, please read this NG post regarding the CW2A bug assuming multibyte is at most 2 bytes per wide character. This was fixed in ATL 8.0 (VS2005).

    You might prefer working with the pfc::stringcvt::string_utf8_from_os helper class, though, as foosion pointed out.
    demalion
    QUOTE(Rasqual @ Sep 28 2006, 19:13) *

    ...
    Note that if you are using conversion classes in ATL 7.1 to convert UTF-16 strings to UTF-8, please read this NG post regarding the CW2A bug assuming multibyte is at most 2 bytes per wide character. This was fixed in ATL 8.0 (VS2005).

    You might prefer working with the pfc::stringcvt::string_utf8_from_os helper class, though, as foosion pointed out.

    Thanks for the advice. smile.gif

    I'm using the latest Platform SDK (Microsoft Platform SDK for Windows Server 2003 R2) over VS2005, and WTL 8.0 so I believe I should be all set as far as the bug goes.
    demalion
    Ok, something new I've found to ask about.
    • cfg_struct_t. I'm trying to build a foundation for backwards compatible configuration reading.
      I have a header file with "frozen" in the name where I'll be archiving configuration versions as I update in future, with each version of config storage structure having a UINT that stores the version number as the first storage member.
      I have a general usage structure that is used in the running code for the config that is intended to be able to accept any raw byte buffer and determine from its size and the integer value of the first UINT storage space whether it can try to import them as config data, and then does so for whatever archived versions exist.

      If I'm doing things correctly, I just need to know how I should be using the cfg_struct_t. If I declare it as a <CURRENT_CFG_STRUCTURE_VERSION>, and go to read from the cfg data I declared like this, can I access the raw buffer data it retrieves from the config storage mechanism even if it isn't of the type of CURRENT_CFG_STRUCTURE_VERSION? I'm not sure how this case is handled, and I'm not sure if the data stored remains safe, whole, and uncorrupted if it isn't actually data in the format of the specified structure (i.e., the CURRENT_CFG_STRUCTURE_VERSION has changed since the config was stored) if I try to access m_val and treat it as a raw buffer.
      From what I can gather so far, it seems this will throw an exception, and I need to use the pfc streamreader::read_object to get the raw data. If this is what is required, what is the best way to get the full stored data buffer and its stored size when the data doesn't match the current struct specify in the cfg_struct_t declaration? Safety tips and alternatives with the same flexibility appreciated as well. smile.gif
    Hmm, just realized that adding padding and limiting all versions to staying within the same size might allow this, but I'd prefer to avoid such a hack if the config mechanism will allow it. sad.gif
    This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
    Invision Power Board © 2001-2008 Invision Power Services, Inc.