RenderSurface

The first example provides the means for creating a surface for 3D rendering.  In this example, a small C++ class called MyGraphics will provide a simple mechanism for initializing some OpenGL state and using OpenGL to render the famous OpenGL teapot.


//C++ source file - Open Producer - Copyright (C) 2002 Don Burns
//Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL)
//as published by the Free Software Foundation.

// Simple example of use of Producer::RenderSurface
// The MyGraphics class is a simple sample of how one would implement
// graphics drawing with Producer::RenderSurface

#include <Producer/RenderSurface>
#include "MyGraphics"

int main(int argc, char **argv )
{
    // Declare a RenderSurface
    Producer::RenderSurface rs;

    // Optional.  Set the window size.
    // Arguments are x, y, width, height
    // If this call is not made, the RenderSurface
    // will occupy the entire screen with no border
    rs.setWindowRect( 100, 100, 640, 480 );
    // Give the window a name in the border
    rs.setWindowName( "Producer Example using Render Surface" );

    // required.  This creates the window and
    // sets up the graphics context.

    rs.realize();

    // Add your own rendering code.
    MyGraphics gfx(rs);
    gfx.init();

    while( true )
    {
        // If possible, RenderSurface will synchronize
        // the application run-time to the vertical
        // retrace signal
        rs.sync();

        // Call your own draw routine
        gfx.draw();

        // Swap Buffers
        rs.swapBuffers();
    }
    return 0;
}

Code example 1 - Simple Render Surface

Explanation of the code



#include <Producer/RenderSurface>

#include "MyGraphics"


Note that Producer uses the convention of standard C++ by omitting the suffix of the header files.  Producer/RenderSurface is the include file for the RenderSurface class.  MyGraphics is a local class that is simply used for example.  It has little bearing on the functionality of RenderSurface although it does access the width() and height() methods of RenderSurface for determining the width and height of the window.   Two methods in MyGraphics are called in the example, init() which initializes graphics state and draw() which draws the famous OpenGL teapot.

int main(int argc, char **argv )
{
    // Declare a RenderSurface
    Producer::RenderSurface rs;

RendersSurface, like all Open Producer classes is namespace protected by the Producer namespace.  Classess are allowed to be declared on the stack as demonstrated in this example, but the usual care should be taken when doing this.

// Optional.  Set the window size
// Arguments are x, y, width, height
// If this call is not made, the RenderSurface
// will occupy the entire screen with no border
rs.setWindowRect( 100, 100, 640, 480 );

// Give the window a name in the border
rs.setWindowName( "Producer Example using Render Surface" );



Two optional methods of RenderSurface are invoked here.  setWindowRect() provides the screen x, y coordinates of the lower left corner of the window and its width and height respectively.  setWindowName() provides the window with a name which will be displayed in the border.  As the comments indicate, if setWindowRect() is not called, the window will occupy the entire screen, as as a borderless window.  
// required.  This creates the window and
// sets up the graphics context.
rs.realize();


The realize() method creates the window and sets up the OpenGL graphics rendering context.  It is important to make this call before any calls are made to OpenGL as there will be no valid context before this.  However, much of the configuration of the RenderSurface is only available before it is realized.  Once realized certain configuration parameters (such as buffer quality attributes) are not configurable.  A complete list of which methods are meaningful before realization and are ignored after realization is given in the reference page.
// Add your own rendering code.
MyGraphics gfx(rs);
gfx.init();

This is code that is added by the user for graphics rendering and is here for example.

while( true )
{
// If possible, RenderSurface will synchronize
// the application run-time to the vertical
// retrace signal
rs.sync();

// Call your own draw routine
gfx.draw();

// Swap Buffers
rs.swapBuffers();
}

Note the very important point that the control of the main loop is given to the programmer.  There is no "mainLoop()" method in Producer, where the programmer must relinquish control over the run time and wait for the system to call his callbacks.  It is therefore up to the programmer to provide the main loop.

The loop begins with a synchronization (rs.sync()).  Some implementations will provide a method of synchronizing the application with the vertical retrace signal of the graphics subsystem.  The advantages of doing this in a real-time application are discussed in a separate section.  This is, however, optional and may be left out.  Without it, the application will race ahead of the graphics and will be throttled only by a very low level FIFO.  See "Synchronizing your Application to the Graphics Subsystem".

The user's implementation of graphics rendering occurs in gfx.draw().  

All rendering in Producer will assume double frame buffers.  The call to swapBuffers will delimit the end of the graphics frame as far as the application is concerned.