Can't get onPaint from example to work

69 views
Skip to first unread message

Jarrett Chisholm

unread,
Nov 19, 2012, 7:08:45 PM11/19/12
to berk...@googlegroups.com
Hi all,

Ok - I have an opengl application using berkelium.  It compiles fine.  I've gotten image loading/textures into the application, and I can get textures to draw onto 3d objects in opengl.

However, when I imported the berkelium code from the glut_input example, the code from mapOnPaintToTexture(..) does not seem to get an image and load it into an opengl texture properly...at least, I can't get it to work.  It DOES work in the example provided with berkelium, so I'm sure it's something i'm doing.

If I copy the code from ppmrender example, I can get it to save the .ppm files into /tmp without issue (I can also load those images and render them to a 3d object).

My onPaint(..) method in my delegate is being called, as is the mapOnPaintToTexture(..) method.

here's my onPaint:
onPaint(Berkelium::Window* wini,
    const unsigned char *bitmap_in, const Berkelium::Rect &bitmap_rect,
    size_t num_copy_rects, const Berkelium::Rect* copy_rects,
    int dx, int dy, const Berkelium::Rect& scroll_rect) {
bool updated = mapOnPaintToTexture(
            wini, bitmap_in, bitmap_rect, num_copy_rects, copy_rects,
            dx, dy, scroll_rect,
            web_texture, width, height, false, scroll_buffer
        );
}

and my mapOnPaintToTexture:
mapOnPaintToTexture(
    Berkelium::Window *wini,
    const unsigned char* bitmap_in, const Berkelium::Rect& bitmap_rect,
    size_t num_copy_rects, const Berkelium::Rect *copy_rects,
    int dx, int dy,
    const Berkelium::Rect& scroll_rect,
    unsigned int dest_texture,
    unsigned int dest_texture_width,
    unsigned int dest_texture_height,
    bool ignore_partial,
    char* scroll_buffer) {
   
    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: " << dest_texture_width << "x" << dest_texture_width << " dest_texture: " << dest_texture;

    glBindTexture(GL_TEXTURE_2D, dest_texture);

    const int kBytesPerPixel = 4;

    // If we've reloaded the page and need a full update, ignore updates
    // until a full one comes in.  This handles out of date updates due to
    // delays in event processing.
    if (ignore_partial) {
        if (bitmap_rect.left() != 0 ||
            bitmap_rect.top() != 0 ||
            bitmap_rect.right() != dest_texture_width ||
            bitmap_rect.bottom() != dest_texture_height) {
            return false;
        }

        glTexImage2D(GL_TEXTURE_2D, 0, kBytesPerPixel, dest_texture_width, dest_texture_height, 0,
            GL_BGRA, GL_UNSIGNED_BYTE, bitmap_in);
        ignore_partial = false;
        return true;
    }
   
    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: here 1";


    // Now, we first handle scrolling. We need to do this first since it
    // requires shifting existing data, some of which will be overwritten by
    // the regular dirty rect update.
    if (dx != 0 || dy != 0) {
        // scroll_rect contains the Rect we need to move
        // First we figure out where the the data is moved to by translating it
        Berkelium::Rect scrolled_rect = scroll_rect.translate(-dx, -dy);
        // Next we figure out where they intersect, giving the scrolled
        // region
        Berkelium::Rect scrolled_shared_rect = scroll_rect.intersect(scrolled_rect);
        // Only do scrolling if they have non-zero intersection
        if (scrolled_shared_rect.width() > 0 && scrolled_shared_rect.height() > 0) {
            // And the scroll is performed by moving shared_rect by (dx,dy)
            Berkelium::Rect shared_rect = scrolled_shared_rect.translate(dx, dy);

            int wid = scrolled_shared_rect.width();
            int hig = scrolled_shared_rect.height();
           
            if (DEBUG_PAINT) {
              std::cout << "Scroll rect: w=" << wid << ", h=" << hig << ", ("
                        << scrolled_shared_rect.left() << "," << scrolled_shared_rect.top()
                        << ") by (" << dx << "," << dy << ")" << std::endl;
            }
           
            int inc = 1;
            char *outputBuffer = scroll_buffer;
            // source data is offset by 1 line to prevent memcpy aliasing
            // In this case, it can happen if dy==0 and dx!=0.
            char *inputBuffer = scroll_buffer+(dest_texture_width*1*kBytesPerPixel);
            int jj = 0;
            if (dy > 0) {
                // Here, we need to shift the buffer around so that we start in the
                // extra row at the end, and then copy in reverse so that we
                // don't clobber source data before copying it.
                outputBuffer = scroll_buffer+(
                    (scrolled_shared_rect.top()+hig+1)*dest_texture_width
                    - hig*wid)*kBytesPerPixel;
                inputBuffer = scroll_buffer;
                inc = -1;
                jj = hig-1;
            }

            // Copy the data out of the texture
            glGetTexImage(
                GL_TEXTURE_2D, 0,
                GL_BGRA, GL_UNSIGNED_BYTE,
                inputBuffer
            );

            // Annoyingly, OpenGL doesn't provide convenient primitives, so
            // we manually copy out the region to the beginning of the
            // buffer
            for(; jj < hig && jj >= 0; jj+=inc) {
                memcpy(
                    outputBuffer + (jj*wid) * kBytesPerPixel,
//scroll_buffer + (jj*wid * kBytesPerPixel),
                    inputBuffer + (
                        (scrolled_shared_rect.top()+jj)*dest_texture_width
                        + scrolled_shared_rect.left()) * kBytesPerPixel,
                    wid*kBytesPerPixel
                );
            }

            // And finally, we push it back into the texture in the right
            // location
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                shared_rect.left(), shared_rect.top(),
                shared_rect.width(), shared_rect.height(),
                GL_BGRA, GL_UNSIGNED_BYTE, outputBuffer
            );
        }
    }

    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: here 2";
    if (DEBUG_PAINT) {
      std::cout << (void*)wini << " Bitmap rect: w="
                << bitmap_rect.width()<<", h="<<bitmap_rect.height()
                <<", ("<<bitmap_rect.top()<<","<<bitmap_rect.left()
                <<") tex size "<<dest_texture_width<<"x"<<dest_texture_height
                <<std::endl;
    }
   
   
    for (size_t i = 0; i < num_copy_rects; i++) {
        int wid = copy_rects[i].width();
        int hig = copy_rects[i].height();
        int top = copy_rects[i].top() - bitmap_rect.top();
        int left = copy_rects[i].left() - bitmap_rect.left();
       
        if (DEBUG_PAINT) {
            std::cout << (void*)wini << " Copy rect: w=" << wid << ", h=" << hig << ", ("
                      << top << "," << left << ")" << std::endl;
        }
       
        for(int jj = 0; jj < hig; jj++) {
            memcpy(
                scroll_buffer + jj*wid*kBytesPerPixel,
                bitmap_in + (left + (jj+top)*bitmap_rect.width())*kBytesPerPixel,
                wid*kBytesPerPixel
                );
        }

        // Finally, we perform the main update, just copying the rect that is
        // marked as dirty but not from scrolled data.
        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        copy_rects[i].left(), copy_rects[i].top(),
                        wid, hig,
                        GL_BGRA, GL_UNSIGNED_BYTE, scroll_buffer
            );
    }
    BOOST_LOG_TRIVIAL(debug) << "mapOnPaintToTexture: here 3";

    glBindTexture(GL_TEXTURE_2D, 0);

    return true;
}


My render code looks like this:
testDrawTestBerkelium() {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable( GL_TEXTURE_2D );
    glBindTexture(GL_TEXTURE_2D, web_texture);
   
    // display   
    glBegin(GL_QUADS);
        glTexCoord2f(0.f, 0.f); glVertex3f(-10.f, -10.f, 0.f);
        glTexCoord2f(0.f, 1.f); glVertex3f(-10.f,  10.f, 0.f);
        glTexCoord2f(1.f, 1.f); glVertex3f( 10.f,  10.f, 0.f);
        glTexCoord2f(1.f, 0.f); glVertex3f( 10.f, -10.f, 0.f);
    glEnd();
   
    Berkelium::update();
}


and my initialize function looks like this:
initialize() {
    if (!Berkelium::init(Berkelium::FileString::empty())) {
        BOOST_LOG_TRIVIAL(debug) << "Failed to initialize berkelium!";
        return -1;
    }
   
    scroll_buffer = new char[width*(height+1)*4];
   
    // Create texture to hold rendered view
    glGenTextures(1, &web_texture);
    glBindTexture(GL_TEXTURE_2D, web_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   
    Berkelium::Context* context = Berkelium::Context::create();
    Berkelium::Window* window = Berkelium::Window::create(context);
    delete context;
   
    width = 600;
    height = 600;
   
    //MyDelegate* delegate = new MyDelegate();
    window->setDelegate(this);
    window->resize(width, height);
    std::string url = "http://yahoo.ca";
    window->navigateTo(Berkelium::URLString::point_to(url.data(), url.length()));
}

I think that's all the relevant bits.  When I load the program, I just see a grey square on the screen.

Does anyone see anything obvious I'm doing wrong?

Cheers

Ewen Cheslack-Postava

unread,
Nov 19, 2012, 7:23:45 PM11/19/12
to berk...@googlegroups.com
Nothing obvious pops out at me, but that's a bunch of code that, at the same time, is missing the infrastructure code which is most likely to differ from the glut demos. Some simple things to check:

1. Are you ever even getting into onPaint/mapOnPaintToTexture? If not triple check the signature of the onPaint override.
2. Put garbage into your texture and make sure it's rendering as garbage. That just checks you're setting up and rendering with the texture properly.
3. Could be a problem with the texture, or a problem with the basic quad rendering code. Does rendering with no texture + another color work? I don't see a glClear/glClearColor in there so I can't tell if gray means "background" or "texture that's been cleared to gray".
4. I assume you're tying the render call to a timer or something? If it's at all event driven like it can be in GLUT then you may not ever get data out of Berkelium since your call to Berkelium::update() is in the render call.

-Ewen

Jarrett Chisholm

unread,
Nov 19, 2012, 8:15:52 PM11/19/12
to berk...@googlegroups.com
Hey Ewen, thanks for the reply.  I appreciate it.

hmm...very peculiar.

I got it to work, after changing my call to mapOnPaintToTexture:
bool updated = mapOnPaintToTexture(
            wini, bitmap_in, bitmap_rect, num_copy_rects, copy_rects,
            dx, dy, scroll_rect,
            web_texture, width, height, true, scroll_buffer
        );

The true flag gets it to render - I guess that makes sense. That flag is whether to render everything or just do a 'partial' update....can't say that I quite understand this.  If I actually take some more code from glut_input demo, and have this basically do a full render on the first call and partial updates after that, my program seg faults (although the onPaint(..) method finishes before doing so) :S  But if I just send in true and do a full refresh every time it works - yay!

Thanks again Ewen :)


ps: Anyone know if there is a berkelium log or something that is dumps debug info to?

cheers

jarrett

Jarrett Chisholm

unread,
Nov 19, 2012, 8:20:04 PM11/19/12
to berk...@googlegroups.com
actually, as it turns out, the onPaint(..) method is NOT returning...the crash is in the mapOnPaintToTexture(..) method at this point:


for(int jj = 0; jj < hig; jj++) {
            memcpy(
                scroll_buffer + jj*wid*kBytesPerPixel,
                bitmap_in + (left + (jj+top)*bitmap_rect.width())*kBytesPerPixel,
                wid*kBytesPerPixel
                );
        }
I get a seg fault when doing a 'partial' update...no idea why :\  Anyone experience anything like this before?

cheers

Jarrett Chisholm

unread,
Nov 19, 2012, 8:45:38 PM11/19/12
to berk...@googlegroups.com
My fault, the variable scroll_buffer was not properly initialized.

Thanks everyone for looking through my hasty posting.

cheers
Reply all
Reply to author
Forward
0 new messages