Chapter 4. Printf in OpenGL ES

Now, having OpenGL ES projects for 2 different platforms, we can see what is common and what is different.

Common is generic structure: Creating GL context, initializing data, main loop with frames rendering, exit. GL calls (Thank God!) look similar too. The difference is in program and GL initialization, in GL-related includes (gl/egl on Android and glfw/glad in Windows). Events and input handling are different as well.

Well, let’s encapsulate platform-specific stuff in 2 separate sets (one for PC and another one for Android).

We will start here from printf-alike function, which is essential for development, and obviously will require 2 different implementations for Windows and for Android. We'll start in

Windows:

  1. Start Visual Studio. Open C:\CPP\a999hello\p_windows\p_windows.sln

2. Add a placeholder: right-click on “p_windows ” project -> Add -> New Filter

Name - xPlatform


3. Physically we will keep Windows-specific files in C:\CPP\p_windows folder. Need to inform Project about this new location:

Right-click on “p_windows” project -> Properties, All configurationsWin32, Configuration properties -> C++ -> General -> Additional Include Directories -> Edit, add New Line, browse to

C:\CPP\p_windows

Select Folder, Ok, Apply, Ok


4. Under xPlatform add a header file: Right-click on xPlatform, Add -> New Item,

  • pick “Header File (.h)”
  • name – platform.h
  • Default location is not what we want, change it to C:\CPP\p_windows

Then – Add.

As was announced above, we will write a function that can print something on the screen (in our case – in Console window), something like printf.

We can’t use printf directly because:

  • It will work only on PC. Android will require different implementation.
  • It doesn’t work at all on OpenGL screen.
  • We need it in Debug configuration only, it must be disabled in Release configuration.

I'll call it mylog(). I want it to accept parameters the same way as printf (format string first and then – whatever).

Also, it should do nothing in Release configuration. So, the code is:

#pragma once
#include "stdio.h"
#include <stdarg.h>

inline void mylog(const char* _Format, ...) {
#ifdef _DEBUG
    va_list _ArgList;
    va_start(_ArgList, _Format);
    vprintf(_Format, _ArgList);
    va_end(_ArgList);
#endif
};

Now we are ready to try it.


5. Open main.cpp.

On the top, in 'includes' section add a new line:

#include "platform.h"

In main(void) function, in the very beginning, right after “{“ add a new line

mylog(" Hello %s !\n", "Windows");

Pick Debug configuration.

Build and run (green arrow). Look at Console window:

Hello Windows !


6. Now we can remove “#include <stdio.h>” from main.cpp and change error_callback() from using printf to mylog (it was an only printf occurrence in main.cpp):

static void error_callback(int error, const char* description)
{
    mylog("Error: %s\n", description);
}

Build and run - good.


Now - on

Android:

On Android it will be a bit different. First – there is no Console window. Second – no “windows” at all (in Windows sense). However, it has “LogCat” - Android’s own mechanism for printing debug/development messages.

7. Close and re-start Visual Studio, open C:\CPP\a999hello\p_android\p_android.sln.


8. Again, need to add a filter (virtual folder): right-click on p_android.NativeActivity project -> Add -> New Filter.

Same name, xPlatform


9. Under xPlatform create a header file: Right-click on xPlatform, Add -> New Item,

  • pick “Header File (.h)”
  • name – platform.h
  • Change location to C:\CPP\p_android\

Then – Add.

The code:

#pragma once
#include <android/log.h>
#include "stdio.h"

inline void mylog(const char* _Format, ...) {
#ifdef _DEBUG
    char outStr[1024];
    va_list _ArgList;
    va_start(_ArgList, _Format);
    vsprintf(outStr, _Format, _ArgList);
    __android_log_print(ANDROID_LOG_INFO, "mylog", outStr, NULL);
    va_end(_ArgList);
#endif
};

This code relies on _DEBUG constant, but it is missed in Android's debug configuration.


10. Open p_android.NativeApplication project properties, pick Debug configuration, ARM64,

go to Configuration Properties -> C/C++ -> Preprocessor, open Preprocessor Definitions -> Edit. If _DEBUG is missed - add it, then OK, Apply, Ok.


11. Now open main.cpp.

In #include section add a new line:

#include "platform.h"

In android_main (…), in the very beginning, right after “{“ add a new line:

mylog(" Hello %s ! \n", "Android");


12. Again, we need to inform p_android.NativeActivity project where to look for platform.h header.

Right-click on p_android.NativeActivity project -> Properties, All Configurations, ARM64. Open Configuration Properties -> C/C++ -> General -> Additional Include Directories -> Edit, Add new line, navigate to

C:\CPP\p_android

Select Folder, Ok, Apply, Ok.


13. Turn on and unlock your Android device, plug it in with USB cable, allow USB Debugging.


14. Build and run (green arrow). On Android side nothing changed, same green flashing screen, but now we can open LogCat.


15. On VS screen open top menu -> Tools -> Android Tools -> Logcat.

In <Search Logcat> field print “mylog”, Enter. What do we have here?:

Hello Android !

VS top menu -> Debug -> Stop Debugging.


Leave a Reply

Your email address will not be published. Required fields are marked *