OK, I have a basic blit demo working (thanks to Alex Fenton for his reply, which I finally saw). However, there''s a great deal of "tearing" on the screen - flickering grey lines in the black background. It looks like the blit isn''t always complete when the screen refreshes. Can anyone look at this and tell me what I might be doing wrong? Any help would be most appreciated! -Jay McGavren http://jay.mcgavren.com/zyps require ''rubygems'' require ''wx'' class MyApp < Wx::App def on_init #Containing frame. frame = Wx::Frame.new(nil, :size => [300, 300]) frame.show #Offscreen drawing buffer. buffer = Wx::Bitmap.new(300, 300) #Displays drawing. window = Wx::Window.new(frame, :size => [300, 300]) window.evt_paint do |event| window.paint do |dc| #Copy the buffer to the viewable window. buffer.draw do |buffer_dc| dc.blit(0, 0, 300, 300, buffer_dc, 0, 0) end end end #Animate. (1..40).each do |i| #Clear screen. buffer.draw do |surface| surface.pen = Wx::Pen.new(Wx::Colour.new(0, 0, 0), 0) surface.brush = Wx::BLACK_BRUSH surface.draw_rectangle(0, 0, 300, 300) end #Draw line. buffer.draw do |surface| surface.pen = Wx::Pen.new( Wx::Colour.new(128, 255, 128), 3 ) surface.pen.cap = Wx::CAP_ROUND surface.draw_line(i, 0, i+100, 100) end #Update screen. window.refresh window.update sleep 0.1 end end end app = MyApp.new app.main_loop
Mario Steele
2007-Dec-01 13:30 UTC
[wxruby-users] Tearing in my buffered animation test script...
On 11/30/07, Jay McGavren <jay at mcgavren.com> wrote:> > OK, I have a basic blit demo working (thanks to Alex Fenton for his > reply, which I finally saw). > > However, there''s a great deal of "tearing" on the screen - flickering > grey lines in the black background. It looks like the blit isn''t > always complete when the screen refreshes. > > Can anyone look at this and tell me what I might be doing wrong? Any > help would be most appreciated! > > -Jay McGavren > http://jay.mcgavren.com/zyps > <snip>Hey Jay, I''ve actually looked over the demo, and tested it out on my computer. According to what I see here, there should be no problems with it. And I''ve tested it on Linux, and I have no flickering, or tears in it. I would suggest, for the final "blit" operation, that instead of waiting for a Paint Event, you switch to using DC#draw_bitmap() instead of using DC#blit() This will take a lot of the computation off of wxRuby, which it must do to ensure that everything is within bounds, and there is not a programmer error (Which is often raised by a Message box error, or a segfault). Especially considering that your drawing the entire buffer that you have offscreen. Two other things. 1.) If your doing the actual painting when evt_paint() is called, then you do not need to create a ClientDC (Which is what window.paint does) 2.) You can skip evt_paint() and window.refresh/window.update all together, and just call window.paint, to paint to the window, when your finished with the painting on the Buffer. Just a couple of suggestions for ya, which should take care of the flicker and tearing. Mario Steele -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/wxruby-users/attachments/20071201/11f399a5/attachment.html
Mario Steele
2007-Dec-01 13:47 UTC
[wxruby-users] Tearing in my buffered animation test script...
On 12/1/07, Mario Steele <mario at ruby-im.net> wrote:> > Two other things. > 1.) If your doing the actual painting when evt_paint() is called, then you > do not need to create a ClientDC (Which is what window.paint does) > 2.) You can skip evt_paint() and window.refresh /window.update all > together, and just call window.paint, to paint to the window, when your > finished with the painting on the Buffer. > > Just a couple of suggestions for ya, which should take care of the flicker > and tearing. > > Mario Steele >Just a quick follow up. What I meant to say, was that you need to use one, or the other, as your basically creating two DC''s within a single event, which would be causing the flicker. So, you need to either create a Thread to draw it, or you need to take out the paint and draw within the evt_paint() proc. Sorry if that didn''t make sense earlier. ;-) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/wxruby-users/attachments/20071201/c139d9fe/attachment-0001.html
Jay McGavren
2007-Dec-01 20:55 UTC
[wxruby-users] Tearing in my buffered animation test script...
Excellent, excellent! All tearing is now gone on Windows. (I meant to mention my platform before, but forgot.) I kept evt_paint, which I need just in case the window needs redrawing (or at least, I will in my final application). But I created a separate routine that just calls Window.paint, and that''s what I use in my main animation loop (as well as evt_paint). And draw_bitmap is a lot cleaner, as well, so thanks for pointing that out. Revised code is below. You''ve saved me days of headaches, so many thanks! -Jay McGavren http://jay.mcgavren.com/zyps require ''rubygems'' require ''wx'' class MyApp < Wx::App def on_init #Containing frame. frame = Wx::Frame.new(nil, :size => [300, 300]) frame.show #Offscreen drawing buffer. buffer = Wx::Bitmap.new(300, 300) #Displays drawing. window = Wx::Window.new(frame, :size => [300, 300]) window.evt_paint do |event| update_window(window, buffer) end #Animate. (1..40).each do |i| #Clear screen. buffer.draw do |surface| surface.pen = Wx::Pen.new(Wx::Colour.new(0, 0, 0), 0) surface.brush = Wx::BLACK_BRUSH surface.draw_rectangle(0, 0, 300, 300) end #Draw line. buffer.draw do |surface| surface.pen = Wx::Pen.new( Wx::Colour.new(128, 255, 128), 3 ) surface.pen.cap = Wx::CAP_ROUND surface.draw_line(i, 0, i+100, 100) end #Update screen. update_window(window, buffer) sleep 0.1 end end def update_window(window, buffer) window.paint do |dc| #Copy the buffer to the viewable window. dc.draw_bitmap(buffer, 0, 0, false) end end end app = MyApp.new app.main_loop> On 12/1/07, Mario Steele <mario at ruby-im.net> wrote: > > Two other things. > > 1.) If your doing the actual painting when evt_paint() is called, then you > > do not need to create a ClientDC (Which is what window.paint does) > > 2.) You can skip evt_paint() and window.refresh /window.update all > > together, and just call window.paint, to paint to the window, when your > > finished with the painting on the Buffer. > > > > Just a couple of suggestions for ya, which should take care of the flicker > > and tearing. > > > > Mario Steele > > Just a quick follow up. What I meant to say, was that you need to use one, > or the other, as your basically creating two DC''s within a single event, > which would be causing the flicker. So, you need to either create a Thread > to draw it, or you need to take out the paint and draw within the > evt_paint() proc. Sorry if that didn''t make sense earlier. ;-)
Paul w Florczykowski
2008-Mar-19 19:59 UTC
[wxruby-users] Tearing in my buffered animation test script...
Hi Jay! I have tested your application, and indeed there is great deal of flicker as expected. You are not making any particular errors in your code; the problem occurs because the drawing, or more precisely, the copying of graphics (blit) is not synchronized with the vertical sync signal your screen receives from your graphics card. (I''m speaking in terms of analog signal CRT, but actually this applies to any kind of digital screen as well, as far the application is concerned) The usual way to deal with this is: 1. Draw all the graphics onto an backbuffer (any surface that does not appear on the screen yet) 2. Await the V-blank (the vertical sync signal) 3. Copy the contents of this backbuffer onto the screen (the frontbuffer), or simply swap the buffers if your API supports it 4. repeat from 1 What you are currently doing is similar but lacks the point (2). wxRuby aims to support this on a lower level (i think). There is a method called "paint_buffered" (in stead of "paint") that provides a BufferedDC-object instead of ClientDC or DC. Drawing to the BufferedDC is then not supposed to be visible first after: 1. the actual drawing you are making on it is finally completed ie. the block provided to "buffered_paint" finishes, and 2. the V-blank occurs. Sadly enough, this feature does not seem to be working properly with wxruby 1.9.5. I have currently similar problem - have not yet decided whether to devise another method to signal V-blank to Ruby, or to accept the moderate flicker in my application. Best regards, Paul W Florczykowski -- Posted via http://www.ruby-forum.com/.
Alex Fenton
2008-Mar-28 00:17 UTC
[wxruby-users] Tearing in my buffered animation test script...
Hi Paul Paul w Florczykowski wrote:> I have tested your application, and indeed there is great deal of > flicker as expected. You are not making any particular errors in your > code; the problem occurs because the drawing, or more precisely, the > copying of graphics (blit) is not synchronized with the vertical sync > signal your screen receives from your graphics card. (I''m speaking in > terms of analog signal CRT, but actually this applies to any kind of > digital screen as well, as far the application is concerned) > > The usual way to deal with this is: > > 1. Draw all the graphics onto an backbuffer (any surface that does not > appear on the screen yet) > > 2. Await the V-blank (the vertical sync signal) > > 3. Copy the contents of this backbuffer onto the screen (the > frontbuffer), or simply swap the buffers if your API supports it > > 4. repeat from 1 >I didn''t know about (2), thanks for this info on buffering.> What you are currently doing is similar but lacks the point (2). wxRuby > aims to support this on a lower level (i think). There is a method > called "paint_buffered" (in stead of "paint") that provides a > BufferedDC-object instead of ClientDC or DC. Drawing to the BufferedDC > is then not supposed to be visible first after: 1. the actual drawing > you are making on it is finally completed ie. the block provided to > "buffered_paint" finishes, and 2. the V-blank occurs. > > Sadly enough, this feature does not seem to be working properly with > wxruby 1.9.5. I have currently similar problem - have not yet decided > whether to devise another method to signal V-blank to Ruby, or to accept > the moderate flicker in my application. >wxRuby 1.9.5 ''paint_buffered'' method does what you describe, lacking point (2). It doesn''t do anything more low-level. It''s implemented in pure Ruby, http://wxruby.rubyforge.org/svn/trunk/wxruby2/lib/wx/classes/window.rb but it''s a straight conversion of the C++ code that wxWidgets uses to provide BufferedDC: http://svn.wxwidgets.org/viewvc/wx/wxWidgets/tags/WX_2_8_7/include/wx/dcbuffer.h?revision=52270&view=markup If you find any advice on how we can improve this by synchronising with the V-blank please post this, as this is beyond my expertise. thanks alex