OpenGL and BBB - simple HelloTriangle example

259 views
Skip to first unread message

John London

unread,
Aug 6, 2015, 8:18:57 AM8/6/15
to BeagleBoard

I'm trying to get a simple example (Hello Triangle) working with BBB running Debian.  I do NOT want to run the example under X11 - I want to run it from the command line.  I do not want to use GLUT; I think this means it uses the framebuffer.  Is this possible and does anyone have an example of how to do this please?


I have been trying to use the example below, taken directly from the Examples directory of the PowerVR SDK.  When I run the compiled program, I get an error:

libEGL warning: DRI2: xcb_connect failed
libEGL warning: DRI2: xcb_connect failed
Failed to initialise the EGLDisplay

Is the code trying to make a connection to X11 perhaps?

I am using the Makefile and code below.


#
# File Makefile
# Title Makes the demo
# Author PowerVR
#
# Copyright Copyright (C) by Imagination Technologies Limited.
#


.PHONY: clean


SDKDIR  
= $(shell cd ../../../../../.. && pwd)
VPATH
= ../..


CROSS_COMPILE
?= arm-linux-gnueabihf-


ifdef TOOLCHAIN
PLAT_CC  
= $(TOOLCHAIN)/bin/$(CROSS_COMPILE)gcc
PLAT_CPP
= $(TOOLCHAIN)/bin/$(CROSS_COMPILE)g++
PLAT_AR  
= $(TOOLCHAIN)/bin/$(CROSS_COMPILE)ar
else
PLAT_CC  
= $(CROSS_COMPILE)gcc
PLAT_CPP
= $(CROSS_COMPILE)g++
PLAT_AR  
= $(CROSS_COMPILE)ar
endif


ifeq
"$(X11BUILD)" "1"
ifndef X11ROOT
$
(error When building an X11 BUILD you must set X11ROOT to point at the location where your X11 headers and libs can be found.)
endif
ifeq
"$(EWSBUILD)" "1"
$
(error Cannot have both X11BUILD and EWSBUILD enabled at the same time)
endif
WS_LIBS
= -L$(X11ROOT)/lib -lX11 -lXau -ldl
WS_RPATH
= $(X11ROOT)/lib
WS_INC  
= $(X11ROOT)/include
WS
= X11
else
ifeq
"$(EWSBUILD)" "1"
PLAT_CFLAGS
+= -DEWS
WS_LIBS
= -lews
WS_INC
=
WS
=EWS
else
ifeq
"$(DRMBUILD)" "1"
ifndef DRMROOT
$
(error When building a DRM BUILD you must set DRMROOT to point at the location where your DRM headers and libs can be found.)
endif
WS_LIBS
= -L$(DRMROOT)/lib -ldrm -lgbm -ludev -ldl -Wl,--rpath-link,$(DRMROOT)/lib
WS_INC
= $(DRMROOT)/include $(DRMROOT)/include/libdrm $(DRMROOT)/include/gbm
WS
=DRM
else
WS_LIBS
=
WS_INC  
=
WS
= NullWS
endif
endif
endif


LIBDIR
?= $(SDKDIR)/Builds/Linux/armv7hf/Lib
LIBDIR_FLAGS
= -L$(LIBDIR) -Wl,--rpath-link,$(LIBDIR):$(WS_RPATH)


ifdef
Debug
DEBUG_RELEASE
= Debug
PLAT_CFLAGS  
+= -g
else
DEBUG_RELEASE
= Release
PLAT_CFLAGS  
+= -O2
endif


PLAT_CFLAGS
+= -Wall -march=armv7 -mfloat-abi=hard
PLAT_INC  
= $(SDKDIR)/Builds/Include $(WS_INC)


PLAT_OBJPATH
= $(DEBUG_RELEASE)$(WS)
PLAT_LINK
= $(LIBDIR_FLAGS) -lEGL -lGLESv2 $(WS_LIBS) -L$(TOOLCHAIN)/lib -march=armv7 -mfloat-abi=hard


ifeq
"$(WS)" "X11"
SRCNAME
= OGLES2HelloAPI_LinuxX11
else
ifeq
"$(WS)" "EWS"
SRCNAME
= OGLES2HelloAPI_EWS
else
ifeq
"$(WS)" "DRM"
SRCNAME
= OGLES2HelloAPI_LinuxDRM
else
SRCNAME
= OGLES2HelloAPI_NullWS
endif
endif
endif


OUTNAME
= OGLES2HelloAPI


OBJECTS
= $(PLAT_OBJPATH)/$(SRCNAME).o


COMMON_INCLUDES
= $(addprefix -I, $(PLAT_INC))


$
(PLAT_OBJPATH)/$(OUTNAME) : $(OBJECTS)
 mkdir
-p $(PLAT_OBJPATH)
 $
(PLAT_CPP) -o $(PLAT_OBJPATH)/$(OUTNAME) $(OBJECTS) $(LINK) $(PLAT_LINK)


$
(PLAT_OBJPATH)/%.o: %.cpp
 mkdir
-p $(PLAT_OBJPATH)
 $
(PLAT_CC) $(PLAT_CFLAGS) -c $(COMMON_INCLUDES) $(INCLUDES) $^ -o $@


clean
:
 
-rm -rf $(PLAT_OBJPATH) *.o






/*******************************************************************************************************************************************

 


 

 @File         OGLES2HelloAPI_NullWS.cpp


 

 @Title        OpenGL ES 2.0 HelloAPI Tutorial


 

 @Version      


 

 @Copyright    Copyright (c) Imagination Technologies Limited.


 

 @Platform      


 

 @Description  Basic Tutorial that shows step-by-step how to initialize OpenGL ES 2.0, use it for drawing a triangle and terminate it.

               Entry Point: main


 

*******************************************************************************************************************************************/


/*******************************************************************************************************************************************

 Include Files

*******************************************************************************************************************************************/


#include <stdio.h>


 

#include <EGL/egl.h>

#include <GLES2/gl2.h>


 

/*******************************************************************************************************************************************

 Defines

*******************************************************************************************************************************************/


// Index to bind the attributes to vertex shaders

#define VERTEX_ARRAY 0


 

/*******************************************************************************************************************************************

 Helper Functions

*******************************************************************************************************************************************/



 

/*!*****************************************************************************************************************************************

 @Function TestEGLError

 @Input functionLastCalled          Function which triggered the error

 @Return True if no EGL error was detected

 @Description Tests for an EGL error and prints it.

*******************************************************************************************************************************************/


bool TestEGLError(const char* functionLastCalled)

{

 
/* eglGetError returns the last error that occurred using EGL, not necessarily the status of the last called function. The user has to

 check after every single EGL call or at least once every frame. Usually this would be for debugging only, but for this example

 it is enabled always.

 */


 
EGLint lastError = eglGetError();

 
if (lastError != EGL_SUCCESS)

 
{

 printf
("%s failed (%x).\n", functionLastCalled, lastError);

 
return false;

 
}


 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function TestGLError

 @Input functionLastCalled          Function which triggered the error

 @Return True if no GL error was detected

 @Description Tests for an GL error and prints it in a message box.

*******************************************************************************************************************************************/


bool TestGLError(const char* functionLastCalled)

{

 
/* glGetError returns the last error that occurred using OpenGL ES, not necessarily the status of the last called function. The user  

 has to check after every single OpenGL ES call or at least once every frame. Usually this would be for debugging only, but for this

 example it is enabled always

 */


 
GLenum lastError = glGetError();

 
if (lastError != GL_NO_ERROR)

 
{

 printf
("%s failed (%x).\n", functionLastCalled, lastError);

 
return false;

 
}


 

 
return true;

}


 

/*******************************************************************************************************************************************

 Application Functions

*******************************************************************************************************************************************/



 

/*!*****************************************************************************************************************************************

 @Function CreateEGLDisplay

 @Output eglDisplay     EGLDisplay created

 @Return Whether the function succeeded or not.

 @Description Creates an EGLDisplay and initialises it.

*******************************************************************************************************************************************/


bool CreateEGLDisplay( EGLDisplay &eglDisplay )  

{

 
/* Get an EGL display.

 EGL uses the concept of a "display" which in most environments corresponds to a single physical screen. After creating a native

 display for a given windowing system, EGL can use this handle to get a corresponding EGLDisplay handle to it for use in rendering.

 Should this fail, EGL is usually able to provide access to a default display. For Null window systems, there is no display so NULL

 is passed the this function.

 */


 eglDisplay
= eglGetDisplay((EGLNativeDisplayType)0);

 
if (eglDisplay == EGL_NO_DISPLAY)

 
{

 printf
("Failed to get an EGLDisplay");

 
return false;

 
}


 

 
/* Initialize EGL.

 EGL has to be initialized with the display obtained in the previous step. All EGL functions other than eglGetDisplay  

 and eglGetError need an initialised EGLDisplay.  

 If an application is not interested in the EGL version number it can just pass NULL for the second and third parameters, but they  

 are queried here for illustration purposes.

 */


 
EGLint eglMajorVersion, eglMinorVersion;

 
if (!eglInitialize(eglDisplay, &eglMajorVersion, &eglMinorVersion))

 
{

 printf
("Failed to initialise the EGLDisplay");

 
return false;

 
}


 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function ChooseEGLConfig

 @Input eglDisplay                  The EGLDisplay used by the application

 @Output eglConfig                   The EGLConfig chosen by the function

 @Return Whether the function succeeded or not.

 @Description Chooses an appropriate EGLConfig and return it.

*******************************************************************************************************************************************/


bool ChooseEGLConfig( EGLDisplay eglDisplay, EGLConfig& eglConfig )  

{

 
/* Specify the required configuration attributes.

 An EGL "configuration" describes the capabilities an application requires and the type of surfaces that can be used for drawing.

 Each implementation exposes a number of different configurations, and an application needs to describe to EGL what capabilities it

 requires so that an appropriate one can be chosen. The first step in doing this is to create an attribute list, which is an array

 of key/value pairs which describe particular capabilities requested. In this application nothing special is required so we can query

 the minimum of needing it to render to a window, and being OpenGL ES 2.0 capable.

 */


 
const EGLint configurationAttributes[] =

 
{

 EGL_SURFACE_TYPE
, EGL_WINDOW_BIT,

 EGL_RENDERABLE_TYPE
, EGL_OPENGL_ES2_BIT,

 EGL_NONE

 
};


 

 
/* Find a suitable EGLConfig

 eglChooseConfig is provided by EGL to provide an easy way to select an appropriate configuration. It takes in the capabilities

 specified in the attribute list, and returns a list of available configurations that match or exceed the capabilities requested.

 Details of all the possible attributes and how they are selected for by this function are available in the EGL reference pages here:

 
http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/eglChooseConfig.html

 It is also possible to simply get the entire list of configurations and use a custom algorithm to choose a suitable one, as many

 advanced applications choose to do. For this application however, taking the first EGLConfig that the function returns suits

 its needs perfectly, so we limit it to returning a single EGLConfig.

 */


 
EGLint configsReturned;

 
if (!eglChooseConfig(eglDisplay, configurationAttributes, &eglConfig, 1, &configsReturned) || (configsReturned != 1))

 
{

 printf
("Failed to choose a suitable config.");

 
return false;

 
}


 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function CreateEGLSurface

 @Input eglDisplay                  The EGLDisplay used by the application

 @Input eglConfig                   An EGLConfig chosen by the application

 @Output eglSurface The EGLSurface created

 @Return Whether the function succeeds or not.

 @Description Creates an EGLSurface for the screen

*******************************************************************************************************************************************/


bool CreateEGLSurface( EGLDisplay eglDisplay, EGLConfig eglConfig, EGLSurface& eglSurface)  

{

 
/* Create an EGLSurface for rendering.

 Using a native window created earlier and a suitable eglConfig, a surface is created that can be used to render OpenGL ES calls to.

 There are three main surface types in EGL, which can all be used in the same way once created but work slightly differently:

 - Window Surfaces  - These are created from a native window and are drawn to the screen.

 - Pixmap Surfaces  - These are created from a native windowing system as well, but are offscreen and are not displayed to the user.

 - PBuffer Surfaces - These are created directly within EGL, and like Pixmap Surfaces are offscreen and thus not displayed.

 The offscreen surfaces are useful for non-rendering contexts and in certain other scenarios, but for most applications the main

 surface used will be a window surface as performed below. For NULL window systems, there are no actual windows, so NULL is passed

 to this function.

 */


 eglSurface
= eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)0, NULL);

 
if (!TestEGLError("eglCreateWindowSurface"))

 
{

 
return false;

 
}


 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function SetupEGLContext

 @Input eglDisplay                  The EGLDisplay used by the application

 @Input eglConfig                   An EGLConfig chosen by the application

 @Input eglSurface The EGLSurface created by the application

 @Output eglContext                  The EGLContext created by this function

 @Return Whether the function succeeds or not.

 @Description Sets up the EGLContext, creating it and then installing it to the current thread.

*******************************************************************************************************************************************/


bool SetupEGLContext( EGLDisplay eglDisplay, EGLConfig eglConfig, EGLSurface eglSurface, EGLContext& eglContext )  

{

 
/* Make OpenGL ES the current API.

 EGL needs a way to know that any subsequent EGL calls are going to be affecting OpenGL ES,

 rather than any other API (such as OpenVG).

 */


 eglBindAPI
(EGL_OPENGL_ES_API);

 
if (!TestEGLError("eglBindAPI"))

 
{

 
return false;

 
}


 

 
/* Create a context.

 EGL has to create what is known as a context for OpenGL ES. The concept of a context is OpenGL ES's way of encapsulating any

 resources and state. What appear to be "global" functions in OpenGL actually only operate on the current context. A context

 is required for any operations in OpenGL ES.

 Similar to an EGLConfig, a context takes in a list of attributes specifying some of its capabilities. However in most cases this

 is limited to just requiring the version of the OpenGL ES context required - In this case, OpenGL ES 2.0.

 */


 
EGLint contextAttributes[] =  

 
{

 EGL_CONTEXT_CLIENT_VERSION
, 2,  

 EGL_NONE

 
};


 

 
// Create the context with the context attributes supplied

 eglContext
= eglCreateContext(eglDisplay, eglConfig, NULL, contextAttributes);

 
if (!TestEGLError("eglCreateContext"))

 
{

 
return false;

 
}


 

 
/* Bind the context to the current thread.

 Due to the way OpenGL uses global functions, contexts need to be made current so that any function call can operate on the correct

 context. Specifically, make current will bind the context to the thread it's called from, and unbind it from any others. To use

 multiple contexts at the same time, users should use multiple threads and synchronise between them.

 */


 eglMakeCurrent
(eglDisplay, eglSurface, eglSurface, eglContext);

 
if (!TestEGLError("eglMakeCurrent"))

 
{

 
return false;

 
}


 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function InitialiseBuffer

 @Output vertexBuffer                Handle to a vertex buffer object

 @Return Whether the function succeeds or not.

 @Description Initialises shaders, buffers and other state required to begin rendering with OpenGL ES

*******************************************************************************************************************************************/


bool InitialiseBuffer(GLuint &vertexBuffer)  

{

 
/* Concept: Vertices

 When rendering a polygon or model to screen, OpenGL ES has to be told where to draw the object, and more fundamentally what shape  

 it is. The data used to do this is referred to as vertices, points in 3D space which are usually collected into groups of three  

 to render as triangles. Fundamentally, any advanced 3D shape in OpenGL ES is constructed from a series of these vertices - each  

 vertex representing one corner of a polygon.

 */



 

 
/* Concept: Buffer Objects

 To operate on any data, OpenGL first needs to be able to access it. The GPU maintains a separate pool of memory it uses independent

 of the CPU. Whilst on many embedded systems these are in the same physical memory, the distinction exists so that they can use and

 allocate memory without having to worry about synchronising with any other processors in the device.

 To this end, data needs to be uploaded into buffers, which are essentially a reserved bit of memory for the GPU to use. By creating

 a buffer and giving it some data we can tell the GPU how to render a triangle.

 */



 

 
// Vertex data containing the positions of each point of the triangle

 
GLfloat vertexData[] = {-0.4f,-0.4f, 0.0f,  // Bottom Left

                         
0.4f,-0.4f, 0.0f,  // Bottom Right

                         
0.0f, 0.4f, 0.0f}; // Top Middle


 

 
// Generate a buffer object

 glGenBuffers
(1, &vertexBuffer);


 

 
// Bind buffer as an vertex buffer so we can fill it with data

 glBindBuffer
(GL_ARRAY_BUFFER, vertexBuffer);

 

 
/* Set the buffer's size, data and usage

 Note the last argument - GL_STATIC_DRAW. This tells the driver that we intend to read from the buffer on the GPU, and don't intend

 to modify the data until we're done with it.

 */


 glBufferData
(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);


 

 
if (!TestGLError("glBufferData"))

 
{

 
return false;

 
}


 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function InitialiseShaders

 @Output fragmentShader              Handle to a fragment shader

 @Output vertexShader                Handle to a vertex shader

 @Output shaderProgram               Handle to a shader program containing the fragment and vertex shader

 @Return Whether the function succeeds or not.

 @Description Initialises shaders, buffers and other state required to begin rendering with OpenGL ES

*******************************************************************************************************************************************/


bool InitialiseShaders( GLuint &fragmentShader, GLuint &vertexShader, GLuint &shaderProgram)  

{

 
/* Concept: Shaders

 OpenGL ES 2.0 uses what are known as shaders to determine how to draw objects on the screen. Instead of the fixed function

 pipeline in early OpenGL or OpenGL ES 1.x, users can now programmatically define how vertices are transformed on screen, what

 data is used where, and how each pixel on the screen is coloured.

 These shaders are written in GL Shading Language ES:
http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf

 which is usually abbreviated to simply "GLSL ES".

 Each shader is compiled on-device and then linked into a shader program, which combines a vertex and fragment shader into a form  

 that the OpenGL ES implementation can execute.

 */



 

 
/* Concept: Fragment Shaders

 In a final buffer of image data, each individual point is referred to as a pixel. Fragment shaders are the part of the pipeline

 which determine how these final pixels are coloured when drawn to the framebuffer. When data is passed through here, the positions

 of these pixels is already set, all that's left to do is set the final colour based on any defined inputs.

 The reason these are called "fragment" shaders instead of "pixel" shaders is due to a small technical difference between the two

 concepts. When you colour a fragment, it may not be the final colour which ends up on screen. This is particularly true when  

 performing blending, where multiple fragments can contribute to the final pixel colour.

 */


 
const char* const fragmentShaderSource = "\

 void main (void)\

 {\

 gl_FragColor = vec4(1.0, 1.0, 0.66 ,1.0);\

 }"
;


 

 
// Create a fragment shader object

 fragmentShader
= glCreateShader(GL_FRAGMENT_SHADER);


 

 
// Load the source code into it

 glShaderSource
(fragmentShader, 1, (const char**)&fragmentShaderSource, NULL);


 

 
// Compile the source code

 glCompileShader
(fragmentShader);


 

 
// Check that the shader compiled

 
GLint isShaderCompiled;

 glGetShaderiv
(fragmentShader, GL_COMPILE_STATUS, &isShaderCompiled);

 
if (!isShaderCompiled)

 
{

 
// If an error happened, first retrieve the length of the log message

 
int infoLogLength, charactersWritten;

 glGetShaderiv
(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);


 

 
// Allocate enough space for the message and retrieve it

 
char* infoLog = new char[infoLogLength];

 glGetShaderInfoLog
(fragmentShader, infoLogLength, &charactersWritten, infoLog);


 

 
// Display the error in a dialog box

 infoLogLength
>1 ? printf("%s", infoLog) : printf("Failed to compile fragment shader.");


 

 
delete[] infoLog;

 
return false;

 
}

 

 
/* Concept: Vertex Shaders

 Vertex shaders primarily exist to allow a developer to express how to orient vertices in 3D space, through transformations like  

 Scaling, Translation or Rotation. Using the same basic layout and structure as a fragment shader, these take in vertex data and  

 output a fully transformed set of positions. Other inputs are also able to be used such as normals or texture coordinates, and can  

 also be transformed and output alongside the position data.

 */


 
// Vertex shader code

 
const char* const vertexShaderSource = "\

   attribute highp vec4 myVertex;\

   uniform mediump mat4 transformationMatrix;\

   void main(void)\

   {\

   gl_Position = transformationMatrix * myVertex;\

   }"
;


 

 
// Create a vertex shader object

 vertexShader
= glCreateShader(GL_VERTEX_SHADER);


 

 
// Load the source code into the shader

 glShaderSource
(vertexShader, 1, (const char**)&vertexShaderSource, NULL);


 

 
// Compile the shader

 glCompileShader
(vertexShader);


 

 
// Check the shader has compiled

 glGetShaderiv
(vertexShader, GL_COMPILE_STATUS, &isShaderCompiled);

 
if (!isShaderCompiled)

 
{

 
// If an error happened, first retrieve the length of the log message

 
int infoLogLength, charactersWritten;

 glGetShaderiv
(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);


 

 
// Allocate enough space for the message and retrieve it

 
char* infoLog = new char[infoLogLength];

 glGetShaderInfoLog
(vertexShader, infoLogLength, &charactersWritten, infoLog);


 

 
// Display the error in a dialog box

 infoLogLength
>1 ? printf("%s", infoLog) : printf("Failed to compile vertex shader.");


 

 
delete[] infoLog;

 
return false;

 
}


 

 
// Create the shader program

 shaderProgram
= glCreateProgram();


 

 
// Attach the fragment and vertex shaders to it

 glAttachShader
(shaderProgram, fragmentShader);

 glAttachShader
(shaderProgram, vertexShader);


 

 
// Bind the vertex attribute "myVertex" to location VERTEX_ARRAY (0)

 glBindAttribLocation
(shaderProgram, VERTEX_ARRAY, "myVertex");


 

 
// Link the program

 glLinkProgram
(shaderProgram);


 

 
// Check if linking succeeded in the same way we checked for compilation success

 
GLint isLinked;

 glGetProgramiv
(shaderProgram, GL_LINK_STATUS, &isLinked);

 
if (!isLinked)

 
{

 
// If an error happened, first retrieve the length of the log message

 
int infoLogLength, charactersWritten;

 glGetProgramiv
(shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);


 

 
// Allocate enough space for the message and retrieve it

 
char* infoLog = new char[infoLogLength];

 glGetProgramInfoLog
(shaderProgram, infoLogLength, &charactersWritten, infoLog);


 

 
// Display the error in a dialog box

 infoLogLength
>1 ? printf("%s", infoLog) : printf("Failed to link shader program.");


 

 
delete[] infoLog;

 
return false;

 
}

 

 
/* Use the Program

 Calling glUseProgram tells OpenGL ES that the application intends to use this program for rendering. Now that it's installed into

 the current state, any further glDraw* calls will use the shaders contained within it to process scene data. Only one program can

 be active at once, so in a multi-program application this function would be called in the render loop. Since this application only

 uses one program it can be installed in the current state and left there.

 */


 glUseProgram
(shaderProgram);


 

 
if (!TestGLError("glUseProgram"))

 
{

 
return false;

 
}

 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function RenderScene

 @Input shaderProgram               The shader program used to render the scene

 @Input eglDisplay                  The EGLDisplay used by the application

 @Input eglSurface The EGLSurface created by the application

 @Return Whether the function succeeds or not.

 @Description Renders the scene to the framebuffer. Usually called within a loop.

*******************************************************************************************************************************************/


bool RenderScene( GLuint shaderProgram, EGLDisplay eglDisplay, EGLSurface eglSurface )  

{

 
/* Set the clear color

 At the start of a frame, generally you clear the image to tell OpenGL ES that you're done with whatever was there before and want to

 draw a new frame. In order to do that however, OpenGL ES needs to know what colour to set in the image's place. glClearColor

 sets this value as 4 floating point values between 0.0 and 1.0, as the Red, Green, Blue and Alpha channels. Each value represents

 the intensity of the particular channel, with all 0.0 being transparent black, and all 1.0 being opaque white. Subsequent calls to

 glClear with the colour bit will clear the frame buffer to this value.

 The functions glClearDepth and glClearStencil allow an application to do the same with depth and stencil values respectively.

 */


 glClearColor
(0.6f, 0.8f, 1.0f, 1.0f);


 

 
/* Clears the color buffer.

 glClear is used here with the Colour Buffer to clear the colour. It can also be used to clear the depth or stencil buffer using  

 GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT, respectively.

 */


 glClear
(GL_COLOR_BUFFER_BIT);


 

 
// Get the location of the transformation matrix in the shader using its name

 
int matrixLocation = glGetUniformLocation(shaderProgram, "transformationMatrix");


 

 
// Matrix used to specify the orientation of the triangle on screen.

 
const float transformationMatrix[] =

 
{

 
1.0f,0.0f,0.0f,0.0f,

 
0.0f,1.0f,0.0f,0.0f,

 
0.0f,0.0f,1.0f,0.0f,

 
0.0f,0.0f,0.0f,1.0f

 
};


 

 
// Pass the transformationMatrix to the shader using its location

 glUniformMatrix4fv
( matrixLocation, 1, GL_FALSE, transformationMatrix);

 
if (!TestGLError("glUniformMatrix4fv"))

 
{

 
return false;

 
}


 

 
// Enable the user-defined vertex array

 glEnableVertexAttribArray
(VERTEX_ARRAY);


 

 
// Sets the vertex data to this attribute index, with the number of floats in each position

 glVertexAttribPointer
(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);

 
if (!TestGLError("glVertexAttribPointer"))

 
{

 
return false;

 
}


 

 
/* Draw the triangle

 glDrawArrays is a draw call, and executes the shader program using the vertices and other state set by the user. Draw calls are the

 functions which tell OpenGL ES when to actually draw something to the framebuffer given the current state.

 glDrawArrays causes the vertices to be submitted sequentially from the position given by the "first" argument until it has processed

 "count" vertices. Other draw calls exist, notably glDrawElements which also accepts index data to allow the user to specify that

 some vertices are accessed multiple times, without copying the vertex multiple times.

 Others include versions of the above that allow the user to draw the same object multiple times with slightly different data, and

 a version of glDrawElements which allows a user to restrict the actual indices accessed.

 */


 glDrawArrays
(GL_TRIANGLES, 0, 3);

 
if (!TestGLError("glDrawArrays"))

 
{

 
return false;

 
}


 

 
/* Present the display data to the screen.

 When rendering to a Window surface, OpenGL ES is double buffered. This means that OpenGL ES renders directly to one frame buffer,  

 known as the back buffer, whilst the display reads from another - the front buffer. eglSwapBuffers signals to the windowing system

 that OpenGL ES 2.0 has finished rendering a scene, and that the display should now draw to the screen from the new data. At the same

 time, the front buffer is made available for OpenGL ES 2.0 to start rendering to. In effect, this call swaps the front and back  

 buffers.

 */


 
if (!eglSwapBuffers(eglDisplay, eglSurface) )

 
{

 
TestEGLError("eglSwapBuffers");

 
return false;

 
}

 

 
return true;

}


 

/*!*****************************************************************************************************************************************

 @Function DeInitialiseGLState

 @Input fragmentShader              Handle to a fragment shader

 @Input vertexShader                Handle to a vertex shader

 @Input shaderProgram               Handle to a shader program containing the fragment and vertex shader

 @Input vertexBuffer                Handle to a vertex buffer object

 @Description Releases the resources created by "InitialiseGLState"

*******************************************************************************************************************************************/


void DeInitialiseGLState( GLuint fragmentShader, GLuint vertexShader, GLuint shaderProgram, GLuint vertexBuffer )  

{

 
// Frees the OpenGL handles for the program and the 2 shaders

 glDeleteShader
(fragmentShader);

 glDeleteShader
(vertexShader);

 glDeleteProgram
(shaderProgram);


 

 
// Delete the VBO as it is no longer needed

 glDeleteBuffers
(1, &vertexBuffer);

}


 

/*!*****************************************************************************************************************************************

 @Function ReleaseEGLState

 @Input eglDisplay                   The EGLDisplay used by the application

 @Description Releases all resources allocated by EGL

*******************************************************************************************************************************************/


void ReleaseEGLState(EGLDisplay eglDisplay)  

{

 
// To release the resources in the context, first the context has to be released from its binding with the current thread.

 eglMakeCurrent
(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);


 

 
// Terminate the display, and any resources associated with it (including the EGLContext)

 eglTerminate
(eglDisplay);

}


 

/*!*****************************************************************************************************************************************

 @Function main

 @Input argc                        Number of arguments passed to the application, ignored.

 @Input argv                        Command line strings passed to the application, ignored.

 @Return Result code to send to the Operating System

 @Description Main function of the program, executes other functions.

*******************************************************************************************************************************************/


int main(int /*argc*/, char **/*argv*/)

{

 
// EGL variables

 
EGLDisplay eglDisplay = NULL;

 
EGLConfig eglConfig = NULL;

 
EGLSurface eglSurface = NULL;

 
EGLContext eglContext = NULL;


 

 
// Handles for the two shaders used to draw the triangle, and the program handle which combines them.

 
GLuint fragmentShader = 0, vertexShader = 0;

 
GLuint shaderProgram = 0;


 

 
// A vertex buffer object to store our model data.

 
GLuint vertexBuffer = 0;

 

 
// Create and Initialise an EGLDisplay

 
if (!CreateEGLDisplay(eglDisplay))

 
{

 
goto cleanup;

 
}


 

 
// Choose an EGLConfig for the application, used when setting up the rendering surface and EGLContext

 
if (!ChooseEGLConfig(eglDisplay, eglConfig))

 
{

 
goto cleanup;

 
}


 

 
// Create an EGLSurface for rendering

 
if (!CreateEGLSurface(eglDisplay, eglConfig, eglSurface))

 
{

 
goto cleanup;

 
}


 

 
// Setup the EGL Context from the other EGL constructs created so far, so that the application is ready to submit OpenGL ES commands

 
if (!SetupEGLContext(eglDisplay, eglConfig, eglSurface, eglContext))

 
{

 
goto cleanup;

 
}


 

 
// Initialise the vertex data in the application

 
if (!InitialiseBuffer(vertexBuffer))

 
{

 
goto cleanup;

 
}

 

 
// Initialise the fragment and vertex shaders used in the application

 
if (!InitialiseShaders(fragmentShader, vertexShader, shaderProgram))

 
{

 
goto cleanup;

 
}

 

 
// Renders a triangle for 800 frames using the state setup in the previous function

 
for (int i = 0; i < 800; ++i)

 
{

 
if (!RenderScene(shaderProgram, eglDisplay, eglSurface))

 
{

 
break;

 
}

 
}


 

 
// Release any resources we created in the Initialise functions

 
DeInitialiseGLState(fragmentShader, vertexShader, shaderProgram, vertexBuffer);


 

cleanup
:

 
// Release the EGL State

 
ReleaseEGLState(eglDisplay);


 

 
// Destroy the eglWindow

 
return 0;

}


 

/*******************************************************************************************************************************************

 End of file (OGLES2HelloAPI_NullWS.cpp)

*******************************************************************************************************************************************/






David Batzle

unread,
Aug 6, 2015, 10:05:27 AM8/6/15
to beagl...@googlegroups.com
At home I have a very simple program I wrote for the Beagleboard that does what you are trying to do. I think it should compile for the BBB fairly easily. When I get home later this evening I can find it and send it to you.



--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


John London

unread,
Aug 6, 2015, 11:09:35 AM8/6/15
to BeagleBoard, n2...@yahoo.com
David, thank you very much indeed, that would be extremely helpful!


...

David Batzle

unread,
Aug 6, 2015, 9:01:25 PM8/6/15
to beagl...@googlegroups.com
The files are located at:
http://www.dcbcyber.com/tmp/src.tar.gz
or
http://www.dcbcyber.com/tmp/src.zip

Originally this did more than what you are asking for. I had Bullet physics doing ray casting and collision detection and OpenAL playing sounds. I also had two rooms connected by a corridor. Unfortunately I seem to have lost my media files that I created. Without drawing the meshes it should still load up and draw a cross hair in the middle of the screen. I also included a line you can uncomment that should turn the cross hair into a triangle.

I commented out the code for physics, sound, world loading, and input and movement. Feel free to play with that stuff if you feel like it.

The code is messy. I never got around to cleaning up or finishing.

If it doesn't work let me know. I will help as much as I can. I no longer have a Beagleboard. I don't have a BBB but I might get one. I do have a Pandaboard which is similar.

David.
--------------------------------------------
On Thu, 8/6/15, John London <john....@blackkitetechnology.com> wrote:

Subject: Re: [beagleboard] OpenGL and BBB - simple HelloTriangle example
To: "BeagleBoard" <beagl...@googlegroups.com>
Cc: n2...@yahoo.com
Date: Thursday, August 6, 2015, 11:09 AM

John London

unread,
Aug 7, 2015, 3:19:22 AM8/7/15
to BeagleBoard
Thanks David, that's very kind.
Reply all
Reply to author
Forward
0 new messages