Skip to content

Commit 3106081

Browse files
committed
WIP: Improve texture loading API
1 parent f67dac9 commit 3106081

9 files changed

Lines changed: 366 additions & 130 deletions

File tree

src/api/include/projectM-4/callbacks.h

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -88,79 +88,6 @@ PROJECTM_EXPORT void projectm_set_preset_switch_failed_event_callback(projectm_h
8888
projectm_preset_switch_failed_event callback,
8989
void* user_data);
9090

91-
/**
92-
* @brief Structure containing texture data returned by the texture load callback.
93-
*
94-
* Applications can provide texture data in one of two ways:
95-
* 1. Raw pixel data: Set data to a valid pointer, width/height to the dimensions,
96-
* and channels to the number of color channels (3 for RGB, 4 for RGBA).
97-
* 2. Existing OpenGL texture: Set texture_id to a valid OpenGL texture ID.
98-
*
99-
* If both are provided, the texture_id takes precedence.
100-
* If neither is provided (data is NULL and texture_id is 0), projectM will
101-
* attempt to load the texture from the filesystem.
102-
*
103-
* @warning When providing a texture_id, projectM takes ownership of the OpenGL texture
104-
* and will delete it (via glDeleteTextures) when it is no longer needed. Do not
105-
* delete the texture yourself or reuse the texture ID after passing it here.
106-
*
107-
* @since 4.2.0
108-
*/
109-
typedef struct projectm_texture_load_data {
110-
const unsigned char* data; /**< Pointer to raw pixel data in standard OpenGL format (first row is bottom of image). Can be NULL. */
111-
unsigned int width; /**< Width of the texture in pixels. Must be > 0 when providing data or texture_id. */
112-
unsigned int height; /**< Height of the texture in pixels. Must be > 0 when providing data or texture_id. */
113-
unsigned int channels; /**< Number of color channels (3 for RGB, 4 for RGBA). */
114-
unsigned int texture_id; /**< An existing OpenGL texture ID to use. Set to 0 if not used. */
115-
} projectm_texture_load_data;
116-
117-
/**
118-
* @brief Callback function that is executed when projectM needs to load a texture.
119-
*
120-
* This callback allows applications to provide textures from sources other than
121-
* the filesystem, such as:
122-
* - Loading textures from archives (e.g., ZIP files)
123-
* - Loading textures over the network
124-
* - Generating textures procedurally
125-
* - Providing pre-loaded textures or video frames
126-
*
127-
* When called, the application should populate the provided data structure with
128-
* either raw pixel data or an OpenGL texture ID. If the application cannot provide
129-
* the requested texture, it should leave the structure unchanged (data = NULL,
130-
* texture_id = 0) and projectM will fall back to loading from the filesystem.
131-
*
132-
* @note The texture_name pointer is only valid inside the callback. Make a copy if
133-
* it needs to be retained for later use.
134-
* @note If providing raw pixel data, the data pointer must remain valid until
135-
* projectM has finished processing it (i.e., until the callback returns).
136-
* @note This callback is always invoked from the same thread that calls projectM
137-
* rendering functions. No additional synchronization is required.
138-
*
139-
* @param texture_name The name of the texture being requested, as used in the preset.
140-
* @param[out] data Pointer to a structure where the application should place texture data.
141-
* @param user_data A user-defined data pointer that was provided when registering the callback.
142-
* @since 4.2.0
143-
*/
144-
typedef void (*projectm_texture_load_event)(const char* texture_name,
145-
projectm_texture_load_data* data,
146-
void* user_data);
147-
148-
/**
149-
* @brief Sets a callback function that will be called when projectM needs to load a texture.
150-
*
151-
* This allows applications to provide textures from non-filesystem sources.
152-
* Only one callback can be registered per projectM instance. To remove the callback, use NULL.
153-
*
154-
* @param instance The projectM instance handle.
155-
* @param callback A pointer to the callback function.
156-
* @param user_data A pointer to any data that will be sent back in the callback, e.g. context
157-
* information.
158-
* @since 4.2.0
159-
*/
160-
PROJECTM_EXPORT void projectm_set_texture_load_event_callback(projectm_handle instance,
161-
projectm_texture_load_event callback,
162-
void* user_data);
163-
16491
#ifdef __cplusplus
16592
} // extern "C"
16693
#endif

src/api/include/projectM-4/projectM.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "projectM-4/memory.h"
3434
#include "projectM-4/parameters.h"
3535
#include "projectM-4/render_opengl.h"
36+
#include "projectM-4/textures.h"
3637
#include "projectM-4/touch.h"
3738
#include "projectM-4/version.h"
3839
#include "projectM-4/user_sprites.h"
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* @file textures.h
3+
* @copyright 2003-2025 projectM Team
4+
* @brief Functions, callbacks and prototypes for loading textures.
5+
* @since 4.2.0
6+
*
7+
* projectM -- Milkdrop-esque visualisation SDK
8+
* Copyright (C)2003-2024 projectM Team
9+
*
10+
* This library is free software; you can redistribute it and/or
11+
* modify it under the terms of the GNU Lesser General Public
12+
* License as published by the Free Software Foundation; either
13+
* version 2.1 of the License, or (at your option) any later version.
14+
*
15+
* This library is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
* Lesser General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU Lesser General Public
21+
* License along with this library; if not, write to the Free Software
22+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23+
* See 'LICENSE.txt' included within this release
24+
*
25+
*/
26+
27+
#pragma once
28+
29+
#include "projectM-4/types.h"
30+
31+
#ifdef __cplusplus
32+
extern "C" {
33+
#endif
34+
35+
/**
36+
* Placeholder values that can be used to address channel indices in PCM data arrays.
37+
* @since 4.2.0
38+
*/
39+
typedef enum
40+
{
41+
PROJECTM_TEXTURE_RAW = 0, //!< Load raw 3/4 channel pixel data in standard OpenGL format (first row is bottom of image).
42+
PROJECTM_TEXTURE_GL_TEX_ID = 1, //!< Specify an existing OpenGL texture ID to use.
43+
/**
44+
* Pass a compressed/plain image file and let projectM decompress/decode it.
45+
* Supported formats are: JPG, PNG, BMP, TGA, DXT and DDS, while GIF and
46+
* PSD are partially supported.
47+
*/
48+
PROJECTM_TEXTURE_COMPRESSED_FILE = 2
49+
} projectm_texture_load_type;
50+
51+
/**
52+
* @brief Structure containing texture data returned by the texture load callback.
53+
*
54+
* Applications can provide texture data in one of three ways:
55+
* 1. Raw pixel data: Set data to a valid pointer, width/height to the dimensions,
56+
* and channels to the number of color channels (3 for RGB, 4 for RGBA).
57+
* 2. Existing OpenGL texture: Set texture_id to a valid OpenGL texture ID.
58+
* 3. Data read from a supported image file type, see @a PROJECTM_TEXTURE_COMPRESSED_FILE for
59+
* details. projectM will internally use stb_image to load the textures.
60+
*
61+
* If no image or texture ID is provided for the given type(data is NULL or texture_id is 0), or
62+
* image loading fails, projectM will attempt to load the texture from the filesystem as usual.
63+
*
64+
* After
65+
*
66+
* @warning When providing a texture_id, projectM takes ownership of the OpenGL texture
67+
* and will delete it (via glDeleteTextures) when it is no longer needed. Do not
68+
* delete the texture yourself or reuse the texture ID after passing it here.
69+
*
70+
* @since 4.2.0
71+
*/
72+
typedef struct projectm_texture_load_data {
73+
projectm_texture_load_type type; //!< The format of the passed-in texture.
74+
const unsigned char* data; //!< Pointer to raw pixel or compressed image data.
75+
unsigned int width; //!< Width of the texture in pixels. Must be > 0 when providing data or texture_id. */
76+
unsigned int height; //!< Height of the texture in pixels. Must be > 0 when providing data or texture_id. */
77+
unsigned int channels; //!< Number of color channels (3 for RGB, 4 for RGBA). */
78+
unsigned int texture_id; //!< An existing OpenGL texture ID to use. Only used if type is @a PROJECTM_TEXTURE_GL_TEX_ID, ignored otherwise. */
79+
} projectm_texture_load_data;
80+
81+
PROJECTM_EXPORT bool projectm_load_texture(projectm_handle instance,
82+
const char* texture_name,
83+
const projectm_texture_load_data* texture_data);
84+
85+
/**
86+
* @brief Callback function that is executed when projectM needs to load a texture.
87+
*
88+
* This callback allows applications to provide textures from sources other than
89+
* the filesystem, such as:
90+
* - Loading textures from archives (e.g., ZIP files)
91+
* - Loading textures over the network
92+
* - Generating textures procedurally
93+
* - Providing pre-loaded textures or video frames
94+
*
95+
* When called, the application should populate the provided data structure with
96+
* either raw pixel data or an OpenGL texture ID. If the application cannot provide
97+
* the requested texture, it should leave the structure unchanged (data = NULL,
98+
* texture_id = 0) and projectM will fall back to loading from the filesystem.
99+
*
100+
* @note The texture_name pointer is only valid inside the callback. Make a copy if
101+
* it needs to be retained for later use.
102+
* @note If providing raw pixel data, the data pointer must remain valid until
103+
* projectM has finished processing it (i.e., until the callback returns).
104+
* @note This callback is always invoked from the same thread that calls projectM
105+
* rendering functions. No additional synchronization is required.
106+
*
107+
* @param texture_name The name of the texture being requested, as used in the preset.
108+
* @param[out] data Pointer to a structure where the application should place texture data.
109+
* @param user_data A user-defined data pointer that was provided when registering the callback.
110+
* @since 4.2.0
111+
*/
112+
typedef void (*projectm_texture_load_event)(const char* texture_name,
113+
projectm_texture_load_data* data,
114+
void* user_data);
115+
116+
/**
117+
* @brief Sets a callback function that will be called when projectM needs to load a texture.
118+
*
119+
* This allows applications to provide textures from non-filesystem sources.
120+
* Only one callback can be registered per projectM instance. To remove the callback, use NULL.
121+
*
122+
* @param instance The projectM instance handle.
123+
* @param callback A pointer to the callback function.
124+
* @param user_data A pointer to any data that will be sent back in the callback, e.g. context
125+
* information.
126+
* @since 4.2.0
127+
*/
128+
PROJECTM_EXPORT void projectm_set_texture_load_event_callback(projectm_handle instance,
129+
projectm_texture_load_event callback,
130+
void* user_data);
131+
132+
/**
133+
* @brief Sets a callback function that will be called after projectM unloaded a texture.
134+
*
135+
* This callback will inform the application that a texture with a given name was removed from
136+
* projectM's texture manager. This callback is only useful when passing a texture ID to projectM,
137+
* as this enabled the application to know when this specific texture is no longer needed and can
138+
* be deleted (or at least doesn't require regular updating anymore).
139+
* @param texture_name The name of the texture being requested, as used in the preset.
140+
* @param user_data A user-defined data pointer that was provided when registering the callback.
141+
* @since 4.2.0
142+
*/
143+
typedef void (*projectm_texture_unload_event)(const char* texture_name,
144+
void* user_data);
145+
146+
/**
147+
* @brief Sets a callback function that will be called when projectM needs to load a texture.
148+
*
149+
* This allows applications to provide textures from non-filesystem sources.
150+
* Only one callback can be registered per projectM instance. To remove the callback, use NULL.
151+
*
152+
* @param instance The projectM instance handle.
153+
* @param callback A pointer to the callback function.
154+
* @param user_data A pointer to any data that will be sent back in the callback, e.g. context
155+
* information.
156+
* @since 4.2.0
157+
*/
158+
PROJECTM_EXPORT void projectm_set_texture_unload_event_callback(projectm_handle instance,
159+
projectm_texture_unload_event callback,
160+
void* user_data);
161+
162+
#ifdef __cplusplus
163+
} // extern "C"
164+
#endif

src/libprojectM/Renderer/Texture.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
namespace libprojectM {
66
namespace Renderer {
77

8-
Texture::Texture(std::string name, const int width, const int height, const bool isUserTexture)
8+
Texture::Texture(std::string name, const int width, const int height, const enum Source source)
99
: m_target(GL_TEXTURE_2D)
1010
, m_name(std::move(name))
1111
, m_width(width)
1212
, m_height(height)
13-
, m_isUserTexture(isUserTexture)
13+
, m_source(source)
1414
, m_internalFormat(GL_RGB)
1515
, m_format(GL_RGB)
1616
, m_type(GL_UNSIGNED_BYTE)
@@ -19,13 +19,13 @@ Texture::Texture(std::string name, const int width, const int height, const bool
1919
}
2020

2121
Texture::Texture(std::string name, GLenum target, int width, int height, int depth,
22-
GLint internalFormat, GLenum format, GLenum type, bool isUserTexture)
22+
GLint internalFormat, GLenum format, GLenum type, const enum Source source)
2323
: m_target(target)
2424
, m_name(std::move(name))
2525
, m_width(width)
2626
, m_height(height)
2727
, m_depth(depth)
28-
, m_isUserTexture(isUserTexture)
28+
, m_source(source)
2929
, m_internalFormat(internalFormat)
3030
, m_format(format)
3131
, m_type(type)
@@ -34,24 +34,24 @@ Texture::Texture(std::string name, GLenum target, int width, int height, int dep
3434
}
3535

3636
Texture::Texture(std::string name, const GLuint texID, const GLenum target,
37-
const int width, const int height, const bool isUserTexture, const bool owned)
37+
const int width, const int height, const enum Source source)
3838
: m_textureId(texID)
3939
, m_target(target)
4040
, m_name(std::move(name))
4141
, m_width(width)
4242
, m_height(height)
43-
, m_isUserTexture(isUserTexture)
44-
, m_owned(owned)
43+
, m_source(source)
4544
{
4645
}
4746

48-
Texture::Texture(std::string name, const void* data, GLenum target, int width, int height, int depth, GLint internalFormat, GLenum format, GLenum type, bool isUserTexture)
47+
Texture::Texture(std::string name, const void* data, GLenum target, int width, int height, int depth,
48+
GLint internalFormat, GLenum format, GLenum type, const enum Source source)
4949
: m_target(target)
5050
, m_name(std::move(name))
5151
, m_width(width)
5252
, m_height(height)
5353
, m_depth(depth)
54-
, m_isUserTexture(isUserTexture)
54+
, m_source(source)
5555
, m_internalFormat(internalFormat)
5656
, m_format(format)
5757
, m_type(type)
@@ -62,7 +62,7 @@ Texture::Texture(std::string name, const void* data, GLenum target, int width, i
6262

6363
Texture::~Texture()
6464
{
65-
if (m_textureId > 0 && m_owned)
65+
if (m_textureId > 0 && m_source != Source::ExternalTexture)
6666
{
6767
glDeleteTextures(1, &m_textureId);
6868
m_textureId = 0;
@@ -116,9 +116,9 @@ auto Texture::Depth() const -> int
116116
return m_depth;
117117
}
118118

119-
auto Texture::IsUserTexture() const -> bool
119+
auto Texture::Source() const -> enum Source
120120
{
121-
return m_isUserTexture;
121+
return m_source;
122122
}
123123

124124
auto Texture::Empty() const -> bool

0 commit comments

Comments
 (0)