Implement a more centralized architecture for OpenGL (ES) code.

Summary

The current implementation of OpenGL / OpenGL ES rendering support scatters the different overridden calls across multiple files and classes (OpenGLTexture_Image & GLESTexture_Image, OpenGLGpuBuffer & GLESGpuBuffer, etc...). Another way we could go about this would be to have only one file/class to specify the calls we're to override, then one to implement the needed code for each rendering API.

Motivation

Having API specific code scattered across different files could prove a bit harder to maintain, even with name prefixes for each API. This RFC aims to improve that by grouping most API specific code in one place.

Proposal

The current rendering code could be implemented as:

class Renderer {
  public:
    // Wraps calls to `glFoo` for OpenGL 4.5 and OpenGL ES 3.2
    virtual void foo(...) const = 0;
};

class OpenGLRenderer: public Renderer {
  public:
    virtual void foo(...) const override {
        // OpenGL implementation of the call
    }
}

class GLESRenderer: public Renderer {
  protected:
    virtual void foo(...) const override {
        // GLES implementation of the call
    }
}

This should help group up all API specific code into one class for each API.

If we wish to mimick the static calls of OpenGL or reduce the need of passing around the renderer, we can instead do:

// renderer.h
class Renderer {
  protected:
    static std::unique_ptr<Renderer> _rendererInstance;  // Initialized somewhere else.

  public:
    void initRenderer(Api renderingApi) {
        // Creates a specialized renderer for the chosen API and assigns it to _rendererInstance.
    }

    // Wraps calls to `glFoo` for OpenGL 4.5 and OpenGL ES 3.2
    static void foo(...) {
        _rendererIntance->fooImpl(...);
    }

  protected:
    virtual void fooImpl(...) const = 0;
};

// opengl_renderer.h
class OpenGLRenderer: public Renderer {
  protected:
    virtual void fooImpl(...) const override {
        // OpenGL implementation of `glFoo`
    }
}

// gles_renderer.h
class GLESRenderer: public Renderer {
  protected:
    virtual void fooImpl(...) const override {
        // GLES implementation of `glFoo`
    }
}

Impact on already existing code

The proposed changes here should allow all API specific code to reside in one place, with minimal changes on the code currently using the existing API.

Roadmap

  1. Setup renderer class and declare all calls that must be overidden or are simply shared between OpenGL and OpenGL ES.
  2. Merge classes that are specialized for OpenGL or GLES, while moving API specific implementations to the corresponding renderer.
Edited by Tarek Yasser