Browse Source

Split OpenGL2 and OpenGL3 implementations into separate files

Signed-off-by: falkTX <falktx@falktx.com>
pull/506/head
falkTX 6 months ago
parent
commit
a56ff9799e
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
17 changed files with 1459 additions and 960 deletions
  1. +34
    -6
      .github/workflows/build.yml
  2. +1
    -1
      Makefile.plugins.mk
  3. +4
    -0
      cmake/DPF-plugin.cmake
  4. +4
    -0
      dgl/Base.hpp
  5. +3
    -4
      dgl/Cairo.hpp
  6. +9
    -9
      dgl/Geometry.hpp
  7. +10
    -6
      dgl/Image.hpp
  8. +7
    -0
      dgl/Makefile
  9. +6
    -15
      dgl/OpenGL.hpp
  10. +33
    -3
      dgl/src/Cairo.cpp
  11. +4
    -910
      dgl/src/OpenGL.cpp
  12. +559
    -0
      dgl/src/OpenGL2.cpp
  13. +710
    -0
      dgl/src/OpenGL3.cpp
  14. +33
    -1
      dgl/src/Stub.cpp
  15. +40
    -5
      dgl/src/Vulkan.cpp
  16. +1
    -0
      examples/Parameters/CMakeLists.txt
  17. +1
    -0
      examples/Parameters/Makefile

+ 34
- 6
.github/workflows/build.yml View File

@@ -98,24 +98,52 @@ jobs:
run: | run: |
make clean >/dev/null make clean >/dev/null
make -j ${{ env.JOBS }} make -j ${{ env.JOBS }}
- name: With OpenGL 3.x
- name: Without Cairo
env: env:
CFLAGS: -Werror CFLAGS: -Werror
CXXFLAGS: -Werror CXXFLAGS: -Werror
run: | run: |
make clean >/dev/null make clean >/dev/null
make -j ${{ env.JOBS }} USE_OPENGL3=true
- name: Without Cairo
make -j ${{ env.JOBS }} HAVE_CAIRO=false
- name: Without OpenGL
env: env:
CFLAGS: -Werror CFLAGS: -Werror
CXXFLAGS: -Werror CXXFLAGS: -Werror
run: | run: |
make clean >/dev/null make clean >/dev/null
make -j ${{ env.JOBS }} HAVE_CAIRO=false
- name: Without OpenGL
make -j ${{ env.JOBS }} HAVE_OPENGL=false
- name: With UI_TYPE=generic
env: env:
CFLAGS: -Werror CFLAGS: -Werror
CXXFLAGS: -Werror CXXFLAGS: -Werror
run: | run: |
make clean >/dev/null make clean >/dev/null
make -j ${{ env.JOBS }} HAVE_OPENGL=false
make -j ${{ env.JOBS }} -C examples/Parameters UI_TYPE=generic
- name: With UI_TYPE=gles2
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} -C examples/Parameters UI_TYPE=gles2
- name: With UI_TYPE=gles3
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} -C examples/Parameters UI_TYPE=gles3
- name: With UI_TYPE=opengl
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} -C examples/Parameters UI_TYPE=opengl
- name: With UI_TYPE=opengl3
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} -C examples/Parameters UI_TYPE=opengl3

+ 1
- 1
Makefile.plugins.mk View File

@@ -9,7 +9,7 @@
# extra useful variables to define before including this file: # extra useful variables to define before including this file:
# - DPF_BUILD_DIR: where to place temporary build files # - DPF_BUILD_DIR: where to place temporary build files
# - DPF_TARGET_DIR: where to place final binary files # - DPF_TARGET_DIR: where to place final binary files
# - UI_TYPE: one of cairo, gles2, gles3, opengl, opengl3 or external, with opengl being default
# - UI_TYPE: one of cairo, external, gles2, gles3, opengl, opengl3 or webview, with opengl being default
# ("generic" is also allowed if only using basic DPF classes like image widgets) # ("generic" is also allowed if only using basic DPF classes like image widgets)


# override the "all" target after including this file to define which plugin formats to build, like so: # override the "all" target after including this file to define which plugin formats to build, like so:


+ 4
- 0
cmake/DPF-plugin.cmake View File

@@ -1003,6 +1003,7 @@ function(dpf__add_dgl_gles2 SHARED_RESOURCES USE_FILE_BROWSER USE_WEB_VIEW)
"${DPF_ROOT_DIR}/dgl/src/Window.cpp" "${DPF_ROOT_DIR}/dgl/src/Window.cpp"
"${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp" "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp" "${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL3.cpp"
"${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp") "${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp")
if(SHARED_RESOURCES) if(SHARED_RESOURCES)
target_sources(dgl-gles2 PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp") target_sources(dgl-gles2 PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp")
@@ -1101,6 +1102,7 @@ function(dpf__add_dgl_gles3 SHARED_RESOURCES USE_FILE_BROWSER USE_WEB_VIEW)
"${DPF_ROOT_DIR}/dgl/src/Window.cpp" "${DPF_ROOT_DIR}/dgl/src/Window.cpp"
"${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp" "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp" "${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL3.cpp"
"${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp") "${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp")
if(SHARED_RESOURCES) if(SHARED_RESOURCES)
target_sources(dgl-gles3 PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp") target_sources(dgl-gles3 PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp")
@@ -1194,6 +1196,7 @@ function(dpf__add_dgl_opengl SHARED_RESOURCES USE_FILE_BROWSER USE_WEB_VIEW)
"${DPF_ROOT_DIR}/dgl/src/Window.cpp" "${DPF_ROOT_DIR}/dgl/src/Window.cpp"
"${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp" "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp" "${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL2.cpp"
"${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp") "${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp")
if(SHARED_RESOURCES) if(SHARED_RESOURCES)
target_sources(dgl-opengl PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp") target_sources(dgl-opengl PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp")
@@ -1289,6 +1292,7 @@ function(dpf__add_dgl_opengl3 SHARED_RESOURCES USE_FILE_BROWSER USE_WEB_VIEW)
"${DPF_ROOT_DIR}/dgl/src/Window.cpp" "${DPF_ROOT_DIR}/dgl/src/Window.cpp"
"${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp" "${DPF_ROOT_DIR}/dgl/src/WindowPrivateData.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp" "${DPF_ROOT_DIR}/dgl/src/OpenGL.cpp"
"${DPF_ROOT_DIR}/dgl/src/OpenGL3.cpp"
"${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp") "${DPF_ROOT_DIR}/dgl/src/NanoVG.cpp")
if(SHARED_RESOURCES) if(SHARED_RESOURCES)
target_sources(dgl-opengl3 PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp") target_sources(dgl-opengl3 PRIVATE "${DPF_ROOT_DIR}/dgl/src/Resources.cpp")


+ 4
- 0
dgl/Base.hpp View File

@@ -49,6 +49,10 @@
# error DGL_FILE_BROWSER_DISABLED has been replaced by DGL_USE_FILE_BROWSER (opt-in vs opt-out) # error DGL_FILE_BROWSER_DISABLED has been replaced by DGL_USE_FILE_BROWSER (opt-in vs opt-out)
#endif #endif


#ifndef DGL_ALLOW_DEPRECATED_METHODS
# define DGL_ALLOW_DEPRECATED_METHODS 1
#endif

// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
// Define namespace // Define namespace




+ 3
- 4
dgl/Cairo.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -165,10 +165,9 @@ private:
Widget display function. Widget display function.
Implemented internally to pass context into the drawing function. Implemented internally to pass context into the drawing function.
*/ */
void onDisplay() override
void onDisplay() final
{ {
const CairoGraphicsContext& context((const CairoGraphicsContext&)BaseWidget::getGraphicsContext());
onCairoDisplay(context);
onCairoDisplay(static_cast<const CairoGraphicsContext&>(BaseWidget::getGraphicsContext()));
} }


DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoBaseWidget); DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoBaseWidget);


+ 9
- 9
dgl/Geometry.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -360,25 +360,23 @@ public:
*/ */
bool isNotNull() const noexcept; bool isNotNull() const noexcept;


#ifndef DPF_TEST_POINT_CPP
/** /**
Draw this line using the provided graphics context, optionally specifying line width. Draw this line using the provided graphics context, optionally specifying line width.
*/ */
void draw(const GraphicsContext& context, T width = 1); void draw(const GraphicsContext& context, T width = 1);
#endif


Line<T>& operator=(const Line<T>& line) noexcept; Line<T>& operator=(const Line<T>& line) noexcept;
bool operator==(const Line<T>& line) const noexcept; bool operator==(const Line<T>& line) const noexcept;
bool operator!=(const Line<T>& line) const noexcept; bool operator!=(const Line<T>& line) const noexcept;


#ifndef DPF_TEST_POINT_CPP
#ifdef DGL_ALLOW_DEPRECATED_METHODS
/** /**
Draw this line using the current OpenGL state.@n Draw this line using the current OpenGL state.@n
DEPRECATED Please use draw(const GraphicsContext&) instead. DEPRECATED Please use draw(const GraphicsContext&) instead.
*/ */
DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)") DISTRHO_DEPRECATED_BY("draw(const GraphicsContext&)")
void draw(); void draw();
#endif
#endif


private: private:
Point<T> posStart, posEnd; Point<T> posStart, posEnd;
@@ -489,7 +487,7 @@ public:
bool operator==(const Circle<T>& cir) const noexcept; bool operator==(const Circle<T>& cir) const noexcept;
bool operator!=(const Circle<T>& cir) const noexcept; bool operator!=(const Circle<T>& cir) const noexcept;


#ifndef DPF_TEST_POINT_CPP
#ifdef DGL_ALLOW_DEPRECATED_METHODS
/** /**
Draw this circle using the current OpenGL state.@n Draw this circle using the current OpenGL state.@n
DEPRECATED Please use draw(const GraphicsContext&) instead. DEPRECATED Please use draw(const GraphicsContext&) instead.
@@ -503,7 +501,7 @@ public:
*/ */
DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)") DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)")
void drawOutline(); void drawOutline();
#endif
#endif


private: private:
Point<T> fPos; Point<T> fPos;
@@ -582,7 +580,7 @@ public:
bool operator==(const Triangle<T>& tri) const noexcept; bool operator==(const Triangle<T>& tri) const noexcept;
bool operator!=(const Triangle<T>& tri) const noexcept; bool operator!=(const Triangle<T>& tri) const noexcept;


#ifndef DPF_TEST_POINT_CPP
#ifdef DGL_ALLOW_DEPRECATED_METHODS
/** /**
Draw this triangle using the current OpenGL state.@n Draw this triangle using the current OpenGL state.@n
DEPRECATED Please use draw(const GraphicsContext&) instead. DEPRECATED Please use draw(const GraphicsContext&) instead.
@@ -596,7 +594,7 @@ public:
*/ */
DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)") DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)")
void drawOutline(); void drawOutline();
#endif
#endif


private: private:
Point<T> pos1, pos2, pos3; Point<T> pos1, pos2, pos3;
@@ -813,6 +811,7 @@ public:
bool operator==(const Rectangle<T>& size) const noexcept; bool operator==(const Rectangle<T>& size) const noexcept;
bool operator!=(const Rectangle<T>& size) const noexcept; bool operator!=(const Rectangle<T>& size) const noexcept;


#ifdef DGL_ALLOW_DEPRECATED_METHODS
/** /**
Draw this rectangle using the current OpenGL state.@n Draw this rectangle using the current OpenGL state.@n
DEPRECATED Please use draw(const GraphicsContext&) instead. DEPRECATED Please use draw(const GraphicsContext&) instead.
@@ -826,6 +825,7 @@ public:
*/ */
DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)") DISTRHO_DEPRECATED_BY("drawOutline(const GraphicsContext&)")
void drawOutline(); void drawOutline();
#endif


private: private:
Point<T> pos; Point<T> pos;


+ 10
- 6
dgl/Image.hpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -17,17 +17,21 @@
#ifndef DGL_IMAGE_HPP_INCLUDED #ifndef DGL_IMAGE_HPP_INCLUDED
#define DGL_IMAGE_HPP_INCLUDED #define DGL_IMAGE_HPP_INCLUDED


#ifdef DGL_CAIRO
#include "Cairo.hpp"
#if defined(DGL_CAIRO)
# include "Cairo.hpp"
#elif defined(DGL_OPENGL)
# include "OpenGL.hpp"
#elif defined(DGL_VULKAN)
# include "Vulkan.hpp"
#else #else
#include "OpenGL.hpp"
# include "Base.hpp"
#endif #endif


START_NAMESPACE_DGL START_NAMESPACE_DGL


#ifdef DGL_CAIRO
#if defined(DGL_CAIRO)
typedef CairoImage Image; typedef CairoImage Image;
#else
#elif defined(DGL_OPENGL)
typedef OpenGLImage Image; typedef OpenGLImage Image;
#endif #endif




+ 7
- 0
dgl/Makefile View File

@@ -73,6 +73,7 @@ endif


OBJS_gles2 = $(OBJS_common) \ OBJS_gles2 = $(OBJS_common) \
$(BUILD_DIR)/dgl/OpenGL.cpp.gles2.o \ $(BUILD_DIR)/dgl/OpenGL.cpp.gles2.o \
$(BUILD_DIR)/dgl/OpenGL3.cpp.gles2.o \
$(BUILD_DIR)/dgl/NanoVG.cpp.gles2.o $(BUILD_DIR)/dgl/NanoVG.cpp.gles2.o


ifeq ($(MACOS),true) ifeq ($(MACOS),true)
@@ -85,6 +86,7 @@ endif


OBJS_gles3 = $(OBJS_common) \ OBJS_gles3 = $(OBJS_common) \
$(BUILD_DIR)/dgl/OpenGL.cpp.gles3.o \ $(BUILD_DIR)/dgl/OpenGL.cpp.gles3.o \
$(BUILD_DIR)/dgl/OpenGL3.cpp.gles3.o \
$(BUILD_DIR)/dgl/NanoVG.cpp.gles3.o $(BUILD_DIR)/dgl/NanoVG.cpp.gles3.o


ifeq ($(MACOS),true) ifeq ($(MACOS),true)
@@ -97,6 +99,7 @@ endif


OBJS_opengl = $(OBJS_common) \ OBJS_opengl = $(OBJS_common) \
$(BUILD_DIR)/dgl/OpenGL.cpp.opengl.o \ $(BUILD_DIR)/dgl/OpenGL.cpp.opengl.o \
$(BUILD_DIR)/dgl/OpenGL2.cpp.opengl.o \
$(BUILD_DIR)/dgl/NanoVG.cpp.opengl.o $(BUILD_DIR)/dgl/NanoVG.cpp.opengl.o


ifeq ($(MACOS),true) ifeq ($(MACOS),true)
@@ -109,6 +112,7 @@ endif


OBJS_opengl3 = $(OBJS_common) \ OBJS_opengl3 = $(OBJS_common) \
$(BUILD_DIR)/dgl/OpenGL.cpp.opengl3.o \ $(BUILD_DIR)/dgl/OpenGL.cpp.opengl3.o \
$(BUILD_DIR)/dgl/OpenGL3.cpp.opengl3.o \
$(BUILD_DIR)/dgl/NanoVG.cpp.opengl3.o $(BUILD_DIR)/dgl/NanoVG.cpp.opengl3.o


ifeq ($(MACOS),true) ifeq ($(MACOS),true)
@@ -146,7 +150,10 @@ TARGETS += $(BUILD_DIR)/libdgl-cairo.a
endif endif


ifeq ($(HAVE_OPENGL),true) ifeq ($(HAVE_OPENGL),true)
TARGETS += $(BUILD_DIR)/libdgl-gles2.a
TARGETS += $(BUILD_DIR)/libdgl-gles3.a
TARGETS += $(BUILD_DIR)/libdgl-opengl.a TARGETS += $(BUILD_DIR)/libdgl-opengl.a
TARGETS += $(BUILD_DIR)/libdgl-opengl3.a
endif endif


ifeq ($(HAVE_STUB),true) ifeq ($(HAVE_STUB),true)


+ 6
- 15
dgl/OpenGL.hpp View File

@@ -24,18 +24,7 @@


START_NAMESPACE_DGL START_NAMESPACE_DGL


// -----------------------------------------------------------------------

/**
OpenGL Graphics context.
*/
struct OpenGLGraphicsContext : GraphicsContext
{
#ifdef DGL_USE_OPENGL3
#endif
};

// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


static inline static inline
ImageFormat asDISTRHOImageFormat(const GLenum format) ImageFormat asDISTRHOImageFormat(const GLenum format)
@@ -87,7 +76,7 @@ GLenum asOpenGLImageFormat(const ImageFormat format)
return 0x0; return 0x0;
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


/** /**
OpenGL Image class. OpenGL Image class.
@@ -157,6 +146,7 @@ public:
inline void drawAt(const GraphicsContext& context, int x, int y) inline void drawAt(const GraphicsContext& context, int x, int y)
{ drawAt(context, Point<int>(x, y)); } { drawAt(context, Point<int>(x, y)); }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
/** /**
Constructor using raw image data, specifying an OpenGL image format. Constructor using raw image data, specifying an OpenGL image format.
@note @a rawData must remain valid for the lifetime of this Image. @note @a rawData must remain valid for the lifetime of this Image.
@@ -200,6 +190,7 @@ public:
*/ */
DISTRHO_DEPRECATED DISTRHO_DEPRECATED
GLenum getType() const noexcept { return GL_UNSIGNED_BYTE; } GLenum getType() const noexcept { return GL_UNSIGNED_BYTE; }
#endif // DGL_ALLOW_DEPRECATED_METHODS


private: private:
bool setupCalled; bool setupCalled;
@@ -207,7 +198,7 @@ private:
GLuint textureId; GLuint textureId;
}; };


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


typedef ImageBaseAboutWindow<OpenGLImage> OpenGLImageAboutWindow; typedef ImageBaseAboutWindow<OpenGLImage> OpenGLImageAboutWindow;
typedef ImageBaseButton<OpenGLImage> OpenGLImageButton; typedef ImageBaseButton<OpenGLImage> OpenGLImageButton;
@@ -215,7 +206,7 @@ typedef ImageBaseKnob<OpenGLImage> OpenGLImageKnob;
typedef ImageBaseSlider<OpenGLImage> OpenGLImageSlider; typedef ImageBaseSlider<OpenGLImage> OpenGLImageSlider;
typedef ImageBaseSwitch<OpenGLImage> OpenGLImageSwitch; typedef ImageBaseSwitch<OpenGLImage> OpenGLImageSwitch;


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


END_NAMESPACE_DGL END_NAMESPACE_DGL




+ 33
- 3
dgl/src/Cairo.cpp View File

@@ -32,16 +32,38 @@
// templated classes // templated classes
#include "ImageBaseWidgets.cpp" #include "ImageBaseWidgets.cpp"


// --------------------------------------------------------------------------------------------------------------------
// Check for correct build config

#ifndef DGL_CAIRO
# error Build config error, Cairo was NOT requested while building Cairo code
#endif
#ifdef DGL_OPENGL
# error Build config error, OpenGL requested while building Cairo code
#endif
#ifdef DGL_VULKAN
# error Build config error, Vulkan requested while building Cairo code
#endif
#ifdef DGL_USE_GLES2
# error Build config error, GLESv2 requested while building Cairo code
#endif
#ifdef DGL_USE_GLES3
# error Build config error, GLESv3 requested while building Cairo code
#endif
#ifdef DGL_USE_OPENGL3
# error Build config error, OpenGL3 requested while building Cairo code
#endif

START_NAMESPACE_DGL START_NAMESPACE_DGL


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


static void notImplemented(const char* const name) static void notImplemented(const char* const name)
{ {
d_stderr2("Cairo function not implemented: %s", name); d_stderr2("Cairo function not implemented: %s", name);
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Color // Color


void Color::setFor(const GraphicsContext& context, const bool includeAlpha) void Color::setFor(const GraphicsContext& context, const bool includeAlpha)
@@ -54,7 +76,7 @@ void Color::setFor(const GraphicsContext& context, const bool includeAlpha)
cairo_set_source_rgb(handle, red, green, blue); cairo_set_source_rgb(handle, red, green, blue);
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Line // Line


template<typename T> template<typename T>
@@ -71,11 +93,13 @@ void Line<T>::draw(const GraphicsContext& context, const T width)
cairo_stroke(handle); cairo_stroke(handle);
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Line<T>::draw() void Line<T>::draw()
{ {
notImplemented("Line::draw"); notImplemented("Line::draw");
} }
#endif


template class Line<double>; template class Line<double>;
template class Line<float>; template class Line<float>;
@@ -145,6 +169,7 @@ void Circle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
drawCircle<T>(handle, fPos, fNumSegments, fSize, fSin, fCos, true); drawCircle<T>(handle, fPos, fNumSegments, fSize, fSin, fCos, true);
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Circle<T>::draw() void Circle<T>::draw()
{ {
@@ -156,6 +181,7 @@ void Circle<T>::drawOutline()
{ {
notImplemented("Circle::drawOutline"); notImplemented("Circle::drawOutline");
} }
#endif


template class Circle<double>; template class Circle<double>;
template class Circle<float>; template class Circle<float>;
@@ -206,6 +232,7 @@ void Triangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
drawTriangle<T>(handle, pos1, pos2, pos3, true); drawTriangle<T>(handle, pos1, pos2, pos3, true);
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Triangle<T>::draw() void Triangle<T>::draw()
{ {
@@ -217,6 +244,7 @@ void Triangle<T>::drawOutline()
{ {
notImplemented("Triangle::drawOutline"); notImplemented("Triangle::drawOutline");
} }
#endif


template class Triangle<double>; template class Triangle<double>;
template class Triangle<float>; template class Triangle<float>;
@@ -261,6 +289,7 @@ void Rectangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth
drawRectangle(handle, *this, true); drawRectangle(handle, *this, true);
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Rectangle<T>::draw() void Rectangle<T>::draw()
{ {
@@ -272,6 +301,7 @@ void Rectangle<T>::drawOutline()
{ {
notImplemented("Rectangle::drawOutline"); notImplemented("Rectangle::drawOutline");
} }
#endif


template class Rectangle<double>; template class Rectangle<double>;
template class Rectangle<float>; template class Rectangle<float>;


+ 4
- 910
dgl/src/OpenGL.cpp View File

@@ -20,7 +20,6 @@
#endif #endif


#include "../OpenGL.hpp" #include "../OpenGL.hpp"
#include "../Color.hpp"
#include "../ImageWidgets.hpp" #include "../ImageWidgets.hpp"


#include "SubWidgetPrivateData.hpp" #include "SubWidgetPrivateData.hpp"
@@ -28,660 +27,11 @@
#include "WidgetPrivateData.hpp" #include "WidgetPrivateData.hpp"
#include "WindowPrivateData.hpp" #include "WindowPrivateData.hpp"


// templated classes
#include "ImageBaseWidgets.cpp"

START_NAMESPACE_DGL START_NAMESPACE_DGL


// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------

#ifdef DGL_USE_OPENGL3
# if defined(DGL_USE_GLES2) && defined(DGL_USE_GLES3)
# error Build config error, both GLESv2 and GLESv3 requested at the same time
# endif

struct OpenGL3GraphicsContext : GraphicsContext
{
mutable int prog, color, pos, tex, texok;
mutable uint w, h;
};

static void notImplemented(const char* const name)
{
#if defined(DGL_USE_GLES2)
#define DGL_OPENGL3_NAME "GLESv2"
#elif defined(DGL_USE_GLES3)
#define DGL_OPENGL3_NAME "GLESv3"
#else
#define DGL_OPENGL3_NAME "OpenGL3"
#endif
d_stderr2(DGL_OPENGL3_NAME " function not implemented: %s", name);
#undef DGL_OPENGL3_NAME
}
#else
# if defined(DGL_USE_GLES2) || defined(DGL_USE_GLES3)
# error Build config error, GLES requested while using OpenGL compat mode
# endif
# define DGL_USE_COMPAT_OPENGL
#endif

// --------------------------------------------------------------------------------------------------------------------
// Color

void Color::setFor(const GraphicsContext& context, const bool includeAlpha)
{
#ifdef DGL_USE_OPENGL3
const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);
const GLfloat color[4] = { red, green, blue, includeAlpha ? alpha : 1.f };
glUniform4fv(gl3context.color, 1, color);
#else
if (includeAlpha)
glColor4f(red, green, blue, alpha);
else
glColor3f(red, green, blue);

// unused
(void)context;
#endif
}

// --------------------------------------------------------------------------------------------------------------------
// Line

#ifdef DGL_USE_COMPAT_OPENGL
template<typename T>
static void drawLine(const Point<T>& posStart, const Point<T>& posEnd)
{
DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,);

glBegin(GL_LINES);

{
glVertex2d(posStart.getX(), posStart.getY());
glVertex2d(posEnd.getX(), posEnd.getY());
}

glEnd();
}
#endif

template<typename T>
void Line<T>::draw(const GraphicsContext& context, const T width)
{
DISTRHO_SAFE_ASSERT_RETURN(width != 0,);

glLineWidth(static_cast<GLfloat>(width));

#ifdef DGL_USE_OPENGL3
const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

const GLfloat x1 = (static_cast<double>(posStart.x) / gl3context.w) * 2 - 1;
const GLfloat y1 = (static_cast<double>(posStart.y) / gl3context.h) * -2 + 1;
const GLfloat x2 = (static_cast<double>(posEnd.x) / gl3context.w) * 2 - 1;
const GLfloat y2 = (static_cast<double>(posEnd.y) / gl3context.h) * -2 + 1;

const GLfloat vertices[] = { x1, y1, x2, y2, };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

const GLubyte order[] = { 0, 1 };
glDrawElements(GL_LINES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
#else
drawLine<T>(posStart, posEnd);

// unused
(void)context;
#endif
}

// deprecated calls
template<typename T>
void Line<T>::draw()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawLine<T>(posStart, posEnd);
#else
notImplemented("Line::draw");
#endif
}

template class Line<double>;
template class Line<float>;
template class Line<int>;
template class Line<uint>;
template class Line<short>;
template class Line<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Circle

#ifdef DGL_USE_COMPAT_OPENGL
template<typename T>
static void drawCircle(const Point<T>& pos,
const uint numSegments,
const float size,
const float sin,
const float cos,
const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,);

const double origx = static_cast<double>(pos.getX());
const double origy = static_cast<double>(pos.getY());
double t;
double x = size;
double y = 0.0;

glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);

for (uint i = 0; i < numSegments; ++i)
{
glVertex2d(x + origx, y + origy);

t = x;
x = cos * x - sin * y;
y = sin * t + cos * y;
}

glEnd();
}
#endif

template<typename T>
static void drawCircle(const GraphicsContext& context,
const Point<T>& pos,
const uint numSegments,
const float size,
const float sin,
const float cos,
const bool outline)
{
#ifdef DGL_USE_OPENGL3
#define MAX_CIRCLE_SEGMENTS 512
DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,);
DISTRHO_SAFE_ASSERT_RETURN(numSegments <= MAX_CIRCLE_SEGMENTS,);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

const double origx = static_cast<double>(pos.getX());
const double origy = static_cast<double>(pos.getY());
double t;
double x = size;
double y = 0.0;

GLfloat vertices[(MAX_CIRCLE_SEGMENTS + 1) * 2];
for (uint i = 0; i < numSegments; ++i)
{
vertices[i * 2 + 0] = ((x + origx) / gl3context.w) * 2 - 1;
vertices[i * 2 + 1] = ((y + origy) / gl3context.h) * -2 + 1;

t = x;
x = cos * x - sin * y;
y = sin * t + cos * y;
}
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

if (outline)
{
GLushort order[MAX_CIRCLE_SEGMENTS * 2];
for (uint i = 0; i < numSegments; ++i)
{
order[i * 2 + 0] = i;
order[i * 2 + 1] = i + 1;
}
order[numSegments * 2 - 1] = 0;
glDrawElements(GL_LINES, numSegments * 2, GL_UNSIGNED_SHORT, order);
}
else
{
// center position
vertices[numSegments * 2 + 0] = (origx / gl3context.w) * 2 - 1;
vertices[numSegments * 2 + 1] = (origy / gl3context.h) * -2 + 1;

GLushort order[MAX_CIRCLE_SEGMENTS * 3];
for (uint i = 0; i < numSegments; ++i)
{
order[i * 3 + 0] = i;
order[i * 3 + 1] = i + 1;
order[i * 3 + 2] = numSegments;
}
order[numSegments * 3 - 2] = 0;

glDrawElements(GL_TRIANGLES, numSegments * 3, GL_UNSIGNED_SHORT, order);
}
#else
drawCircle<T>(pos, numSegments, size, sin, cos, outline);

// unused
(void)context;
#endif
}

template<typename T>
void Circle<T>::draw(const GraphicsContext& context)
{
drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, false);
}

template<typename T>
void Circle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, true);
}

// deprecated calls
template<typename T>
void Circle<T>::draw()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, false);
#else
notImplemented("Circle::draw");
#endif
}

template<typename T>
void Circle<T>::drawOutline()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, true);
#else
notImplemented("Circle::drawOutline");
#endif
}

template class Circle<double>;
template class Circle<float>;
template class Circle<int>;
template class Circle<uint>;
template class Circle<short>;
template class Circle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Triangle

#ifdef DGL_USE_COMPAT_OPENGL
template<typename T>
static void drawTriangle(const Point<T>& pos1,
const Point<T>& pos2,
const Point<T>& pos3,
const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,);

glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);

{
glVertex2d(pos1.getX(), pos1.getY());
glVertex2d(pos2.getX(), pos2.getY());
glVertex2d(pos3.getX(), pos3.getY());
}

glEnd();
}
#endif

template<typename T>
static void drawTriangle(const GraphicsContext& context,
const Point<T>& pos1,
const Point<T>& pos2,
const Point<T>& pos3,
const bool outline)
{
#ifdef DGL_USE_OPENGL3
DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);
const GLfloat x1 = (static_cast<double>(pos1.getX()) / gl3context.w) * 2 - 1;
const GLfloat y1 = (static_cast<double>(pos1.getY()) / gl3context.h) * -2 + 1;
const GLfloat x2 = (static_cast<double>(pos2.getX()) / gl3context.w) * 2 - 1;
const GLfloat y2 = (static_cast<double>(pos2.getY()) / gl3context.h) * -2 + 1;
const GLfloat x3 = (static_cast<double>(pos3.getX()) / gl3context.w) * 2 - 1;
const GLfloat y3 = (static_cast<double>(pos3.getY()) / gl3context.h) * -2 + 1;

const GLfloat vertices[] = { x1, y1, x2, y2, x3, y3 };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

if (outline)
{
const GLubyte order[] = { 0, 1, 1, 2, 2, 0 };
glDrawElements(GL_LINES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}
else
{
glDrawArrays(GL_TRIANGLES, 0, 3);
}
#else
drawTriangle<T>(pos1, pos2, pos3, outline);

// unused
(void)context;
#endif
}

template<typename T>
void Triangle<T>::draw(const GraphicsContext& context)
{
drawTriangle<T>(context, pos1, pos2, pos3, false);
}

template<typename T>
void Triangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawTriangle<T>(context, pos1, pos2, pos3, true);
}

// deprecated calls
template<typename T>
void Triangle<T>::draw()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawTriangle<T>(pos1, pos2, pos3, false);
#else
notImplemented("Triangle::draw");
#endif
}

template<typename T>
void Triangle<T>::drawOutline()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawTriangle<T>(pos1, pos2, pos3, true);
#else
notImplemented("Triangle::drawOutline");
#endif
}

template class Triangle<double>;
template class Triangle<float>;
template class Triangle<int>;
template class Triangle<uint>;
template class Triangle<short>;
template class Triangle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Rectangle

#ifdef DGL_USE_COMPAT_OPENGL
template<typename T>
static void drawRectangle(const Rectangle<T>& rect, const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),);

glBegin(outline ? GL_LINE_LOOP : GL_QUADS);

{
const T x = rect.getX();
const T y = rect.getY();
const T w = rect.getWidth();
const T h = rect.getHeight();

glTexCoord2f(0.0f, 0.0f);
glVertex2d(x, y);

glTexCoord2f(1.0f, 0.0f);
glVertex2d(x+w, y);

glTexCoord2f(1.0f, 1.0f);
glVertex2d(x+w, y+h);

glTexCoord2f(0.0f, 1.0f);
glVertex2d(x, y+h);
}

glEnd();
}
#endif

template<typename T>
static void drawRectangle(const GraphicsContext& context, const Rectangle<T>& rect, const bool outline)
{
#ifdef DGL_USE_OPENGL3
DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);
const GLfloat x = (static_cast<double>(rect.getX()) / gl3context.w) * 2 - 1;
const GLfloat y = (static_cast<double>(rect.getY()) / gl3context.h) * -2 + 1;
const GLfloat w = (static_cast<double>(rect.getWidth()) / gl3context.w) * 2;
const GLfloat h = (static_cast<double>(rect.getHeight()) / gl3context.h) * -2;

const GLfloat vertices[] = { x, y, x, y + h, x + w, y + h, x + w, y };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

if (outline)
{
const GLubyte order[] = { 0, 1, 1, 2, 2, 3, 3, 0 };
glDrawElements(GL_LINES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}
else
{
const GLubyte order[] = { 0, 1, 2, 0, 2, 3 };
glDrawElements(GL_TRIANGLES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}
#else
drawRectangle<T>(rect, outline);

// unused
(void)context;
#endif
}

template<typename T>
void Rectangle<T>::draw(const GraphicsContext& context)
{
drawRectangle<T>(context, *this, false);
}

template<typename T>
void Rectangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawRectangle<T>(context, *this, true);
}

// deprecated calls
template<typename T>
void Rectangle<T>::draw()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawRectangle<T>(*this, false);
#else
notImplemented("Rectangle::draw");
#endif
}

template<typename T>
void Rectangle<T>::drawOutline()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawRectangle<T>(*this, true);
#else
notImplemented("Rectangle::drawOutline");
#endif
}

template class Rectangle<double>;
template class Rectangle<float>;
template class Rectangle<int>;
template class Rectangle<uint>;
template class Rectangle<short>;
template class Rectangle<ushort>;

// -----------------------------------------------------------------------
// OpenGLImage // OpenGLImage


static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId)
{
DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),);

const ImageFormat imageFormat = image.getFormat();
GLint intformat = GL_RGBA;

#ifdef DGL_USE_GLES2
// GLESv2 does not support BGR
DISTRHO_SAFE_ASSERT_RETURN(imageFormat != kImageFormatBGR && imageFormat != kImageFormatBGRA,);
#endif

#ifdef DGL_USE_OPENGL3
switch (imageFormat)
{
case kImageFormatBGR:
case kImageFormatRGB:
intformat = GL_RGB;
break;
case kImageFormatGrayscale:
#if defined(DGL_USE_GLES3)
intformat = GL_R8;
#elif defined(DGL_USE_OPENGL3)
intformat = GL_RED;
#else
intformat = GL_LUMINANCE;
#endif
break;
default:
break;
}
#else
glEnable(GL_TEXTURE_2D);
#endif

glBindTexture(GL_TEXTURE_2D, textureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D,
0,
intformat,
static_cast<GLsizei>(image.getWidth()),
static_cast<GLsizei>(image.getHeight()),
0,
asOpenGLImageFormat(imageFormat),
GL_UNSIGNED_BYTE,
image.getRawData());

glBindTexture(GL_TEXTURE_2D, 0);

#ifdef DGL_USE_COMPAT_OPENGL
glDisable(GL_TEXTURE_2D);
#endif
}

#ifdef DGL_USE_COMPAT_OPENGL
static void drawOpenGLImage(const OpenGLImage& image, const Point<int>& pos, const GLuint textureId, bool& setupCalled)
{
if (textureId == 0 || image.isInvalid())
return;

if (! setupCalled)
{
setupOpenGLImage(image, textureId);
setupCalled = true;
}

glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureId);

glBegin(GL_QUADS);

{
const int x = pos.getX();
const int y = pos.getY();
const int w = static_cast<int>(image.getWidth());
const int h = static_cast<int>(image.getHeight());

glTexCoord2f(0.0f, 0.0f);
glVertex2d(x, y);

glTexCoord2f(1.0f, 0.0f);
glVertex2d(x+w, y);

glTexCoord2f(1.0f, 1.0f);
glVertex2d(x+w, y+h);

glTexCoord2f(0.0f, 1.0f);
glVertex2d(x, y+h);
}

glEnd();

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
#endif

static void drawOpenGLImage(const GraphicsContext& context,
const OpenGLImage& image,
const Point<int>& pos,
const GLuint textureId,
bool& setupCalled)
{
#ifdef DGL_USE_OPENGL3
if (textureId == 0 || image.isInvalid())
return;

if (! setupCalled)
{
setupOpenGLImage(image, textureId);
setupCalled = true;
}

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

const GLfloat color[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
glUniform4fv(gl3context.color, 1, color);

const GLfloat x = (static_cast<double>(pos.getX()) / gl3context.w) * 2 - 1;
const GLfloat y = (static_cast<double>(pos.getY()) / gl3context.h) * -2 + 1;
const GLfloat w = (static_cast<double>(image.getWidth()) / gl3context.w) * 2;
const GLfloat h = (static_cast<double>(image.getHeight()) / gl3context.h) * -2;

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(gl3context.texok, 1);

const GLfloat vertices[] = { x, y, x, y + h, x + w, y + h, x + w, y };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

const GLfloat vtex[] = { 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, 0.f };
glVertexAttribPointer(gl3context.tex, 2, GL_FLOAT, GL_FALSE, 0, vtex);
glEnableVertexAttribArray(gl3context.tex);

const GLubyte order[] = { 0, 1, 2, 0, 2, 3 };
glDrawElements(GL_TRIANGLES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);

glUniform1i(gl3context.texok, 0);
glBindTexture(GL_TEXTURE_2D, 0);
#else
drawOpenGLImage(image, pos, textureId, setupCalled);

// unused
(void)context;
#endif
}

OpenGLImage::OpenGLImage() OpenGLImage::OpenGLImage()
: ImageBase(), : ImageBase(),
setupCalled(false), setupCalled(false),
@@ -738,11 +88,6 @@ void OpenGLImage::loadFromMemory(const char* const rdata, const Size<uint>& s, c
ImageBase::loadFromMemory(rdata, s, fmt); ImageBase::loadFromMemory(rdata, s, fmt);
} }


void OpenGLImage::drawAt(const GraphicsContext& context, const Point<int>& pos)
{
drawOpenGLImage(context, *this, pos, textureId, setupCalled);
}

OpenGLImage& OpenGLImage::operator=(const OpenGLImage& image) noexcept OpenGLImage& OpenGLImage::operator=(const OpenGLImage& image) noexcept
{ {
rawData = image.rawData; rawData = image.rawData;
@@ -760,7 +105,7 @@ OpenGLImage& OpenGLImage::operator=(const OpenGLImage& image) noexcept
return *this; return *this;
} }


// deprecated calls
#ifdef DGL_ALLOW_DEPRECATED_METHODS
OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const GLenum fmt) OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, const GLenum fmt)
: ImageBase(rdata, w, h, asDISTRHOImageFormat(fmt)), : ImageBase(rdata, w, h, asDISTRHOImageFormat(fmt)),
setupCalled(false), setupCalled(false),
@@ -780,163 +125,9 @@ OpenGLImage::OpenGLImage(const char* const rdata, const Size<uint>& s, const GLe
glGenTextures(1, &textureId); glGenTextures(1, &textureId);
DISTRHO_SAFE_ASSERT(textureId != 0); DISTRHO_SAFE_ASSERT(textureId != 0);
} }

void OpenGLImage::draw()
{
#ifdef DGL_USE_COMPAT_OPENGL
drawOpenGLImage(*this, Point<int>(0, 0), textureId, setupCalled);
#else
notImplemented("OpenGLImage::draw");
#endif
}

void OpenGLImage::drawAt(const int x, const int y)
{
#ifdef DGL_USE_COMPAT_OPENGL
drawOpenGLImage(*this, Point<int>(x, y), textureId, setupCalled);
#else
notImplemented("OpenGLImage::drawAt");
#endif
}

void OpenGLImage::drawAt(const Point<int>& pos)
{
#ifdef DGL_USE_COMPAT_OPENGL
drawOpenGLImage(*this, pos, textureId, setupCalled);
#else
notImplemented("OpenGLImage::drawAt");
#endif #endif
}

// -----------------------------------------------------------------------
// ImageBaseAboutWindow

#if 0
template <>
void ImageBaseAboutWindow<OpenGLImage>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());
img.draw(context);
}
#endif

template class ImageBaseAboutWindow<OpenGLImage>;

// -----------------------------------------------------------------------
// ImageBaseButton

template class ImageBaseButton<OpenGLImage>;

// -----------------------------------------------------------------------
// ImageBaseKnob


template <>
void ImageBaseKnob<OpenGLImage>::PrivateData::init()
{
glTextureId = 0;
glGenTextures(1, &glTextureId);
}

template <>
void ImageBaseKnob<OpenGLImage>::PrivateData::cleanup()
{
if (glTextureId == 0)
return;

glDeleteTextures(1, &glTextureId);
glTextureId = 0;
}

template <>
void ImageBaseKnob<OpenGLImage>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());
const float normValue = getNormalizedValue();

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, pData->glTextureId);

if (! pData->isReady)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

uint imageDataOffset = 0;

if (pData->rotationAngle == 0)
{
DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,);
DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);

const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight);
const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth);

// TODO kImageFormatGreyscale
const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA ||
pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3);
/* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1));
}

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset);

pData->isReady = true;
}

const int w = static_cast<int>(getWidth());
const int h = static_cast<int>(getHeight());

if (pData->rotationAngle != 0)
{
#ifdef DGL_USE_COMPAT_OPENGL
glPushMatrix();
#endif

const int w2 = w/2;
const int h2 = h/2;

#ifdef DGL_USE_COMPAT_OPENGL
glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
glRotatef(normValue*static_cast<float>(pData->rotationAngle), 0.0f, 0.0f, 1.0f);
#endif

Rectangle<int>(-w2, -h2, w, h).draw(context);

#ifdef DGL_USE_COMPAT_OPENGL
glPopMatrix();
#endif
}
else
{
Rectangle<int>(0, 0, w, h).draw(context);
}

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

template class ImageBaseKnob<OpenGLImage>;

// -----------------------------------------------------------------------
// ImageBaseSlider

template class ImageBaseSlider<OpenGLImage>;

// -----------------------------------------------------------------------
// ImageBaseSwitch

template class ImageBaseSwitch<OpenGLImage>;

// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor)
{ {
@@ -997,7 +188,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const
selfw->pData->displaySubWidgets(width, height, autoScaleFactor); selfw->pData->displaySubWidgets(width, height, autoScaleFactor);
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


void TopLevelWidget::PrivateData::display() void TopLevelWidget::PrivateData::display()
{ {
@@ -1018,7 +209,7 @@ void TopLevelWidget::PrivateData::display()
selfw->pData->displaySubWidgets(width, height, window.pData->autoScaleFactor); selfw->pData->displaySubWidgets(width, height, window.pData->autoScaleFactor);
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


void Window::PrivateData::renderToPicture(const char* const filename, void Window::PrivateData::renderToPicture(const char* const filename,
const GraphicsContext&, const GraphicsContext&,
@@ -1050,101 +241,4 @@ void Window::PrivateData::renderToPicture(const char* const filename,


// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


#ifdef DGL_USE_OPENGL3
const GraphicsContext& contextCreationFail(const OpenGL3GraphicsContext& gl3context)
{
gl3context.prog = -1;
return gl3context;
}
#endif

const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept
{
GraphicsContext& context = reinterpret_cast<GraphicsContext&>(graphicsContext);

#ifdef DGL_USE_OPENGL3
const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

// previous context creation failed
if (gl3context.prog == -1)
return context;

// create new context
if (gl3context.prog == 0)
{
int status;

const GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
DISTRHO_SAFE_ASSERT_RETURN(fragment != 0, contextCreationFail(gl3context));

const GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
DISTRHO_SAFE_ASSERT_RETURN(vertex != 0, contextCreationFail(gl3context));

const GLuint program = glCreateProgram();
DISTRHO_SAFE_ASSERT_RETURN(program != 0, contextCreationFail(gl3context));

#if defined(DGL_USE_GLES2)
#define DGL_SHADER_HEADER "#version 100\n"
#elif defined(DGL_USE_GLES3)
#define DGL_SHADER_HEADER "#version 300 es\n"
#else
#define DGL_SHADER_HEADER "#version 150 core\n"
#endif

{
static constexpr const char* const src = DGL_SHADER_HEADER
"precision mediump float;"
"uniform vec4 color;"
"uniform sampler2D stex;"
"uniform bool texok;"
"varying vec2 vtex;"
"void main() { gl_FragColor = texok ? texture2D(stex, vtex) : color; }";

glShaderSource(fragment, 1, &src, nullptr);
glCompileShader(fragment);

glGetShaderiv(fragment, GL_COMPILE_STATUS, &status);
DISTRHO_SAFE_ASSERT_RETURN(status != 0, contextCreationFail(gl3context));
}

{
static constexpr const char* const src = DGL_SHADER_HEADER
"attribute vec4 pos;"
"attribute vec2 tex;"
"varying vec2 vtex;"
"void main() { gl_Position = pos; vtex = tex; }";

glShaderSource(vertex, 1, &src, nullptr);
glCompileShader(vertex);

glGetShaderiv(vertex, GL_COMPILE_STATUS, &status);
DISTRHO_SAFE_ASSERT_RETURN(status != 0, contextCreationFail(gl3context));
}

glAttachShader(program, fragment);
glAttachShader(program, vertex);
glLinkProgram(program);

glGetProgramiv(program, GL_LINK_STATUS, &status);
DISTRHO_SAFE_ASSERT_RETURN(status != 0, contextCreationFail(gl3context));

gl3context.prog = program;
gl3context.color = glGetUniformLocation(program, "color");
gl3context.texok = glGetUniformLocation(program, "texok");
gl3context.pos = glGetAttribLocation(program, "pos");
gl3context.tex = glGetAttribLocation(program, "tex");
}

const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
gl3context.w = size.width;
gl3context.h = size.height;

glUseProgram(gl3context.prog);
#endif

return context;
}

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DGL END_NAMESPACE_DGL

+ 559
- 0
dgl/src/OpenGL2.cpp View File

@@ -0,0 +1,559 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifdef _MSC_VER
// instantiated template classes whose methods are defined elsewhere
# pragma warning(disable:4661)
#endif

#include "../OpenGL.hpp"
#include "../Color.hpp"
#include "../ImageWidgets.hpp"

// #include "SubWidgetPrivateData.hpp"
// #include "TopLevelWidgetPrivateData.hpp"
// #include "WidgetPrivateData.hpp"
#include "WindowPrivateData.hpp"

// templated classes
#include "ImageBaseWidgets.cpp"

START_NAMESPACE_DGL

// --------------------------------------------------------------------------------------------------------------------
// Check for correct build config

#ifndef DGL_OPENGL
# error Build config error, OpenGL was NOT requested while building OpenGL2 code
#endif
#ifdef DGL_CAIRO
# error Build config error, Cairo requested while building OpenGL2 code
#endif
#ifdef DGL_VULKAN
# error Build config error, Vulkan requested while building OpenGL2 code
#endif
#ifdef DGL_USE_GLES2
# error Build config error, GLESv2 requested while building OpenGL2 code
#endif
#ifdef DGL_USE_GLES3
# error Build config error, GLESv3 requested while building OpenGL2 code
#endif
#ifdef DGL_USE_OPENGL3
# error Build config error, OpenGL3 requested while building OpenGL2 code
#endif

// --------------------------------------------------------------------------------------------------------------------
// Color

void Color::setFor(const GraphicsContext&, const bool includeAlpha)
{
if (includeAlpha)
glColor4f(red, green, blue, alpha);
else
glColor3f(red, green, blue);
}

// --------------------------------------------------------------------------------------------------------------------
// Line

template<typename T>
static void drawLine(const Point<T>& posStart, const Point<T>& posEnd)
{
DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,);

glBegin(GL_LINES);

{
glVertex2d(posStart.getX(), posStart.getY());
glVertex2d(posEnd.getX(), posEnd.getY());
}

glEnd();
}

template<typename T>
void Line<T>::draw(const GraphicsContext&, const T width)
{
DISTRHO_SAFE_ASSERT_RETURN(width != 0,);

glLineWidth(static_cast<GLfloat>(width));
drawLine<T>(posStart, posEnd);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Line<T>::draw()
{
drawLine<T>(posStart, posEnd);
}
#endif

template class Line<double>;
template class Line<float>;
template class Line<int>;
template class Line<uint>;
template class Line<short>;
template class Line<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Circle

template<typename T>
static void drawCircle(const Point<T>& pos,
const uint numSegments,
const float size,
const float sin,
const float cos,
const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,);

const double origx = static_cast<double>(pos.getX());
const double origy = static_cast<double>(pos.getY());
double t;
double x = size;
double y = 0.0;

glBegin(outline ? GL_LINE_LOOP : GL_POLYGON);

for (uint i = 0; i < numSegments; ++i)
{
glVertex2d(x + origx, y + origy);

t = x;
x = cos * x - sin * y;
y = sin * t + cos * y;
}

glEnd();
}

template<typename T>
static void drawCircle(const GraphicsContext&,
const Point<T>& pos,
const uint numSegments,
const float size,
const float sin,
const float cos,
const bool outline)
{
drawCircle<T>(pos, numSegments, size, sin, cos, outline);
}

template<typename T>
void Circle<T>::draw(const GraphicsContext& context)
{
drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, false);
}

template<typename T>
void Circle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, true);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Circle<T>::draw()
{
drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, false);
}

template<typename T>
void Circle<T>::drawOutline()
{
drawCircle<T>(fPos, fNumSegments, fSize, fSin, fCos, true);
}
#endif

template class Circle<double>;
template class Circle<float>;
template class Circle<int>;
template class Circle<uint>;
template class Circle<short>;
template class Circle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Triangle

template<typename T>
static void drawTriangle(const Point<T>& pos1,
const Point<T>& pos2,
const Point<T>& pos3,
const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,);

glBegin(outline ? GL_LINE_LOOP : GL_TRIANGLES);

{
glVertex2d(pos1.getX(), pos1.getY());
glVertex2d(pos2.getX(), pos2.getY());
glVertex2d(pos3.getX(), pos3.getY());
}

glEnd();
}

template<typename T>
static void drawTriangle(const GraphicsContext&,
const Point<T>& pos1,
const Point<T>& pos2,
const Point<T>& pos3,
const bool outline)
{
drawTriangle<T>(pos1, pos2, pos3, outline);
}

template<typename T>
void Triangle<T>::draw(const GraphicsContext&)
{
drawTriangle<T>(pos1, pos2, pos3, false);
}

template<typename T>
void Triangle<T>::drawOutline(const GraphicsContext&, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawTriangle<T>(pos1, pos2, pos3, true);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Triangle<T>::draw()
{
drawTriangle<T>(pos1, pos2, pos3, false);
}

template<typename T>
void Triangle<T>::drawOutline()
{
drawTriangle<T>(pos1, pos2, pos3, true);
}
#endif

template class Triangle<double>;
template class Triangle<float>;
template class Triangle<int>;
template class Triangle<uint>;
template class Triangle<short>;
template class Triangle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Rectangle

template<typename T>
static void drawRectangle(const Rectangle<T>& rect, const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),);

glBegin(outline ? GL_LINE_LOOP : GL_QUADS);

{
const T x = rect.getX();
const T y = rect.getY();
const T w = rect.getWidth();
const T h = rect.getHeight();

glTexCoord2f(0.0f, 0.0f);
glVertex2d(x, y);

glTexCoord2f(1.0f, 0.0f);
glVertex2d(x+w, y);

glTexCoord2f(1.0f, 1.0f);
glVertex2d(x+w, y+h);

glTexCoord2f(0.0f, 1.0f);
glVertex2d(x, y+h);
}

glEnd();
}

template<typename T>
void Rectangle<T>::draw(const GraphicsContext& context)
{
drawRectangle<T>(*this, false);
}

template<typename T>
void Rectangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawRectangle<T>(*this, true);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Rectangle<T>::draw()
{
drawRectangle<T>(*this, false);
}

template<typename T>
void Rectangle<T>::drawOutline()
{
drawRectangle<T>(*this, true);
}
#endif

template class Rectangle<double>;
template class Rectangle<float>;
template class Rectangle<int>;
template class Rectangle<uint>;
template class Rectangle<short>;
template class Rectangle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// OpenGLImage

static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId)
{
DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
static_cast<GLsizei>(image.getWidth()),
static_cast<GLsizei>(image.getHeight()),
0,
asOpenGLImageFormat(image.getFormat()),
GL_UNSIGNED_BYTE,
image.getRawData());

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

static void drawOpenGLImage(const OpenGLImage& image, const Point<int>& pos, const GLuint textureId, bool& setupCalled)
{
if (textureId == 0 || image.isInvalid())
return;

if (! setupCalled)
{
setupOpenGLImage(image, textureId);
setupCalled = true;
}

glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureId);

glBegin(GL_QUADS);

{
const int x = pos.getX();
const int y = pos.getY();
const int w = static_cast<int>(image.getWidth());
const int h = static_cast<int>(image.getHeight());

glTexCoord2f(0.0f, 0.0f);
glVertex2d(x, y);

glTexCoord2f(1.0f, 0.0f);
glVertex2d(x+w, y);

glTexCoord2f(1.0f, 1.0f);
glVertex2d(x+w, y+h);

glTexCoord2f(0.0f, 1.0f);
glVertex2d(x, y+h);
}

glEnd();

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

void OpenGLImage::drawAt(const GraphicsContext&, const Point<int>& pos)
{
drawOpenGLImage(*this, pos, textureId, setupCalled);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
void OpenGLImage::draw()
{
drawOpenGLImage(*this, Point<int>(0, 0), textureId, setupCalled);
}

void OpenGLImage::drawAt(const int x, const int y)
{
drawOpenGLImage(*this, Point<int>(x, y), textureId, setupCalled);
}

void OpenGLImage::drawAt(const Point<int>& pos)
{
drawOpenGLImage(*this, pos, textureId, setupCalled);
}
#endif

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseAboutWindow

#if 0
template <>
void ImageBaseAboutWindow<OpenGLImage>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());
img.draw(context);
}
#endif

template class ImageBaseAboutWindow<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseButton

template class ImageBaseButton<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseKnob

template <>
void ImageBaseKnob<OpenGLImage>::PrivateData::init()
{
glTextureId = 0;
glGenTextures(1, &glTextureId);
}

template <>
void ImageBaseKnob<OpenGLImage>::PrivateData::cleanup()
{
if (glTextureId == 0)
return;

glDeleteTextures(1, &glTextureId);
glTextureId = 0;
}

template <>
void ImageBaseKnob<OpenGLImage>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());
const float normValue = getNormalizedValue();

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, pData->glTextureId);

if (! pData->isReady)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

uint imageDataOffset = 0;

if (pData->rotationAngle == 0)
{
DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,);
DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);

const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight);
const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth);

// TODO kImageFormatGreyscale
const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA ||
pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3);
/* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1));
}

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset);

pData->isReady = true;
}

const int w = static_cast<int>(getWidth());
const int h = static_cast<int>(getHeight());

if (pData->rotationAngle != 0)
{
glPushMatrix();

const int w2 = w/2;
const int h2 = h/2;

glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
glRotatef(normValue*static_cast<float>(pData->rotationAngle), 0.0f, 0.0f, 1.0f);

Rectangle<int>(-w2, -h2, w, h).draw(context);

glPopMatrix();
}
else
{
Rectangle<int>(0, 0, w, h).draw(context);
}

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

template class ImageBaseKnob<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseSlider

template class ImageBaseSlider<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseSwitch

template class ImageBaseSwitch<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------

const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept
{
return reinterpret_cast<GraphicsContext&>(graphicsContext);
}

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DGL

+ 710
- 0
dgl/src/OpenGL3.cpp View File

@@ -0,0 +1,710 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifdef _MSC_VER
// instantiated template classes whose methods are defined elsewhere
# pragma warning(disable:4661)
#endif

#include "../OpenGL.hpp"
#include "../Color.hpp"
#include "../ImageWidgets.hpp"

// #include "SubWidgetPrivateData.hpp"
// #include "TopLevelWidgetPrivateData.hpp"
// #include "WidgetPrivateData.hpp"
#include "WindowPrivateData.hpp"

// templated classes
#include "ImageBaseWidgets.cpp"

START_NAMESPACE_DGL

// --------------------------------------------------------------------------------------------------------------------
// Check for correct build config

#ifndef DGL_OPENGL
# error Build config error, OpenGL was NOT requested while building OpenGL3 code
#endif
#ifndef DGL_USE_OPENGL3
# error Build config error, OpenGL3 not requested while building OpenGL3 code
#endif
#ifdef DGL_CAIRO
# error Build config error, Cairo requested while building OpenGL3 code
#endif
#ifdef DGL_VULKAN
# error Build config error, Vulkan requested while building OpenGL3 code
#endif
#if defined(DGL_USE_GLES2) && defined(DGL_USE_GLES3)
# error Build config error, both GLESv2 and GLESv3 requested at the same time
#endif

// --------------------------------------------------------------------------------------------------------------------

struct OpenGL3GraphicsContext : GraphicsContext
{
mutable int prog, color, pos, tex, texok;
mutable uint w, h;
};

// --------------------------------------------------------------------------------------------------------------------

static void notImplemented(const char* const name)
{
d_stderr2("OpenGL3 function not implemented: %s", name);
}

// --------------------------------------------------------------------------------------------------------------------
// Color

void Color::setFor(const GraphicsContext& context, const bool includeAlpha)
{
const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);
const GLfloat color[4] = { red, green, blue, includeAlpha ? alpha : 1.f };
glUniform4fv(gl3context.color, 1, color);
}

// --------------------------------------------------------------------------------------------------------------------
// Line

template<typename T>
void Line<T>::draw(const GraphicsContext& context, const T width)
{
DISTRHO_SAFE_ASSERT_RETURN(width != 0,);

glLineWidth(static_cast<GLfloat>(width));

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

const GLfloat x1 = (static_cast<double>(posStart.x) / gl3context.w) * 2 - 1;
const GLfloat y1 = (static_cast<double>(posStart.y) / gl3context.h) * -2 + 1;
const GLfloat x2 = (static_cast<double>(posEnd.x) / gl3context.w) * 2 - 1;
const GLfloat y2 = (static_cast<double>(posEnd.y) / gl3context.h) * -2 + 1;

const GLfloat vertices[] = { x1, y1, x2, y2, };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

const GLubyte order[] = { 0, 1 };
glDrawElements(GL_LINES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Line<T>::draw()
{
notImplemented("Line::draw");
}
#endif

template class Line<double>;
template class Line<float>;
template class Line<int>;
template class Line<uint>;
template class Line<short>;
template class Line<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Circle

template<typename T>
static void drawCircle(const GraphicsContext& context,
const Point<T>& pos,
const uint numSegments,
const float size,
const float sin,
const float cos,
const bool outline)
{
#define MAX_CIRCLE_SEGMENTS 512
DISTRHO_SAFE_ASSERT_RETURN(numSegments >= 3 && size > 0.0f,);
DISTRHO_SAFE_ASSERT_RETURN(numSegments <= MAX_CIRCLE_SEGMENTS,);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

const double origx = static_cast<double>(pos.getX());
const double origy = static_cast<double>(pos.getY());
double t;
double x = size;
double y = 0.0;

GLfloat vertices[(MAX_CIRCLE_SEGMENTS + 1) * 2];
for (uint i = 0; i < numSegments; ++i)
{
vertices[i * 2 + 0] = ((x + origx) / gl3context.w) * 2 - 1;
vertices[i * 2 + 1] = ((y + origy) / gl3context.h) * -2 + 1;

t = x;
x = cos * x - sin * y;
y = sin * t + cos * y;
}
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

if (outline)
{
GLushort order[MAX_CIRCLE_SEGMENTS * 2];
for (uint i = 0; i < numSegments; ++i)
{
order[i * 2 + 0] = i;
order[i * 2 + 1] = i + 1;
}
order[numSegments * 2 - 1] = 0;
glDrawElements(GL_LINES, numSegments * 2, GL_UNSIGNED_SHORT, order);
}
else
{
// center position
vertices[numSegments * 2 + 0] = (origx / gl3context.w) * 2 - 1;
vertices[numSegments * 2 + 1] = (origy / gl3context.h) * -2 + 1;

GLushort order[MAX_CIRCLE_SEGMENTS * 3];
for (uint i = 0; i < numSegments; ++i)
{
order[i * 3 + 0] = i;
order[i * 3 + 1] = i + 1;
order[i * 3 + 2] = numSegments;
}
order[numSegments * 3 - 2] = 0;

glDrawElements(GL_TRIANGLES, numSegments * 3, GL_UNSIGNED_SHORT, order);
}
}

template<typename T>
void Circle<T>::draw(const GraphicsContext& context)
{
drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, false);
}

template<typename T>
void Circle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawCircle<T>(context, fPos, fNumSegments, fSize, fSin, fCos, true);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Circle<T>::draw()
{
notImplemented("Circle::draw");
}

template<typename T>
void Circle<T>::drawOutline()
{
notImplemented("Circle::drawOutline");
}
#endif

template class Circle<double>;
template class Circle<float>;
template class Circle<int>;
template class Circle<uint>;
template class Circle<short>;
template class Circle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Triangle

template<typename T>
static void drawTriangle(const GraphicsContext& context,
const Point<T>& pos1,
const Point<T>& pos2,
const Point<T>& pos3,
const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(pos1 != pos2 && pos1 != pos3,);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);
const GLfloat x1 = (static_cast<double>(pos1.getX()) / gl3context.w) * 2 - 1;
const GLfloat y1 = (static_cast<double>(pos1.getY()) / gl3context.h) * -2 + 1;
const GLfloat x2 = (static_cast<double>(pos2.getX()) / gl3context.w) * 2 - 1;
const GLfloat y2 = (static_cast<double>(pos2.getY()) / gl3context.h) * -2 + 1;
const GLfloat x3 = (static_cast<double>(pos3.getX()) / gl3context.w) * 2 - 1;
const GLfloat y3 = (static_cast<double>(pos3.getY()) / gl3context.h) * -2 + 1;

const GLfloat vertices[] = { x1, y1, x2, y2, x3, y3 };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

if (outline)
{
const GLubyte order[] = { 0, 1, 1, 2, 2, 0 };
glDrawElements(GL_LINES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}
else
{
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}

template<typename T>
void Triangle<T>::draw(const GraphicsContext& context)
{
drawTriangle<T>(context, pos1, pos2, pos3, false);
}

template<typename T>
void Triangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawTriangle<T>(context, pos1, pos2, pos3, true);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Triangle<T>::draw()
{
notImplemented("Triangle::draw");
}

template<typename T>
void Triangle<T>::drawOutline()
{
notImplemented("Triangle::drawOutline");
}
#endif

template class Triangle<double>;
template class Triangle<float>;
template class Triangle<int>;
template class Triangle<uint>;
template class Triangle<short>;
template class Triangle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// Rectangle

template<typename T>
static void drawRectangle(const GraphicsContext& context, const Rectangle<T>& rect, const bool outline)
{
DISTRHO_SAFE_ASSERT_RETURN(rect.isValid(),);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);
const GLfloat x = (static_cast<double>(rect.getX()) / gl3context.w) * 2 - 1;
const GLfloat y = (static_cast<double>(rect.getY()) / gl3context.h) * -2 + 1;
const GLfloat w = (static_cast<double>(rect.getWidth()) / gl3context.w) * 2;
const GLfloat h = (static_cast<double>(rect.getHeight()) / gl3context.h) * -2;

const GLfloat vertices[] = { x, y, x, y + h, x + w, y + h, x + w, y };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

if (outline)
{
const GLubyte order[] = { 0, 1, 1, 2, 2, 3, 3, 0 };
glDrawElements(GL_LINES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}
else
{
const GLubyte order[] = { 0, 1, 2, 0, 2, 3 };
glDrawElements(GL_TRIANGLES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);
}
}

template<typename T>
void Rectangle<T>::draw(const GraphicsContext& context)
{
drawRectangle<T>(context, *this, false);
}

template<typename T>
void Rectangle<T>::drawOutline(const GraphicsContext& context, const T lineWidth)
{
DISTRHO_SAFE_ASSERT_RETURN(lineWidth != 0,);

glLineWidth(static_cast<GLfloat>(lineWidth));
drawRectangle<T>(context, *this, true);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T>
void Rectangle<T>::draw()
{
notImplemented("Rectangle::draw");
}

template<typename T>
void Rectangle<T>::drawOutline()
{
notImplemented("Rectangle::drawOutline");
}
#endif

template class Rectangle<double>;
template class Rectangle<float>;
template class Rectangle<int>;
template class Rectangle<uint>;
template class Rectangle<short>;
template class Rectangle<ushort>;

// --------------------------------------------------------------------------------------------------------------------
// OpenGLImage

static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId)
{
DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),);

const ImageFormat imageFormat = image.getFormat();
GLint intformat = GL_RGBA;

#ifdef DGL_USE_GLES2
// GLESv2 does not support BGR
DISTRHO_SAFE_ASSERT_RETURN(imageFormat != kImageFormatBGR && imageFormat != kImageFormatBGRA,);
#endif

switch (imageFormat)
{
case kImageFormatBGR:
case kImageFormatRGB:
intformat = GL_RGB;
break;
case kImageFormatGrayscale:
#if defined(DGL_USE_GLES3)
intformat = GL_R8;
#elif defined(DGL_USE_OPENGL3)
intformat = GL_RED;
#else
intformat = GL_LUMINANCE;
#endif
break;
default:
break;
}

glBindTexture(GL_TEXTURE_2D, textureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D,
0,
intformat,
static_cast<GLsizei>(image.getWidth()),
static_cast<GLsizei>(image.getHeight()),
0,
asOpenGLImageFormat(imageFormat),
GL_UNSIGNED_BYTE,
image.getRawData());

glBindTexture(GL_TEXTURE_2D, 0);
}

// static void drawOpenGLImage(const GraphicsContext& context,
// const OpenGLImage& image,
// const Point<int>& pos,
// const GLuint textureId,
// bool& setupCalled)
// {
// }

void OpenGLImage::drawAt(const GraphicsContext& context, const Point<int>& pos)
{
// drawOpenGLImage(context, *this, pos, textureId, setupCalled);

if (textureId == 0 || isInvalid())
return;

if (! setupCalled)
{
setupOpenGLImage(*this, textureId);
setupCalled = true;
}

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

const GLfloat color[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
glUniform4fv(gl3context.color, 1, color);

const GLfloat x = (static_cast<double>(pos.getX()) / gl3context.w) * 2 - 1;
const GLfloat y = (static_cast<double>(pos.getY()) / gl3context.h) * -2 + 1;
const GLfloat w = (static_cast<double>(getWidth()) / gl3context.w) * 2;
const GLfloat h = (static_cast<double>(getHeight()) / gl3context.h) * -2;

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(gl3context.texok, 1);

const GLfloat vertices[] = { x, y, x, y + h, x + w, y + h, x + w, y };
glVertexAttribPointer(gl3context.pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(gl3context.pos);

const GLfloat vtex[] = { 0.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, 0.f };
glVertexAttribPointer(gl3context.tex, 2, GL_FLOAT, GL_FALSE, 0, vtex);
glEnableVertexAttribArray(gl3context.tex);

const GLubyte order[] = { 0, 1, 2, 0, 2, 3 };
glDrawElements(GL_TRIANGLES, ARRAY_SIZE(order), GL_UNSIGNED_BYTE, order);

glUniform1i(gl3context.texok, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}

#ifdef DGL_ALLOW_DEPRECATED_METHODS
void OpenGLImage::draw()
{
notImplemented("OpenGLImage::draw");
}

void OpenGLImage::drawAt(const int x, const int y)
{
notImplemented("OpenGLImage::drawAt");
}

void OpenGLImage::drawAt(const Point<int>& pos)
{
notImplemented("OpenGLImage::drawAt");
}
#endif

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseAboutWindow

#if 0
template <>
void ImageBaseAboutWindow<OpenGLImage>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());
img.draw(context);
}
#endif

template class ImageBaseAboutWindow<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseButton

template class ImageBaseButton<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseKnob

template <>
void ImageBaseKnob<OpenGLImage>::PrivateData::init()
{
glTextureId = 0;
glGenTextures(1, &glTextureId);
}

template <>
void ImageBaseKnob<OpenGLImage>::PrivateData::cleanup()
{
if (glTextureId == 0)
return;

glDeleteTextures(1, &glTextureId);
glTextureId = 0;
}

template <>
void ImageBaseKnob<OpenGLImage>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());
const float normValue = getNormalizedValue();

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, pData->glTextureId);

if (! pData->isReady)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);

glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

uint imageDataOffset = 0;

if (pData->rotationAngle == 0)
{
DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,);
DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);

const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight);
const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth);

// TODO kImageFormatGreyscale
const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA ||
pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3);
/* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1));
}

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset);

pData->isReady = true;
}

const int w = static_cast<int>(getWidth());
const int h = static_cast<int>(getHeight());

if (pData->rotationAngle != 0)
{
#ifdef DGL_USE_COMPAT_OPENGL
glPushMatrix();
#endif

const int w2 = w/2;
const int h2 = h/2;

#ifdef DGL_USE_COMPAT_OPENGL
glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
glRotatef(normValue*static_cast<float>(pData->rotationAngle), 0.0f, 0.0f, 1.0f);
#endif

Rectangle<int>(-w2, -h2, w, h).draw(context);

#ifdef DGL_USE_COMPAT_OPENGL
glPopMatrix();
#endif
}
else
{
Rectangle<int>(0, 0, w, h).draw(context);
}

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}

template class ImageBaseKnob<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseSlider

template class ImageBaseSlider<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------
// ImageBaseSwitch

template class ImageBaseSwitch<OpenGLImage>;

// --------------------------------------------------------------------------------------------------------------------

static const GraphicsContext& contextCreationFail(const OpenGL3GraphicsContext& gl3context)
{
gl3context.prog = -1;
return gl3context;
}

const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept
{
GraphicsContext& context = reinterpret_cast<GraphicsContext&>(graphicsContext);

const OpenGL3GraphicsContext& gl3context = static_cast<const OpenGL3GraphicsContext&>(context);

// previous context creation failed
if (gl3context.prog == -1)
return context;

// create new context
if (gl3context.prog == 0)
{
int status;

const GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
DISTRHO_SAFE_ASSERT_RETURN(fragment != 0, contextCreationFail(gl3context));

const GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
DISTRHO_SAFE_ASSERT_RETURN(vertex != 0, contextCreationFail(gl3context));

const GLuint program = glCreateProgram();
DISTRHO_SAFE_ASSERT_RETURN(program != 0, contextCreationFail(gl3context));

#if defined(DGL_USE_GLES2)
#define DGL_SHADER_HEADER "#version 100\n"
#elif defined(DGL_USE_GLES3)
#define DGL_SHADER_HEADER "#version 300 es\n"
#else
#define DGL_SHADER_HEADER "#version 150 core\n"
#endif

{
static constexpr const char* const src = DGL_SHADER_HEADER
"precision mediump float;"
"uniform vec4 color;"
"uniform sampler2D stex;"
"uniform bool texok;"
"varying vec2 vtex;"
"void main() { gl_FragColor = texok ? texture2D(stex, vtex) : color; }";

glShaderSource(fragment, 1, &src, nullptr);
glCompileShader(fragment);

glGetShaderiv(fragment, GL_COMPILE_STATUS, &status);
DISTRHO_SAFE_ASSERT_RETURN(status != 0, contextCreationFail(gl3context));
}

{
static constexpr const char* const src = DGL_SHADER_HEADER
"attribute vec4 pos;"
"attribute vec2 tex;"
"varying vec2 vtex;"
"void main() { gl_Position = pos; vtex = tex; }";

glShaderSource(vertex, 1, &src, nullptr);
glCompileShader(vertex);

glGetShaderiv(vertex, GL_COMPILE_STATUS, &status);
DISTRHO_SAFE_ASSERT_RETURN(status != 0, contextCreationFail(gl3context));
}

glAttachShader(program, fragment);
glAttachShader(program, vertex);
glLinkProgram(program);

glGetProgramiv(program, GL_LINK_STATUS, &status);
DISTRHO_SAFE_ASSERT_RETURN(status != 0, contextCreationFail(gl3context));

gl3context.prog = program;
gl3context.color = glGetUniformLocation(program, "color");
gl3context.texok = glGetUniformLocation(program, "texok");
gl3context.pos = glGetAttribLocation(program, "pos");
gl3context.tex = glGetAttribLocation(program, "tex");
}

const PuglArea size = puglGetSizeHint(view, PUGL_CURRENT_SIZE);
gl3context.w = size.width;
gl3context.h = size.height;

glUseProgram(gl3context.prog);

return context;
}

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DGL

+ 33
- 1
dgl/src/Stub.cpp View File

@@ -19,7 +19,9 @@
# pragma warning(disable:4661) # pragma warning(disable:4661)
#endif #endif


#include "Color.hpp"
#include "../Color.hpp"
#include "../ImageBaseWidgets.hpp"

#include "SubWidgetPrivateData.hpp" #include "SubWidgetPrivateData.hpp"
#include "TopLevelWidgetPrivateData.hpp" #include "TopLevelWidgetPrivateData.hpp"
#include "WidgetPrivateData.hpp" #include "WidgetPrivateData.hpp"
@@ -27,6 +29,28 @@


START_NAMESPACE_DGL START_NAMESPACE_DGL


// --------------------------------------------------------------------------------------------------------------------
// Check for correct build config

#ifdef DGL_CAIRO
# error Build config error, Cairo requested while building Stub code
#endif
#ifdef DGL_OPENGL
# error Build config error, OpenGL requested while building Stub code
#endif
#ifdef DGL_VULKAN
# error Build config error, Vulkan requested while building Stub code
#endif
#ifdef DGL_USE_GLES2
# error Build config error, GLESv2 requested while building Stub code
#endif
#ifdef DGL_USE_GLES3
# error Build config error, GLESv3 requested while building Stub code
#endif
#ifdef DGL_USE_OPENGL3
# error Build config error, OpenGL3 requested while building Stub code
#endif

// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


static void notImplemented(const char* const name) static void notImplemented(const char* const name)
@@ -51,11 +75,13 @@ void Line<T>::draw(const GraphicsContext& context, T)
notImplemented("Line::draw"); notImplemented("Line::draw");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Line<T>::draw() void Line<T>::draw()
{ {
notImplemented("Line::draw"); notImplemented("Line::draw");
} }
#endif


template class Line<double>; template class Line<double>;
template class Line<float>; template class Line<float>;
@@ -79,6 +105,7 @@ void Circle<T>::drawOutline(const GraphicsContext&, T)
notImplemented("Circle::drawOutline"); notImplemented("Circle::drawOutline");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Circle<T>::draw() void Circle<T>::draw()
{ {
@@ -90,6 +117,7 @@ void Circle<T>::drawOutline()
{ {
notImplemented("Circle::drawOutline"); notImplemented("Circle::drawOutline");
} }
#endif


template class Circle<double>; template class Circle<double>;
template class Circle<float>; template class Circle<float>;
@@ -113,6 +141,7 @@ void Triangle<T>::drawOutline(const GraphicsContext&, T)
notImplemented("Triangle::drawOutline"); notImplemented("Triangle::drawOutline");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Triangle<T>::draw() void Triangle<T>::draw()
{ {
@@ -124,6 +153,7 @@ void Triangle<T>::drawOutline()
{ {
notImplemented("Triangle::drawOutline"); notImplemented("Triangle::drawOutline");
} }
#endif


template class Triangle<double>; template class Triangle<double>;
template class Triangle<float>; template class Triangle<float>;
@@ -147,6 +177,7 @@ void Rectangle<T>::drawOutline(const GraphicsContext&, T)
notImplemented("Rectangle::drawOutline"); notImplemented("Rectangle::drawOutline");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Rectangle<T>::draw() void Rectangle<T>::draw()
{ {
@@ -158,6 +189,7 @@ void Rectangle<T>::drawOutline()
{ {
notImplemented("Rectangle::drawOutline"); notImplemented("Rectangle::drawOutline");
} }
#endif


template class Rectangle<double>; template class Rectangle<double>;
template class Rectangle<float>; template class Rectangle<float>;


+ 40
- 5
dgl/src/Vulkan.cpp View File

@@ -1,6 +1,6 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -14,8 +14,14 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */


#ifdef _MSC_VER
// instantiated template classes whose methods are defined elsewhere
# pragma warning(disable:4661)
#endif

#include "../Vulkan.hpp" #include "../Vulkan.hpp"
#include "../Color.hpp" #include "../Color.hpp"
#include "../ImageBaseWidgets.hpp"


#include "SubWidgetPrivateData.hpp" #include "SubWidgetPrivateData.hpp"
#include "TopLevelWidgetPrivateData.hpp" #include "TopLevelWidgetPrivateData.hpp"
@@ -24,14 +30,36 @@


START_NAMESPACE_DGL START_NAMESPACE_DGL


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Check for correct build config

#ifndef DGL_VULKAN
# error Build config error, Vulkan was NOT requested while building Vulkan code
#endif
#ifdef DGL_CAIRO
# error Build config error, Cairo requested while building Vulkan code
#endif
#ifdef DGL_OPENGL
# error Build config error, OpenGL requested while building Vulkan code
#endif
#ifdef DGL_USE_GLES2
# error Build config error, GLESv2 requested while building Vulkan code
#endif
#ifdef DGL_USE_GLES3
# error Build config error, GLESv3 requested while building Vulkan code
#endif
#ifdef DGL_USE_OPENGL3
# error Build config error, OpenGL3 requested while building Vulkan code
#endif

// --------------------------------------------------------------------------------------------------------------------


static void notImplemented(const char* const name) static void notImplemented(const char* const name)
{ {
d_stderr2("vulkan function not implemented: %s", name);
d_stderr2("Vulkan function not implemented: %s", name);
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Color // Color


void Color::setFor(const GraphicsContext&, bool) void Color::setFor(const GraphicsContext&, bool)
@@ -48,11 +76,13 @@ void Line<T>::draw(const GraphicsContext&, T)
notImplemented("Line::draw"); notImplemented("Line::draw");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Line<T>::draw() void Line<T>::draw()
{ {
notImplemented("Line::draw"); notImplemented("Line::draw");
} }
#endif


template class Line<double>; template class Line<double>;
template class Line<float>; template class Line<float>;
@@ -76,6 +106,7 @@ void Circle<T>::drawOutline(const GraphicsContext&, T)
notImplemented("Circle::drawOutline"); notImplemented("Circle::drawOutline");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Circle<T>::draw() void Circle<T>::draw()
{ {
@@ -87,6 +118,7 @@ void Circle<T>::drawOutline()
{ {
notImplemented("Circle::drawOutline"); notImplemented("Circle::drawOutline");
} }
#endif


template class Circle<double>; template class Circle<double>;
template class Circle<float>; template class Circle<float>;
@@ -110,6 +142,7 @@ void Triangle<T>::drawOutline(const GraphicsContext&, T)
notImplemented("Triangle::drawOutline"); notImplemented("Triangle::drawOutline");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Triangle<T>::draw() void Triangle<T>::draw()
{ {
@@ -121,6 +154,7 @@ void Triangle<T>::drawOutline()
{ {
notImplemented("Triangle::drawOutline"); notImplemented("Triangle::drawOutline");
} }
#endif


template class Triangle<double>; template class Triangle<double>;
template class Triangle<float>; template class Triangle<float>;
@@ -129,7 +163,6 @@ template class Triangle<uint>;
template class Triangle<short>; template class Triangle<short>;
template class Triangle<ushort>; template class Triangle<ushort>;



// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Rectangle // Rectangle


@@ -145,11 +178,13 @@ void Rectangle<T>::drawOutline(const GraphicsContext&, T)
notImplemented("Rectangle::drawOutline"); notImplemented("Rectangle::drawOutline");
} }


#ifdef DGL_ALLOW_DEPRECATED_METHODS
template<typename T> template<typename T>
void Rectangle<T>::draw() void Rectangle<T>::draw()
{ {
notImplemented("Rectangle::draw"); notImplemented("Rectangle::draw");
} }
#endif


template<typename T> template<typename T>
void Rectangle<T>::drawOutline() void Rectangle<T>::drawOutline()


+ 1
- 0
examples/Parameters/CMakeLists.txt View File

@@ -3,6 +3,7 @@


dpf_add_plugin(d_parameters dpf_add_plugin(d_parameters
TARGETS jack ladspa dssi lv2 vst2 vst3 clap TARGETS jack ladspa dssi lv2 vst2 vst3 clap
UI_TYPE gles2
FILES_DSP FILES_DSP
ExamplePluginParameters.cpp ExamplePluginParameters.cpp
FILES_UI FILES_UI


+ 1
- 0
examples/Parameters/Makefile View File

@@ -21,6 +21,7 @@ FILES_UI = \
# -------------------------------------------------------------- # --------------------------------------------------------------
# Do some magic # Do some magic


UI_TYPE = gles2
include ../../Makefile.plugins.mk include ../../Makefile.plugins.mk


# -------------------------------------------------------------- # --------------------------------------------------------------


Loading…
Cancel
Save