sokol: update to floooh/sokol from 27-Dec-2021 (4ff3ed7) (#13044)
parent
70a0aab72b
commit
3ae4513e2e
|
@ -252,6 +252,10 @@
|
||||||
may help to prevent casting back and forth between int and float
|
may help to prevent casting back and forth between int and float
|
||||||
in more strongly typed languages than C and C++.
|
in more strongly typed languages than C and C++.
|
||||||
|
|
||||||
|
double sapp_frame_duration(void)
|
||||||
|
Returns the frame duration in seconds averaged over a number of
|
||||||
|
frames to smooth out any jittering spikes.
|
||||||
|
|
||||||
int sapp_color_format(void)
|
int sapp_color_format(void)
|
||||||
int sapp_depth_format(void)
|
int sapp_depth_format(void)
|
||||||
The color and depth-stencil pixelformats of the default framebuffer,
|
The color and depth-stencil pixelformats of the default framebuffer,
|
||||||
|
@ -411,7 +415,7 @@
|
||||||
- SAPP_EVENTTYPE_MOUSE_DOWN
|
- SAPP_EVENTTYPE_MOUSE_DOWN
|
||||||
- SAPP_EVENTTYPE_MOUSE_UP
|
- SAPP_EVENTTYPE_MOUSE_UP
|
||||||
- SAPP_EVENTTYPE_MOUSE_SCROLL
|
- SAPP_EVENTTYPE_MOUSE_SCROLL
|
||||||
- SAPP_EVENTYTPE_KEY_UP
|
- SAPP_EVENTTYPE_KEY_UP
|
||||||
- SAPP_EVENTTYPE_KEY_DOWN
|
- SAPP_EVENTTYPE_KEY_DOWN
|
||||||
- The mouse lock/unlock action on the web platform is asynchronous,
|
- The mouse lock/unlock action on the web platform is asynchronous,
|
||||||
this means that sapp_mouse_locked() won't immediately return
|
this means that sapp_mouse_locked() won't immediately return
|
||||||
|
@ -1378,7 +1382,7 @@ typedef struct sapp_desc {
|
||||||
bool html5_ask_leave_site; // initial state of the internal html5_ask_leave_site flag (see sapp_html5_ask_leave_site())
|
bool html5_ask_leave_site; // initial state of the internal html5_ask_leave_site flag (see sapp_html5_ask_leave_site())
|
||||||
bool ios_keyboard_resizes_canvas; // if true, showing the iOS keyboard shrinks the canvas
|
bool ios_keyboard_resizes_canvas; // if true, showing the iOS keyboard shrinks the canvas
|
||||||
// __v_ start
|
// __v_ start
|
||||||
bool __v_native_render; /* V patch to allow for native rendering */
|
bool __v_native_render; // V patch to allow for native rendering
|
||||||
// __v_ end
|
// __v_ end
|
||||||
} sapp_desc;
|
} sapp_desc;
|
||||||
|
|
||||||
|
@ -1443,7 +1447,7 @@ SOKOL_APP_API_DECL void sapp_toggle_fullscreen(void);
|
||||||
/* show or hide the mouse cursor */
|
/* show or hide the mouse cursor */
|
||||||
SOKOL_APP_API_DECL void sapp_show_mouse(bool show);
|
SOKOL_APP_API_DECL void sapp_show_mouse(bool show);
|
||||||
/* show or hide the mouse cursor */
|
/* show or hide the mouse cursor */
|
||||||
SOKOL_APP_API_DECL bool sapp_mouse_shown();
|
SOKOL_APP_API_DECL bool sapp_mouse_shown(void);
|
||||||
/* enable/disable mouse-pointer-lock mode */
|
/* enable/disable mouse-pointer-lock mode */
|
||||||
SOKOL_APP_API_DECL void sapp_lock_mouse(bool lock);
|
SOKOL_APP_API_DECL void sapp_lock_mouse(bool lock);
|
||||||
/* return true if in mouse-pointer-lock mode (this may toggle a few frames later) */
|
/* return true if in mouse-pointer-lock mode (this may toggle a few frames later) */
|
||||||
|
@ -1462,6 +1466,8 @@ SOKOL_APP_API_DECL void sapp_quit(void);
|
||||||
SOKOL_APP_API_DECL void sapp_consume_event(void);
|
SOKOL_APP_API_DECL void sapp_consume_event(void);
|
||||||
/* get the current frame counter (for comparison with sapp_event.frame_count) */
|
/* get the current frame counter (for comparison with sapp_event.frame_count) */
|
||||||
SOKOL_APP_API_DECL uint64_t sapp_frame_count(void);
|
SOKOL_APP_API_DECL uint64_t sapp_frame_count(void);
|
||||||
|
/* get an averaged/smoothed frame duration in seconds */
|
||||||
|
SOKOL_APP_API_DECL double sapp_frame_duration(void);
|
||||||
/* write string into clipboard */
|
/* write string into clipboard */
|
||||||
SOKOL_APP_API_DECL void sapp_set_clipboard_string(const char* str);
|
SOKOL_APP_API_DECL void sapp_set_clipboard_string(const char* str);
|
||||||
/* read string from clipboard (usually during SAPP_EVENTTYPE_CLIPBOARD_PASTED) */
|
/* read string from clipboard (usually during SAPP_EVENTTYPE_CLIPBOARD_PASTED) */
|
||||||
|
@ -1685,6 +1691,8 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); }
|
||||||
#import <GLKit/GLKit.h>
|
#import <GLKit/GLKit.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
#include <mach/mach_time.h>
|
||||||
#elif defined(_SAPP_EMSCRIPTEN)
|
#elif defined(_SAPP_EMSCRIPTEN)
|
||||||
#if defined(SOKOL_WGPU)
|
#if defined(SOKOL_WGPU)
|
||||||
#include <webgpu/webgpu.h>
|
#include <webgpu/webgpu.h>
|
||||||
|
@ -1774,6 +1782,7 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); }
|
||||||
#elif defined(_SAPP_ANDROID)
|
#elif defined(_SAPP_ANDROID)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
#include <android/native_activity.h>
|
#include <android/native_activity.h>
|
||||||
#include <android/looper.h>
|
#include <android/looper.h>
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
@ -1791,8 +1800,209 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); }
|
||||||
#include <dlfcn.h> /* dlopen, dlsym, dlclose */
|
#include <dlfcn.h> /* dlopen, dlsym, dlclose */
|
||||||
#include <limits.h> /* LONG_MAX */
|
#include <limits.h> /* LONG_MAX */
|
||||||
#include <pthread.h> /* only used a linker-guard, search for _sapp_linux_run() and see first comment */
|
#include <pthread.h> /* only used a linker-guard, search for _sapp_linux_run() and see first comment */
|
||||||
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*== frame timing helpers ===================================================*/
|
||||||
|
#define _SAPP_RING_NUM_SLOTS (256)
|
||||||
|
typedef struct {
|
||||||
|
int head;
|
||||||
|
int tail;
|
||||||
|
double buf[_SAPP_RING_NUM_SLOTS];
|
||||||
|
} _sapp_ring_t;
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE int _sapp_ring_idx(int i) {
|
||||||
|
return i % _SAPP_RING_NUM_SLOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_ring_init(_sapp_ring_t* ring) {
|
||||||
|
ring->head = 0;
|
||||||
|
ring->tail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE bool _sapp_ring_full(_sapp_ring_t* ring) {
|
||||||
|
return _sapp_ring_idx(ring->head + 1) == ring->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE bool _sapp_ring_empty(_sapp_ring_t* ring) {
|
||||||
|
return ring->head == ring->tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE int _sapp_ring_count(_sapp_ring_t* ring) {
|
||||||
|
int count;
|
||||||
|
if (ring->head >= ring->tail) {
|
||||||
|
count = ring->head - ring->tail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
count = (ring->head + _SAPP_RING_NUM_SLOTS) - ring->tail;
|
||||||
|
}
|
||||||
|
SOKOL_ASSERT((count >= 0) && (count < _SAPP_RING_NUM_SLOTS));
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_ring_enqueue(_sapp_ring_t* ring, double val) {
|
||||||
|
SOKOL_ASSERT(!_sapp_ring_full(ring));
|
||||||
|
ring->buf[ring->head] = val;
|
||||||
|
ring->head = _sapp_ring_idx(ring->head + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE double _sapp_ring_dequeue(_sapp_ring_t* ring) {
|
||||||
|
SOKOL_ASSERT(!_sapp_ring_empty(ring));
|
||||||
|
double val = ring->buf[ring->tail];
|
||||||
|
ring->tail = _sapp_ring_idx(ring->tail + 1);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE:
|
||||||
|
|
||||||
|
Q: Why not use CAMetalDrawable.presentedTime on macOS and iOS?
|
||||||
|
A: The value appears to be highly unstable during the first few
|
||||||
|
seconds, sometimes several frames are dropped in sequence, or
|
||||||
|
switch between 120 and 60 Hz for a few frames. Simply measuring
|
||||||
|
and averaging the frame time yielded a more stable frame duration.
|
||||||
|
Maybe switching to CVDisplayLink would yield better results.
|
||||||
|
Until then just measure the time.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
#if defined(_SAPP_APPLE)
|
||||||
|
struct {
|
||||||
|
mach_timebase_info_data_t timebase;
|
||||||
|
uint64_t start;
|
||||||
|
} mach;
|
||||||
|
#elif defined(_SAPP_EMSCRIPTEN)
|
||||||
|
// empty
|
||||||
|
#elif defined(_SAPP_WIN32) || defined(_SAPP_UWP)
|
||||||
|
struct {
|
||||||
|
LARGE_INTEGER freq;
|
||||||
|
LARGE_INTEGER start;
|
||||||
|
} win;
|
||||||
|
#else // Linux, Android, ...
|
||||||
|
#ifdef CLOCK_MONOTONIC
|
||||||
|
#define _SAPP_CLOCK_MONOTONIC CLOCK_MONOTONIC
|
||||||
|
#else
|
||||||
|
// on some embedded platforms, CLOCK_MONOTONIC isn't defined
|
||||||
|
#define _SAPP_CLOCK_MONOTONIC (1)
|
||||||
|
#endif
|
||||||
|
struct {
|
||||||
|
uint64_t start;
|
||||||
|
} posix;
|
||||||
|
#endif
|
||||||
|
} _sapp_timestamp_t;
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE int64_t _sapp_int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
|
||||||
|
int64_t q = value / denom;
|
||||||
|
int64_t r = value % denom;
|
||||||
|
return q * numer + r * numer / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_timestamp_init(_sapp_timestamp_t* ts) {
|
||||||
|
#if defined(_SAPP_APPLE)
|
||||||
|
mach_timebase_info(&ts->mach.timebase);
|
||||||
|
ts->mach.start = mach_absolute_time();
|
||||||
|
#elif defined(_SAPP_EMSCRIPTEN)
|
||||||
|
(void)ts;
|
||||||
|
#elif defined(_SAPP_WIN32) || defined(_SAPP_UWP)
|
||||||
|
QueryPerformanceFrequency(&ts->win.freq);
|
||||||
|
QueryPerformanceCounter(&ts->win.start);
|
||||||
|
#else
|
||||||
|
struct timespec tspec;
|
||||||
|
clock_gettime(_SAPP_CLOCK_MONOTONIC, &tspec);
|
||||||
|
ts->posix.start = (uint64_t)tspec.tv_sec*1000000000 + (uint64_t)tspec.tv_nsec;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE double _sapp_timestamp_now(_sapp_timestamp_t* ts) {
|
||||||
|
#if defined(_SAPP_APPLE)
|
||||||
|
const uint64_t traw = mach_absolute_time() - ts->mach.start;
|
||||||
|
const uint64_t now = (uint64_t) _sapp_int64_muldiv((int64_t)traw, (int64_t)ts->mach.timebase.numer, (int64_t)ts->mach.timebase.denom);
|
||||||
|
return (double)now / 1000000000.0;
|
||||||
|
#elif defined(_SAPP_EMSCRIPTEN)
|
||||||
|
(void)ts;
|
||||||
|
SOKOL_ASSERT(false);
|
||||||
|
return 0.0;
|
||||||
|
#elif defined(_SAPP_WIN32) || defined(_SAPP_UWP)
|
||||||
|
LARGE_INTEGER qpc;
|
||||||
|
QueryPerformanceCounter(&qpc);
|
||||||
|
const uint64_t now = (uint64_t)_sapp_int64_muldiv(qpc.QuadPart - ts->win.start.QuadPart, 1000000000, ts->win.freq.QuadPart);
|
||||||
|
return (double)now / 1000000000.0;
|
||||||
|
#else
|
||||||
|
struct timespec tspec;
|
||||||
|
clock_gettime(_SAPP_CLOCK_MONOTONIC, &tspec);
|
||||||
|
const uint64_t now = ((uint64_t)tspec.tv_sec*1000000000 + (uint64_t)tspec.tv_nsec) - ts->posix.start;
|
||||||
|
return (double)now / 1000000000.0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double last;
|
||||||
|
double accum;
|
||||||
|
double avg;
|
||||||
|
int num;
|
||||||
|
_sapp_timestamp_t timestamp;
|
||||||
|
_sapp_ring_t ring;
|
||||||
|
} _sapp_timing_t;
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_timing_init(_sapp_timing_t* t) {
|
||||||
|
t->last = 0.0;
|
||||||
|
t->accum = 0.0;
|
||||||
|
// dummy value until first actual value is available
|
||||||
|
t->avg = 1.0 / 60.0;
|
||||||
|
t->num = 0;
|
||||||
|
_sapp_timestamp_init(&t->timestamp);
|
||||||
|
_sapp_ring_init(&t->ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_timing_put(_sapp_timing_t* t, double dur) {
|
||||||
|
// arbitrary upper limit to ignore outliers (e.g. during window resizing, or debugging)
|
||||||
|
double min_dur = 0.0;
|
||||||
|
double max_dur = 0.1;
|
||||||
|
// if we have enough samples for a useful average, use a much tighter 'valid window'
|
||||||
|
if (_sapp_ring_full(&t->ring)) {
|
||||||
|
min_dur = t->avg * 0.8;
|
||||||
|
max_dur = t->avg * 1.2;
|
||||||
|
}
|
||||||
|
if ((dur < min_dur) || (dur > max_dur)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_sapp_ring_full(&t->ring)) {
|
||||||
|
double old_val = _sapp_ring_dequeue(&t->ring);
|
||||||
|
t->accum -= old_val;
|
||||||
|
t->num -= 1;
|
||||||
|
}
|
||||||
|
_sapp_ring_enqueue(&t->ring, dur);
|
||||||
|
t->accum += dur;
|
||||||
|
t->num += 1;
|
||||||
|
SOKOL_ASSERT(t->num > 0);
|
||||||
|
t->avg = t->accum / t->num;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_timing_measure(_sapp_timing_t* t) {
|
||||||
|
const double now = _sapp_timestamp_now(&t->timestamp);
|
||||||
|
if (t->last > 0.0) {
|
||||||
|
double dur = now - t->last;
|
||||||
|
_sapp_timing_put(t, dur);
|
||||||
|
}
|
||||||
|
t->last = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call this if the external timing had been disrupted somehow
|
||||||
|
_SOKOL_PRIVATE void _sapp_timing_external_reset(_sapp_timing_t* t) {
|
||||||
|
t->last = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_timing_external(_sapp_timing_t* t, double now) {
|
||||||
|
if (t->last > 0.0) {
|
||||||
|
double dur = now - t->last;
|
||||||
|
_sapp_timing_put(t, dur);
|
||||||
|
}
|
||||||
|
t->last = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE double _sapp_timing_get_avg(_sapp_timing_t* t) {
|
||||||
|
return t->avg;
|
||||||
|
}
|
||||||
|
|
||||||
/*== MACOS DECLARATIONS ======================================================*/
|
/*== MACOS DECLARATIONS ======================================================*/
|
||||||
#if defined(_SAPP_MACOS)
|
#if defined(_SAPP_MACOS)
|
||||||
// __v_ start
|
// __v_ start
|
||||||
|
@ -1830,9 +2040,8 @@ typedef struct {
|
||||||
uint32_t flags_changed_store;
|
uint32_t flags_changed_store;
|
||||||
uint8_t mouse_buttons;
|
uint8_t mouse_buttons;
|
||||||
// __v_ start
|
// __v_ start
|
||||||
// NSWindow* window;
|
//NSWindow* window; // __v_ removed
|
||||||
// SokolWindow* window; // __v_
|
_sapp_macos_window* window; // __v_ added
|
||||||
_sapp_macos_window* window; // __v_
|
|
||||||
// __v_ end
|
// __v_ end
|
||||||
NSTrackingArea* tracking_area;
|
NSTrackingArea* tracking_area;
|
||||||
_sapp_macos_app_delegate* app_dlg;
|
_sapp_macos_app_delegate* app_dlg;
|
||||||
|
@ -1922,6 +2131,7 @@ typedef struct {
|
||||||
ID3D11DepthStencilView* dsv;
|
ID3D11DepthStencilView* dsv;
|
||||||
DXGI_SWAP_CHAIN_DESC swap_chain_desc;
|
DXGI_SWAP_CHAIN_DESC swap_chain_desc;
|
||||||
IDXGISwapChain* swap_chain;
|
IDXGISwapChain* swap_chain;
|
||||||
|
UINT sync_refresh_count;
|
||||||
} _sapp_d3d11_t;
|
} _sapp_d3d11_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2103,7 +2313,7 @@ typedef struct {
|
||||||
#define GLX_RGBA_BIT 0x00000001
|
#define GLX_RGBA_BIT 0x00000001
|
||||||
#define GLX_WINDOW_BIT 0x00000001
|
#define GLX_WINDOW_BIT 0x00000001
|
||||||
#define GLX_DRAWABLE_TYPE 0x8010
|
#define GLX_DRAWABLE_TYPE 0x8010
|
||||||
#define GLX_RENDER_TYPE 0x8011
|
#define GLX_RENDER_TYPE 0x8011
|
||||||
#define GLX_DOUBLEBUFFER 5
|
#define GLX_DOUBLEBUFFER 5
|
||||||
#define GLX_RED_SIZE 8
|
#define GLX_RED_SIZE 8
|
||||||
#define GLX_GREEN_SIZE 9
|
#define GLX_GREEN_SIZE 9
|
||||||
|
@ -2300,6 +2510,7 @@ typedef struct {
|
||||||
int swap_interval;
|
int swap_interval;
|
||||||
float dpi_scale;
|
float dpi_scale;
|
||||||
uint64_t frame_count;
|
uint64_t frame_count;
|
||||||
|
_sapp_timing_t timing;
|
||||||
sapp_event event;
|
sapp_event event;
|
||||||
_sapp_mouse_t mouse;
|
_sapp_mouse_t mouse;
|
||||||
_sapp_clipboard_t clipboard;
|
_sapp_clipboard_t clipboard;
|
||||||
|
@ -2334,7 +2545,6 @@ typedef struct {
|
||||||
char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */
|
char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */
|
||||||
wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */
|
wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */
|
||||||
sapp_keycode keycodes[SAPP_MAX_KEYCODES];
|
sapp_keycode keycodes[SAPP_MAX_KEYCODES];
|
||||||
|
|
||||||
// __v_ start
|
// __v_ start
|
||||||
bool __v_native_render; /* V patch to allow for native rendering */
|
bool __v_native_render; /* V patch to allow for native rendering */
|
||||||
// __v_ end
|
// __v_ end
|
||||||
|
@ -2383,8 +2593,8 @@ _SOKOL_PRIVATE void _sapp_call_frame(void) {
|
||||||
|
|
||||||
// __v_ start
|
// __v_ start
|
||||||
_SOKOL_PRIVATE void _sapp_call_frame_native(void) {
|
_SOKOL_PRIVATE void _sapp_call_frame_native(void) {
|
||||||
//puts("_sapp_call_frame_native()");
|
//puts("_sapp_call_frame_native()");
|
||||||
//printf("init called=%d cleanup_called=%d\n", _sapp.init_called,_sapp.cleanup_called);
|
//printf("init called=%d cleanup_called=%d\n", _sapp.init_called,_sapp.cleanup_called);
|
||||||
if (_sapp.init_called && !_sapp.cleanup_called) {
|
if (_sapp.init_called && !_sapp.cleanup_called) {
|
||||||
if (_sapp.desc.frame_cb) {
|
if (_sapp.desc.frame_cb) {
|
||||||
_sapp.desc.frame_cb();
|
_sapp.desc.frame_cb();
|
||||||
|
@ -2409,7 +2619,6 @@ _SOKOL_PRIVATE void _sapp_call_cleanup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE bool _sapp_call_event(const sapp_event* e) {
|
_SOKOL_PRIVATE bool _sapp_call_event(const sapp_event* e) {
|
||||||
//puts("_sapp_call_event start");
|
|
||||||
if (!_sapp.cleanup_called) {
|
if (!_sapp.cleanup_called) {
|
||||||
if (_sapp.desc.event_cb) {
|
if (_sapp.desc.event_cb) {
|
||||||
_sapp.desc.event_cb(e);
|
_sapp.desc.event_cb(e);
|
||||||
|
@ -2418,7 +2627,6 @@ _SOKOL_PRIVATE bool _sapp_call_event(const sapp_event* e) {
|
||||||
_sapp.desc.event_userdata_cb(e, _sapp.desc.user_data);
|
_sapp.desc.event_userdata_cb(e, _sapp.desc.user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//puts("_sapp_call_event end");
|
|
||||||
if (_sapp.event_consumed) {
|
if (_sapp.event_consumed) {
|
||||||
_sapp.event_consumed = false;
|
_sapp.event_consumed = false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -2481,6 +2689,14 @@ _SOKOL_PRIVATE sapp_desc _sapp_desc_defaults(const sapp_desc* in_desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE void _sapp_init_state(const sapp_desc* desc) {
|
_SOKOL_PRIVATE void _sapp_init_state(const sapp_desc* desc) {
|
||||||
|
SOKOL_ASSERT(desc);
|
||||||
|
SOKOL_ASSERT(desc->width >= 0);
|
||||||
|
SOKOL_ASSERT(desc->height >= 0);
|
||||||
|
SOKOL_ASSERT(desc->sample_count >= 0);
|
||||||
|
SOKOL_ASSERT(desc->swap_interval >= 0);
|
||||||
|
SOKOL_ASSERT(desc->clipboard_size >= 0);
|
||||||
|
SOKOL_ASSERT(desc->max_dropped_files >= 0);
|
||||||
|
SOKOL_ASSERT(desc->max_dropped_file_path_length >= 0);
|
||||||
_SAPP_CLEAR(_sapp_t, _sapp);
|
_SAPP_CLEAR(_sapp_t, _sapp);
|
||||||
_sapp.desc = _sapp_desc_defaults(desc);
|
_sapp.desc = _sapp_desc_defaults(desc);
|
||||||
_sapp.first_frame = true;
|
_sapp.first_frame = true;
|
||||||
|
@ -2511,6 +2727,7 @@ _SOKOL_PRIVATE void _sapp_init_state(const sapp_desc* desc) {
|
||||||
_sapp.dpi_scale = 1.0f;
|
_sapp.dpi_scale = 1.0f;
|
||||||
_sapp.fullscreen = _sapp.desc.fullscreen;
|
_sapp.fullscreen = _sapp.desc.fullscreen;
|
||||||
_sapp.mouse.shown = true;
|
_sapp.mouse.shown = true;
|
||||||
|
_sapp_timing_init(&_sapp.timing);
|
||||||
// __v_ start
|
// __v_ start
|
||||||
_sapp.__v_native_render = _sapp.desc.__v_native_render;
|
_sapp.__v_native_render = _sapp.desc.__v_native_render;
|
||||||
// __v_end
|
// __v_end
|
||||||
|
@ -3034,14 +3251,6 @@ _SOKOL_PRIVATE void _sapp_macos_update_window_title(void) {
|
||||||
[_sapp.macos.window setTitle: [NSString stringWithUTF8String:_sapp.window_title]];
|
[_sapp.macos.window setTitle: [NSString stringWithUTF8String:_sapp.window_title]];
|
||||||
}
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE void _sapp_macos_resize_window(int width, height) {
|
|
||||||
[_sapp.macos.window setFrame:NSMakeRect(width, height, width, height) display:YES animate:YES];
|
|
||||||
//NSRect frame = [window frame];
|
|
||||||
//frame.size = ;
|
|
||||||
//[window setFrame: frame display: YES animate: NO];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_SOKOL_PRIVATE void _sapp_macos_update_mouse(NSEvent* event) {
|
_SOKOL_PRIVATE void _sapp_macos_update_mouse(NSEvent* event) {
|
||||||
if (!_sapp.mouse.locked) {
|
if (!_sapp.mouse.locked) {
|
||||||
const NSPoint mouse_pos = event.locationInWindow;
|
const NSPoint mouse_pos = event.locationInWindow;
|
||||||
|
@ -3175,39 +3384,19 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) {
|
||||||
_sapp.macos.window.acceptsMouseMovedEvents = YES;
|
_sapp.macos.window.acceptsMouseMovedEvents = YES;
|
||||||
_sapp.macos.window.restorable = YES;
|
_sapp.macos.window.restorable = YES;
|
||||||
|
|
||||||
// _v__ start
|
|
||||||
_sapp.macos.window.backgroundColor = [NSColor whiteColor];
|
|
||||||
|
|
||||||
// Quit menu
|
|
||||||
NSMenu* menu_bar = [[NSMenu alloc] init];
|
|
||||||
NSMenuItem* app_menu_item = [[NSMenuItem alloc] init];
|
|
||||||
[menu_bar addItem:app_menu_item];
|
|
||||||
NSApp.mainMenu = menu_bar;
|
|
||||||
NSMenu* app_menu = [[NSMenu alloc] init];
|
|
||||||
NSString* window_title_as_nsstring = [NSString stringWithUTF8String:_sapp.window_title];
|
|
||||||
// `quit_title` memory will be owned by the NSMenuItem, so no need to release it ourselves
|
|
||||||
NSString* quit_title = [@"Quit " stringByAppendingString:window_title_as_nsstring];
|
|
||||||
NSMenuItem* quit_menu_item = [[NSMenuItem alloc]
|
|
||||||
initWithTitle:quit_title
|
|
||||||
action:@selector(terminate:)
|
|
||||||
keyEquivalent:@"q"];
|
|
||||||
[app_menu addItem:quit_menu_item];
|
|
||||||
app_menu_item.submenu = app_menu;
|
|
||||||
_SAPP_OBJC_RELEASE( window_title_as_nsstring );
|
|
||||||
_SAPP_OBJC_RELEASE( app_menu );
|
|
||||||
_SAPP_OBJC_RELEASE( app_menu_item );
|
|
||||||
_SAPP_OBJC_RELEASE( menu_bar );
|
|
||||||
|
|
||||||
|
|
||||||
// _v__ end
|
|
||||||
|
|
||||||
_sapp.macos.win_dlg = [[_sapp_macos_window_delegate alloc] init];
|
_sapp.macos.win_dlg = [[_sapp_macos_window_delegate alloc] init];
|
||||||
_sapp.macos.window.delegate = _sapp.macos.win_dlg;
|
_sapp.macos.window.delegate = _sapp.macos.win_dlg;
|
||||||
#if defined(SOKOL_METAL)
|
#if defined(SOKOL_METAL)
|
||||||
|
NSInteger max_fps = 60;
|
||||||
|
#if (__MAC_OS_X_VERSION_MAX_ALLOWED >= 120000)
|
||||||
|
if (@available(macOS 12.0, *)) {
|
||||||
|
max_fps = NSScreen.mainScreen.maximumFramesPerSecond;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
_sapp.macos.mtl_device = MTLCreateSystemDefaultDevice();
|
_sapp.macos.mtl_device = MTLCreateSystemDefaultDevice();
|
||||||
_sapp.macos.view = [[_sapp_macos_view alloc] init];
|
_sapp.macos.view = [[_sapp_macos_view alloc] init];
|
||||||
[_sapp.macos.view updateTrackingAreas];
|
[_sapp.macos.view updateTrackingAreas];
|
||||||
_sapp.macos.view.preferredFramesPerSecond = 60 / _sapp.swap_interval;
|
_sapp.macos.view.preferredFramesPerSecond = max_fps / _sapp.swap_interval;
|
||||||
_sapp.macos.view.device = _sapp.macos.mtl_device;
|
_sapp.macos.view.device = _sapp.macos.mtl_device;
|
||||||
_sapp.macos.view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
|
_sapp.macos.view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
_sapp.macos.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
_sapp.macos.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||||
|
@ -3262,8 +3451,8 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) {
|
||||||
timer_obj = nil;
|
timer_obj = nil;
|
||||||
#endif
|
#endif
|
||||||
_sapp.valid = true;
|
_sapp.valid = true;
|
||||||
// __v_ start
|
// __v_ start
|
||||||
if (!_sapp.__v_native_render) { // __v_
|
if (!_sapp.__v_native_render) { // __v_
|
||||||
if (_sapp.fullscreen) {
|
if (_sapp.fullscreen) {
|
||||||
/* on GL, this already toggles a rendered frame, so set the valid flag before */
|
/* on GL, this already toggles a rendered frame, so set the valid flag before */
|
||||||
[_sapp.macos.window toggleFullScreen:self];
|
[_sapp.macos.window toggleFullScreen:self];
|
||||||
|
@ -3271,43 +3460,40 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) {
|
||||||
else {
|
else {
|
||||||
[_sapp.macos.window center];
|
[_sapp.macos.window center];
|
||||||
}
|
}
|
||||||
} // __v_
|
} // __v_
|
||||||
// __v_ end
|
// __v_ end
|
||||||
NSApp.activationPolicy = NSApplicationActivationPolicyRegular;
|
NSApp.activationPolicy = NSApplicationActivationPolicyRegular;
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
// __v start
|
// __v start
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// Create a child view for native rendering
|
// Create a child view for native rendering
|
||||||
if (_sapp.__v_native_render) {
|
if (_sapp.__v_native_render) {
|
||||||
|
|
||||||
CGRect wRect = _sapp.macos.window.frame;
|
CGRect wRect = _sapp.macos.window.frame;
|
||||||
NSView *contentView =_sapp.macos.window.contentView;
|
NSView *contentView =_sapp.macos.window.contentView;
|
||||||
CGRect cRect = contentView.frame;
|
CGRect cRect = contentView.frame;
|
||||||
|
|
||||||
CGRect rect = CGRectMake(wRect.origin.x, wRect.origin.y, cRect.size.width, cRect.size.height);
|
CGRect rect = CGRectMake(wRect.origin.x, wRect.origin.y, cRect.size.width, cRect.size.height);
|
||||||
NSWindow *overlayWindow = [[NSWindow alloc]initWithContentRect:rect
|
NSWindow *overlayWindow = [[NSWindow alloc]initWithContentRect:rect
|
||||||
styleMask:NSBorderlessWindowMask
|
styleMask:NSBorderlessWindowMask
|
||||||
backing:NSBackingStoreBuffered
|
backing:NSBackingStoreBuffered
|
||||||
defer:NO];
|
defer:NO];
|
||||||
//overlayWindow.backgroundColor = [NSColor whiteColor];
|
//overlayWindow.backgroundColor = [NSColor whiteColor];
|
||||||
|
|
||||||
//overlayWindow.backgroundColor = [[NSColor whiteColor] colorWithAlphaComponent:0];
|
//overlayWindow.backgroundColor = [[NSColor whiteColor] colorWithAlphaComponent:0];
|
||||||
[overlayWindow setOpaque:YES];
|
[overlayWindow setOpaque:YES];
|
||||||
[_sapp.macos.window setIgnoresMouseEvents:NO];
|
[_sapp.macos.window setIgnoresMouseEvents:NO];
|
||||||
g_view = [[MyView2 alloc] init];
|
g_view = [[MyView2 alloc] init];
|
||||||
overlayWindow.contentView = g_view;
|
overlayWindow.contentView = g_view;
|
||||||
|
|
||||||
[ contentView addSubview:g_view];
|
[ contentView addSubview:g_view];
|
||||||
//[ _sapp.macos.window addChildWindow:overlayWindow ordered:NSWindowAbove];
|
//[ _sapp.macos.window addChildWindow:overlayWindow ordered:NSWindowAbove];
|
||||||
[_sapp.macos.window center];
|
[_sapp.macos.window center];
|
||||||
|
}
|
||||||
}
|
//////////////////////////////////
|
||||||
//////////////////////////////////
|
// __v_ end
|
||||||
// __v_ end
|
|
||||||
|
|
||||||
[_sapp.macos.window makeKeyAndOrderFront:nil];
|
[_sapp.macos.window makeKeyAndOrderFront:nil];
|
||||||
_sapp_macos_update_dimensions();
|
_sapp_macos_update_dimensions();
|
||||||
|
|
||||||
// __v_ start
|
// __v_ start
|
||||||
// [NSEvent setMouseCoalescingEnabled:NO];
|
// [NSEvent setMouseCoalescingEnabled:NO];
|
||||||
// __v_ end
|
// __v_ end
|
||||||
|
@ -3520,6 +3706,7 @@ _SOKOL_PRIVATE void _sapp_macos_poll_input_events() {
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)rect {
|
- (void)drawRect:(NSRect)rect {
|
||||||
_SOKOL_UNUSED(rect);
|
_SOKOL_UNUSED(rect);
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
/* Catch any last-moment input events */
|
/* Catch any last-moment input events */
|
||||||
_sapp_macos_poll_input_events();
|
_sapp_macos_poll_input_events();
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
@ -3656,8 +3843,6 @@ _SOKOL_PRIVATE void _sapp_macos_poll_input_events() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
- (void)keyDown:(NSEvent*)event {
|
- (void)keyDown:(NSEvent*)event {
|
||||||
//puts("-keyDown()");
|
|
||||||
//NSLog(@"%@", event);
|
|
||||||
if (_sapp_events_enabled()) {
|
if (_sapp_events_enabled()) {
|
||||||
const uint32_t mods = _sapp_macos_mods(event);
|
const uint32_t mods = _sapp_macos_mods(event);
|
||||||
/* NOTE: macOS doesn't send keyUp events while the Cmd key is pressed,
|
/* NOTE: macOS doesn't send keyUp events while the Cmd key is pressed,
|
||||||
|
@ -3881,10 +4066,11 @@ _SOKOL_PRIVATE void _sapp_ios_show_keyboard(bool shown) {
|
||||||
}
|
}
|
||||||
_sapp.framebuffer_width = _sapp.window_width * _sapp.dpi_scale;
|
_sapp.framebuffer_width = _sapp.window_width * _sapp.dpi_scale;
|
||||||
_sapp.framebuffer_height = _sapp.window_height * _sapp.dpi_scale;
|
_sapp.framebuffer_height = _sapp.window_height * _sapp.dpi_scale;
|
||||||
|
NSInteger max_fps = UIScreen.mainScreen.maximumFramesPerSecond;
|
||||||
#if defined(SOKOL_METAL)
|
#if defined(SOKOL_METAL)
|
||||||
_sapp.ios.mtl_device = MTLCreateSystemDefaultDevice();
|
_sapp.ios.mtl_device = MTLCreateSystemDefaultDevice();
|
||||||
_sapp.ios.view = [[_sapp_ios_view alloc] init];
|
_sapp.ios.view = [[_sapp_ios_view alloc] init];
|
||||||
_sapp.ios.view.preferredFramesPerSecond = 60 / _sapp.swap_interval;
|
_sapp.ios.view.preferredFramesPerSecond = max_fps / _sapp.swap_interval;
|
||||||
_sapp.ios.view.device = _sapp.ios.mtl_device;
|
_sapp.ios.view.device = _sapp.ios.mtl_device;
|
||||||
_sapp.ios.view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
|
_sapp.ios.view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
_sapp.ios.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
_sapp.ios.view.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||||
|
@ -3924,14 +4110,14 @@ _SOKOL_PRIVATE void _sapp_ios_show_keyboard(bool shown) {
|
||||||
_sapp.ios.view.multipleTouchEnabled = YES;
|
_sapp.ios.view.multipleTouchEnabled = YES;
|
||||||
// on GLKView, contentScaleFactor appears to work just fine!
|
// on GLKView, contentScaleFactor appears to work just fine!
|
||||||
if (_sapp.desc.high_dpi) {
|
if (_sapp.desc.high_dpi) {
|
||||||
_sapp.ios.view.contentScaleFactor = 2.0;
|
_sapp.ios.view.contentScaleFactor = _sapp.dpi_scale;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_sapp.ios.view.contentScaleFactor = 1.0;
|
_sapp.ios.view.contentScaleFactor = 1.0;
|
||||||
}
|
}
|
||||||
_sapp.ios.view_ctrl = [[GLKViewController alloc] init];
|
_sapp.ios.view_ctrl = [[GLKViewController alloc] init];
|
||||||
_sapp.ios.view_ctrl.view = _sapp.ios.view;
|
_sapp.ios.view_ctrl.view = _sapp.ios.view;
|
||||||
_sapp.ios.view_ctrl.preferredFramesPerSecond = 60 / _sapp.swap_interval;
|
_sapp.ios.view_ctrl.preferredFramesPerSecond = max_fps / _sapp.swap_interval;
|
||||||
_sapp.ios.window.rootViewController = _sapp.ios.view_ctrl;
|
_sapp.ios.window.rootViewController = _sapp.ios.view_ctrl;
|
||||||
#endif
|
#endif
|
||||||
[_sapp.ios.window makeKeyAndVisible];
|
[_sapp.ios.window makeKeyAndVisible];
|
||||||
|
@ -4043,6 +4229,7 @@ _SOKOL_PRIVATE void _sapp_ios_show_keyboard(bool shown) {
|
||||||
@implementation _sapp_ios_view
|
@implementation _sapp_ios_view
|
||||||
- (void)drawRect:(CGRect)rect {
|
- (void)drawRect:(CGRect)rect {
|
||||||
_SOKOL_UNUSED(rect);
|
_SOKOL_UNUSED(rect);
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
_sapp_ios_frame();
|
_sapp_ios_frame();
|
||||||
}
|
}
|
||||||
|
@ -5172,8 +5359,8 @@ _SOKOL_PRIVATE void _sapp_emsc_unregister_eventhandlers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE EM_BOOL _sapp_emsc_frame(double time, void* userData) {
|
_SOKOL_PRIVATE EM_BOOL _sapp_emsc_frame(double time, void* userData) {
|
||||||
_SOKOL_UNUSED(time);
|
|
||||||
_SOKOL_UNUSED(userData);
|
_SOKOL_UNUSED(userData);
|
||||||
|
_sapp_timing_external(&_sapp.timing, time / 1000.0);
|
||||||
|
|
||||||
#if defined(SOKOL_WGPU)
|
#if defined(SOKOL_WGPU)
|
||||||
/*
|
/*
|
||||||
|
@ -5591,6 +5778,14 @@ static inline HRESULT _sapp_dxgi_Present(IDXGISwapChain* self, UINT SyncInterval
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline HRESULT _sapp_dxgi_GetFrameStatistics(IDXGISwapChain* self, DXGI_FRAME_STATISTICS* pStats) {
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
return self->GetFrameStatistics(pStats);
|
||||||
|
#else
|
||||||
|
return self->lpVtbl->GetFrameStatistics(self, pStats);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE void _sapp_d3d11_create_device_and_swapchain(void) {
|
_SOKOL_PRIVATE void _sapp_d3d11_create_device_and_swapchain(void) {
|
||||||
DXGI_SWAP_CHAIN_DESC* sc_desc = &_sapp.d3d11.swap_chain_desc;
|
DXGI_SWAP_CHAIN_DESC* sc_desc = &_sapp.d3d11.swap_chain_desc;
|
||||||
sc_desc->BufferDesc.Width = (UINT)_sapp.framebuffer_width;
|
sc_desc->BufferDesc.Width = (UINT)_sapp.framebuffer_width;
|
||||||
|
@ -6234,6 +6429,33 @@ _SOKOL_PRIVATE void _sapp_win32_files_dropped(HDROP hdrop) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sapp_win32_timing_measure(void) {
|
||||||
|
#if defined(SOKOL_D3D11)
|
||||||
|
// on D3D11, use the more precise DXGI timestamp
|
||||||
|
DXGI_FRAME_STATISTICS dxgi_stats;
|
||||||
|
_SAPP_CLEAR(DXGI_FRAME_STATISTICS, dxgi_stats);
|
||||||
|
HRESULT hr = _sapp_dxgi_GetFrameStatistics(_sapp.d3d11.swap_chain, &dxgi_stats);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
if (dxgi_stats.SyncRefreshCount != _sapp.d3d11.sync_refresh_count) {
|
||||||
|
if ((_sapp.d3d11.sync_refresh_count + 1) != dxgi_stats.SyncRefreshCount) {
|
||||||
|
_sapp_timing_external_reset(&_sapp.timing);
|
||||||
|
}
|
||||||
|
_sapp.d3d11.sync_refresh_count = dxgi_stats.SyncRefreshCount;
|
||||||
|
LARGE_INTEGER qpc = dxgi_stats.SyncQPCTime;
|
||||||
|
const uint64_t now = (uint64_t)_sapp_int64_muldiv(qpc.QuadPart - _sapp.timing.timestamp.win.start.QuadPart, 1000000000, _sapp.timing.timestamp.win.freq.QuadPart);
|
||||||
|
_sapp_timing_external(&_sapp.timing, (double)now / 1000000000.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// fallback if GetFrameStats doesn't work for some reason
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(SOKOL_GLCORE33)
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
_SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
if (!_sapp.win32.in_create_window) {
|
if (!_sapp.win32.in_create_window) {
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
|
@ -6417,6 +6639,7 @@ _SOKOL_PRIVATE LRESULT CALLBACK _sapp_win32_wndproc(HWND hWnd, UINT uMsg, WPARAM
|
||||||
KillTimer(_sapp.win32.hwnd, 1);
|
KillTimer(_sapp.win32.hwnd, 1);
|
||||||
break;
|
break;
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
|
_sapp_win32_timing_measure();
|
||||||
_sapp_frame();
|
_sapp_frame();
|
||||||
#if defined(SOKOL_D3D11)
|
#if defined(SOKOL_D3D11)
|
||||||
_sapp_d3d11_present();
|
_sapp_d3d11_present();
|
||||||
|
@ -6789,6 +7012,7 @@ _SOKOL_PRIVATE void _sapp_win32_run(const sapp_desc* desc) {
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while (!(done || _sapp.quit_ordered)) {
|
while (!(done || _sapp.quit_ordered)) {
|
||||||
|
_sapp_win32_timing_measure();
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
if (WM_QUIT == msg.message) {
|
if (WM_QUIT == msg.message) {
|
||||||
|
@ -7729,6 +7953,7 @@ void App::Run() {
|
||||||
// NOTE: UWP will simply terminate an application, it's not possible to detect when an application is being closed
|
// NOTE: UWP will simply terminate an application, it's not possible to detect when an application is being closed
|
||||||
while (true) {
|
while (true) {
|
||||||
if (m_windowVisible) {
|
if (m_windowVisible) {
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
|
winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessAllIfPresent);
|
||||||
_sapp_frame();
|
_sapp_frame();
|
||||||
m_deviceResources->Present();
|
m_deviceResources->Present();
|
||||||
|
@ -8108,6 +8333,7 @@ _SOKOL_PRIVATE void _sapp_android_frame(void) {
|
||||||
SOKOL_ASSERT(_sapp.android.display != EGL_NO_DISPLAY);
|
SOKOL_ASSERT(_sapp.android.display != EGL_NO_DISPLAY);
|
||||||
SOKOL_ASSERT(_sapp.android.context != EGL_NO_CONTEXT);
|
SOKOL_ASSERT(_sapp.android.context != EGL_NO_CONTEXT);
|
||||||
SOKOL_ASSERT(_sapp.android.surface != EGL_NO_SURFACE);
|
SOKOL_ASSERT(_sapp.android.surface != EGL_NO_SURFACE);
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
_sapp_android_update_dimensions(_sapp.android.current.window, false);
|
_sapp_android_update_dimensions(_sapp.android.current.window, false);
|
||||||
_sapp_frame();
|
_sapp_frame();
|
||||||
eglSwapBuffers(_sapp.android.display, _sapp.android.surface);
|
eglSwapBuffers(_sapp.android.display, _sapp.android.surface);
|
||||||
|
@ -10718,6 +10944,7 @@ _SOKOL_PRIVATE void _sapp_linux_run(const sapp_desc* desc) {
|
||||||
_sapp_glx_swapinterval(_sapp.swap_interval);
|
_sapp_glx_swapinterval(_sapp.swap_interval);
|
||||||
XFlush(_sapp.x11.display);
|
XFlush(_sapp.x11.display);
|
||||||
while (!_sapp.quit_ordered) {
|
while (!_sapp.quit_ordered) {
|
||||||
|
_sapp_timing_measure(&_sapp.timing);
|
||||||
_sapp_glx_make_current();
|
_sapp_glx_make_current();
|
||||||
int count = XPending(_sapp.x11.display);
|
int count = XPending(_sapp.x11.display);
|
||||||
while (count--) {
|
while (count--) {
|
||||||
|
@ -10807,6 +11034,10 @@ SOKOL_API_IMPL uint64_t sapp_frame_count(void) {
|
||||||
return _sapp.frame_count;
|
return _sapp.frame_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOKOL_API_IMPL double sapp_frame_duration(void) {
|
||||||
|
return _sapp_timing_get_avg(&_sapp.timing);
|
||||||
|
}
|
||||||
|
|
||||||
SOKOL_API_IMPL int sapp_width(void) {
|
SOKOL_API_IMPL int sapp_width(void) {
|
||||||
return (_sapp.framebuffer_width > 0) ? _sapp.framebuffer_width : 1;
|
return (_sapp.framebuffer_width > 0) ? _sapp.framebuffer_width : 1;
|
||||||
}
|
}
|
||||||
|
@ -10995,19 +11226,6 @@ SOKOL_API_IMPL void sapp_set_window_title(const char* title) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SOKOL_API_IMPL void sapp_resize_window(int width, int height) {
|
|
||||||
/*
|
|
||||||
#if defined(_SAPP_MACOS)
|
|
||||||
_sapp_macos_resize_window(width, height);
|
|
||||||
#elif defined(_SAPP_WIN32)
|
|
||||||
_sapp_win32_resize_window();
|
|
||||||
#elif defined(_SAPP_LINUX)
|
|
||||||
_sapp_x11_resize_window();
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SOKOL_API_IMPL void sapp_set_icon(const sapp_icon_desc* desc) {
|
SOKOL_API_IMPL void sapp_set_icon(const sapp_icon_desc* desc) {
|
||||||
SOKOL_ASSERT(desc);
|
SOKOL_ASSERT(desc);
|
||||||
if (desc->sokol_default) {
|
if (desc->sokol_default) {
|
||||||
|
|
|
@ -439,6 +439,8 @@ SOKOL_AUDIO_API_DECL int saudio_sample_rate(void);
|
||||||
SOKOL_AUDIO_API_DECL int saudio_buffer_frames(void);
|
SOKOL_AUDIO_API_DECL int saudio_buffer_frames(void);
|
||||||
/* actual number of channels */
|
/* actual number of channels */
|
||||||
SOKOL_AUDIO_API_DECL int saudio_channels(void);
|
SOKOL_AUDIO_API_DECL int saudio_channels(void);
|
||||||
|
/* return true if audio context is currently suspended (only in WebAudio backend, all other backends return false) */
|
||||||
|
SOKOL_AUDIO_API_DECL bool saudio_suspended(void);
|
||||||
/* get current number of frames to fill packet queue */
|
/* get current number of frames to fill packet queue */
|
||||||
SOKOL_AUDIO_API_DECL int saudio_expect(void);
|
SOKOL_AUDIO_API_DECL int saudio_expect(void);
|
||||||
/* push sample frames from main thread, returns number of frames actually pushed */
|
/* push sample frames from main thread, returns number of frames actually pushed */
|
||||||
|
@ -556,12 +558,13 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc);
|
||||||
#endif
|
#endif
|
||||||
#include <mmdeviceapi.h>
|
#include <mmdeviceapi.h>
|
||||||
#include <audioclient.h>
|
#include <audioclient.h>
|
||||||
static const IID _saudio_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
|
static const IID _saudio_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2} };
|
||||||
static const IID _saudio_IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35, { 0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6 } };
|
static const IID _saudio_IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35, {0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6} };
|
||||||
static const CLSID _saudio_CLSID_IMMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c, { 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e } };
|
static const CLSID _saudio_CLSID_IMMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c, {0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e} };
|
||||||
static const IID _saudio_IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483,{ 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2 } };
|
static const IID _saudio_IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483, {0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2} };
|
||||||
static const IID _saudio_IID_Devinterface_Audio_Render = { 0xe6327cad, 0xdcec, 0x4949, {0xae, 0x8a, 0x99, 0x1e, 0x97, 0x6a, 0x79, 0xd2 } };
|
static const IID _saudio_IID_Devinterface_Audio_Render = { 0xe6327cad, 0xdcec, 0x4949, {0xae, 0x8a, 0x99, 0x1e, 0x97, 0x6a, 0x79, 0xd2} };
|
||||||
static const IID _saudio_IID_IActivateAudioInterface_Completion_Handler = { 0x94ea2b94, 0xe9cc, 0x49e0, {0xc0, 0xff, 0xee, 0x64, 0xca, 0x8f, 0x5b, 0x90} };
|
static const IID _saudio_IID_IActivateAudioInterface_Completion_Handler = { 0x94ea2b94, 0xe9cc, 0x49e0, {0xc0, 0xff, 0xee, 0x64, 0xca, 0x8f, 0x5b, 0x90} };
|
||||||
|
static const GUID _saudio_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} };
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
#define _SOKOL_AUDIO_WIN32COM_ID(x) (x)
|
#define _SOKOL_AUDIO_WIN32COM_ID(x) (x)
|
||||||
#else
|
#else
|
||||||
|
@ -821,7 +824,6 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
IAudioClient* audio_client;
|
IAudioClient* audio_client;
|
||||||
IAudioRenderClient* render_client;
|
IAudioRenderClient* render_client;
|
||||||
int si16_bytes_per_frame;
|
|
||||||
_saudio_wasapi_thread_data_t thread;
|
_saudio_wasapi_thread_data_t thread;
|
||||||
} _saudio_backend_t;
|
} _saudio_backend_t;
|
||||||
|
|
||||||
|
@ -1422,6 +1424,10 @@ _SOKOL_PRIVATE void _saudio_wasapi_fill_buffer(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE int _saudio_wasapi_min(int a, int b) {
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE void _saudio_wasapi_submit_buffer(int num_frames) {
|
_SOKOL_PRIVATE void _saudio_wasapi_submit_buffer(int num_frames) {
|
||||||
BYTE* wasapi_buffer = 0;
|
BYTE* wasapi_buffer = 0;
|
||||||
if (FAILED(IAudioRenderClient_GetBuffer(_saudio.backend.render_client, num_frames, &wasapi_buffer))) {
|
if (FAILED(IAudioRenderClient_GetBuffer(_saudio.backend.render_client, num_frames, &wasapi_buffer))) {
|
||||||
|
@ -1429,24 +1435,34 @@ _SOKOL_PRIVATE void _saudio_wasapi_submit_buffer(int num_frames) {
|
||||||
}
|
}
|
||||||
SOKOL_ASSERT(wasapi_buffer);
|
SOKOL_ASSERT(wasapi_buffer);
|
||||||
|
|
||||||
/* convert float samples to int16_t, refill float buffer if needed */
|
/* copy samples to WASAPI buffer, refill source buffer if needed */
|
||||||
const int num_samples = num_frames * _saudio.num_channels;
|
int num_remaining_samples = num_frames * _saudio.num_channels;
|
||||||
int16_t* dst = (int16_t*) wasapi_buffer;
|
|
||||||
int buffer_pos = _saudio.backend.thread.src_buffer_pos;
|
int buffer_pos = _saudio.backend.thread.src_buffer_pos;
|
||||||
const int buffer_float_size = _saudio.backend.thread.src_buffer_byte_size / (int)sizeof(float);
|
const int buffer_size_in_samples = _saudio.backend.thread.src_buffer_byte_size / (int)sizeof(float);
|
||||||
float* src = _saudio.backend.thread.src_buffer;
|
float* dst = (float*)wasapi_buffer;
|
||||||
for (int i = 0; i < num_samples; i++) {
|
const float* dst_end = dst + num_remaining_samples;
|
||||||
|
_SOKOL_UNUSED(dst_end); // suppress unused warning in release mode
|
||||||
|
const float* src = _saudio.backend.thread.src_buffer;
|
||||||
|
|
||||||
|
while (num_remaining_samples > 0) {
|
||||||
if (0 == buffer_pos) {
|
if (0 == buffer_pos) {
|
||||||
_saudio_wasapi_fill_buffer();
|
_saudio_wasapi_fill_buffer();
|
||||||
}
|
}
|
||||||
dst[i] = (int16_t) (src[buffer_pos] * 0x7FFF);
|
const int samples_to_copy = _saudio_wasapi_min(num_remaining_samples, buffer_size_in_samples - buffer_pos);
|
||||||
buffer_pos += 1;
|
SOKOL_ASSERT((buffer_pos + samples_to_copy) <= buffer_size_in_samples);
|
||||||
if (buffer_pos == buffer_float_size) {
|
SOKOL_ASSERT((dst + samples_to_copy) <= dst_end);
|
||||||
|
memcpy(dst, &src[buffer_pos], (size_t)samples_to_copy * sizeof(float));
|
||||||
|
num_remaining_samples -= samples_to_copy;
|
||||||
|
SOKOL_ASSERT(num_remaining_samples >= 0);
|
||||||
|
buffer_pos += samples_to_copy;
|
||||||
|
dst += samples_to_copy;
|
||||||
|
|
||||||
|
SOKOL_ASSERT(buffer_pos <= buffer_size_in_samples);
|
||||||
|
if (buffer_pos == buffer_size_in_samples) {
|
||||||
buffer_pos = 0;
|
buffer_pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_saudio.backend.thread.src_buffer_pos = buffer_pos;
|
_saudio.backend.thread.src_buffer_pos = buffer_pos;
|
||||||
|
|
||||||
IAudioRenderClient_ReleaseBuffer(_saudio.backend.render_client, num_frames, 0);
|
IAudioRenderClient_ReleaseBuffer(_saudio.backend.render_client, num_frames, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1584,20 +1600,25 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
WAVEFORMATEX fmt;
|
|
||||||
memset(&fmt, 0, sizeof(fmt));
|
WAVEFORMATEXTENSIBLE fmtex;
|
||||||
fmt.nChannels = (WORD)_saudio.num_channels;
|
memset(&fmtex, 0, sizeof(fmtex));
|
||||||
fmt.nSamplesPerSec = (DWORD)_saudio.sample_rate;
|
fmtex.Format.nChannels = (WORD)_saudio.num_channels;
|
||||||
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
fmtex.Format.nSamplesPerSec = (DWORD)_saudio.sample_rate;
|
||||||
fmt.wBitsPerSample = 16;
|
fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||||
fmt.nBlockAlign = (fmt.nChannels * fmt.wBitsPerSample) / 8;
|
fmtex.Format.wBitsPerSample = 32;
|
||||||
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
|
fmtex.Format.nBlockAlign = (fmtex.Format.nChannels * fmtex.Format.wBitsPerSample) / 8;
|
||||||
|
fmtex.Format.nAvgBytesPerSec = fmtex.Format.nSamplesPerSec * fmtex.Format.nBlockAlign;
|
||||||
|
fmtex.Format.cbSize = 22; /* WORD + DWORD + GUID */
|
||||||
|
fmtex.Samples.wValidBitsPerSample = 32;
|
||||||
|
fmtex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||||
|
fmtex.SubFormat = _saudio_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||||
dur = (REFERENCE_TIME)
|
dur = (REFERENCE_TIME)
|
||||||
(((double)_saudio.buffer_frames) / (((double)_saudio.sample_rate) * (1.0/10000000.0)));
|
(((double)_saudio.buffer_frames) / (((double)_saudio.sample_rate) * (1.0/10000000.0)));
|
||||||
if (FAILED(IAudioClient_Initialize(_saudio.backend.audio_client,
|
if (FAILED(IAudioClient_Initialize(_saudio.backend.audio_client,
|
||||||
AUDCLNT_SHAREMODE_SHARED,
|
AUDCLNT_SHAREMODE_SHARED,
|
||||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK|AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM|AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,
|
AUDCLNT_STREAMFLAGS_EVENTCALLBACK|AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM|AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,
|
||||||
dur, 0, &fmt, 0)))
|
dur, 0, (WAVEFORMATEX*)&fmtex, 0)))
|
||||||
{
|
{
|
||||||
SOKOL_LOG("sokol_audio wasapi: audio client initialize failed");
|
SOKOL_LOG("sokol_audio wasapi: audio client initialize failed");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1617,7 +1638,6 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||||
SOKOL_LOG("sokol_audio wasapi: audio client SetEventHandle failed");
|
SOKOL_LOG("sokol_audio wasapi: audio client SetEventHandle failed");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
_saudio.backend.si16_bytes_per_frame = _saudio.num_channels * (int)sizeof(int16_t);
|
|
||||||
_saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);
|
_saudio.bytes_per_frame = _saudio.num_channels * (int)sizeof(float);
|
||||||
_saudio.backend.thread.src_buffer_frames = _saudio.buffer_frames;
|
_saudio.backend.thread.src_buffer_frames = _saudio.buffer_frames;
|
||||||
_saudio.backend.thread.src_buffer_byte_size = _saudio.backend.thread.src_buffer_frames * _saudio.bytes_per_frame;
|
_saudio.backend.thread.src_buffer_byte_size = _saudio.backend.thread.src_buffer_frames * _saudio.bytes_per_frame;
|
||||||
|
@ -1776,6 +1796,18 @@ EM_JS(int, saudio_js_buffer_frames, (void), {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* return 1 if the WebAudio context is currently suspended, else 0 */
|
||||||
|
EM_JS(int, saudio_js_suspended, (void), {
|
||||||
|
if (Module._saudio_context) {
|
||||||
|
if (Module._saudio_context.state === 'suspended') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
_SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
_SOKOL_PRIVATE bool _saudio_backend_init(void) {
|
||||||
if (saudio_js_init(_saudio.sample_rate, _saudio.num_channels, _saudio.buffer_frames)) {
|
if (saudio_js_init(_saudio.sample_rate, _saudio.num_channels, _saudio.buffer_frames)) {
|
||||||
_saudio.bytes_per_frame = (int)sizeof(float) * _saudio.num_channels;
|
_saudio.bytes_per_frame = (int)sizeof(float) * _saudio.num_channels;
|
||||||
|
@ -2113,6 +2145,19 @@ SOKOL_API_IMPL int saudio_channels(void) {
|
||||||
return _saudio.num_channels;
|
return _saudio.num_channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOKOL_API_IMPL bool saudio_suspended(void) {
|
||||||
|
#if defined(_SAUDIO_EMSCRIPTEN)
|
||||||
|
if (_saudio.valid) {
|
||||||
|
return 1 == saudio_js_suspended();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
SOKOL_API_IMPL int saudio_expect(void) {
|
SOKOL_API_IMPL int saudio_expect(void) {
|
||||||
if (_saudio.valid) {
|
if (_saudio.valid) {
|
||||||
const int num_frames = _saudio_fifo_writable_bytes(&_saudio.fifo) / _saudio.bytes_per_frame;
|
const int num_frames = _saudio_fifo_writable_bytes(&_saudio.fifo) / _saudio.bytes_per_frame;
|
||||||
|
|
|
@ -2976,10 +2976,10 @@ typedef struct {
|
||||||
/* helper macros */
|
/* helper macros */
|
||||||
#define _sg_def(val, def) (((val) == 0) ? (def) : (val))
|
#define _sg_def(val, def) (((val) == 0) ? (def) : (val))
|
||||||
#define _sg_def_flt(val, def) (((val) == 0.0f) ? (def) : (val))
|
#define _sg_def_flt(val, def) (((val) == 0.0f) ? (def) : (val))
|
||||||
#define _sg_min(a,b) ((a<b)?a:b)
|
#define _sg_min(a,b) (((a)<(b))?(a):(b))
|
||||||
#define _sg_max(a,b) ((a>b)?a:b)
|
#define _sg_max(a,b) (((a)>(b))?(a):(b))
|
||||||
#define _sg_clamp(v,v0,v1) ((v<v0)?(v0):((v>v1)?(v1):(v)))
|
#define _sg_clamp(v,v0,v1) (((v)<(v0))?(v0):(((v)>(v1))?(v1):(v)))
|
||||||
#define _sg_fequal(val,cmp,delta) (((val-cmp)> -delta)&&((val-cmp)<delta))
|
#define _sg_fequal(val,cmp,delta) ((((val)-(cmp))> -(delta))&&(((val)-(cmp))<(delta)))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int size;
|
int size;
|
||||||
|
@ -3098,6 +3098,7 @@ _SOKOL_PRIVATE void _sg_shader_common_init(_sg_shader_common_t* cmn, const sg_sh
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sg_shader shader_id;
|
sg_shader shader_id;
|
||||||
sg_index_type index_type;
|
sg_index_type index_type;
|
||||||
|
bool use_instanced_draw;
|
||||||
bool vertex_layout_valid[SG_MAX_SHADERSTAGE_BUFFERS];
|
bool vertex_layout_valid[SG_MAX_SHADERSTAGE_BUFFERS];
|
||||||
int color_attachment_count;
|
int color_attachment_count;
|
||||||
sg_pixel_format color_formats[SG_MAX_COLOR_ATTACHMENTS];
|
sg_pixel_format color_formats[SG_MAX_COLOR_ATTACHMENTS];
|
||||||
|
@ -3113,6 +3114,7 @@ _SOKOL_PRIVATE void _sg_pipeline_common_init(_sg_pipeline_common_t* cmn, const s
|
||||||
SOKOL_ASSERT((desc->color_count >= 1) && (desc->color_count <= SG_MAX_COLOR_ATTACHMENTS));
|
SOKOL_ASSERT((desc->color_count >= 1) && (desc->color_count <= SG_MAX_COLOR_ATTACHMENTS));
|
||||||
cmn->shader_id = desc->shader;
|
cmn->shader_id = desc->shader;
|
||||||
cmn->index_type = desc->index_type;
|
cmn->index_type = desc->index_type;
|
||||||
|
cmn->use_instanced_draw = false;
|
||||||
for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
|
for (int i = 0; i < SG_MAX_SHADERSTAGE_BUFFERS; i++) {
|
||||||
cmn->vertex_layout_valid[i] = false;
|
cmn->vertex_layout_valid[i] = false;
|
||||||
}
|
}
|
||||||
|
@ -3584,6 +3586,7 @@ typedef struct {
|
||||||
void* user_data;
|
void* user_data;
|
||||||
bool in_pass;
|
bool in_pass;
|
||||||
bool use_indexed_draw;
|
bool use_indexed_draw;
|
||||||
|
bool use_instanced_draw;
|
||||||
int cur_width;
|
int cur_width;
|
||||||
int cur_height;
|
int cur_height;
|
||||||
int num_rtvs;
|
int num_rtvs;
|
||||||
|
@ -3912,6 +3915,10 @@ typedef enum {
|
||||||
_SG_VALIDATE_BUFFERDESC_DATA_SIZE,
|
_SG_VALIDATE_BUFFERDESC_DATA_SIZE,
|
||||||
_SG_VALIDATE_BUFFERDESC_NO_DATA,
|
_SG_VALIDATE_BUFFERDESC_NO_DATA,
|
||||||
|
|
||||||
|
/* image data (for image creation and updating) */
|
||||||
|
_SG_VALIDATE_IMAGEDATA_NODATA,
|
||||||
|
_SG_VALIDATE_IMAGEDATA_DATA_SIZE,
|
||||||
|
|
||||||
/* image creation */
|
/* image creation */
|
||||||
_SG_VALIDATE_IMAGEDESC_CANARY,
|
_SG_VALIDATE_IMAGEDESC_CANARY,
|
||||||
_SG_VALIDATE_IMAGEDESC_WIDTH,
|
_SG_VALIDATE_IMAGEDESC_WIDTH,
|
||||||
|
@ -3922,8 +3929,9 @@ typedef enum {
|
||||||
_SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT,
|
_SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT,
|
||||||
_SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE,
|
_SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE,
|
||||||
_SG_VALIDATE_IMAGEDESC_RT_NO_DATA,
|
_SG_VALIDATE_IMAGEDESC_RT_NO_DATA,
|
||||||
_SG_VALIDATE_IMAGEDESC_DATA,
|
_SG_VALIDATE_IMAGEDESC_INJECTED_NO_DATA,
|
||||||
_SG_VALIDATE_IMAGEDESC_NO_DATA,
|
_SG_VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA,
|
||||||
|
_SG_VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE,
|
||||||
|
|
||||||
/* shader creation */
|
/* shader creation */
|
||||||
_SG_VALIDATE_SHADERDESC_CANARY,
|
_SG_VALIDATE_SHADERDESC_CANARY,
|
||||||
|
@ -4019,8 +4027,6 @@ typedef enum {
|
||||||
/* sg_update_image validation */
|
/* sg_update_image validation */
|
||||||
_SG_VALIDATE_UPDIMG_USAGE,
|
_SG_VALIDATE_UPDIMG_USAGE,
|
||||||
_SG_VALIDATE_UPDIMG_NOTENOUGHDATA,
|
_SG_VALIDATE_UPDIMG_NOTENOUGHDATA,
|
||||||
_SG_VALIDATE_UPDIMG_SIZE,
|
|
||||||
_SG_VALIDATE_UPDIMG_COMPRESSED,
|
|
||||||
_SG_VALIDATE_UPDIMG_ONCE
|
_SG_VALIDATE_UPDIMG_ONCE
|
||||||
} _sg_validate_error_t;
|
} _sg_validate_error_t;
|
||||||
|
|
||||||
|
@ -4234,7 +4240,21 @@ _SOKOL_PRIVATE int _sg_roundup(int val, int round_to) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return row pitch for an image
|
/* return row pitch for an image
|
||||||
|
|
||||||
see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp
|
see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp
|
||||||
|
|
||||||
|
For the special PVRTC pitch computation, see:
|
||||||
|
GL extension requirement (https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt)
|
||||||
|
|
||||||
|
Quote:
|
||||||
|
|
||||||
|
6) How is the imageSize argument calculated for the CompressedTexImage2D
|
||||||
|
and CompressedTexSubImage2D functions.
|
||||||
|
|
||||||
|
Resolution: For PVRTC 4BPP formats the imageSize is calculated as:
|
||||||
|
( max(width, 8) * max(height, 8) * 4 + 7) / 8
|
||||||
|
For PVRTC 2BPP formats the imageSize is calculated as:
|
||||||
|
( max(width, 16) * max(height, 8) * 2 + 7) / 8
|
||||||
*/
|
*/
|
||||||
_SOKOL_PRIVATE int _sg_row_pitch(sg_pixel_format fmt, int width, int row_align) {
|
_SOKOL_PRIVATE int _sg_row_pitch(sg_pixel_format fmt, int width, int row_align) {
|
||||||
int pitch;
|
int pitch;
|
||||||
|
@ -4262,23 +4282,11 @@ _SOKOL_PRIVATE int _sg_row_pitch(sg_pixel_format fmt, int width, int row_align)
|
||||||
break;
|
break;
|
||||||
case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
|
case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
|
||||||
case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
|
case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
|
||||||
{
|
pitch = (_sg_max(width, 8) * 4 + 7) / 8;
|
||||||
const int block_size = 4*4;
|
|
||||||
const int bpp = 4;
|
|
||||||
int width_blocks = width / 4;
|
|
||||||
width_blocks = width_blocks < 2 ? 2 : width_blocks;
|
|
||||||
pitch = width_blocks * ((block_size * bpp) / 8);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
|
case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
|
||||||
case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
|
case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
|
||||||
{
|
pitch = (_sg_max(width, 16) * 2 + 7) / 8;
|
||||||
const int block_size = 8*4;
|
|
||||||
const int bpp = 2;
|
|
||||||
int width_blocks = width / 4;
|
|
||||||
width_blocks = width_blocks < 2 ? 2 : width_blocks;
|
|
||||||
pitch = width_blocks * ((block_size * bpp) / 8);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pitch = width * _sg_pixelformat_bytesize(fmt);
|
pitch = width * _sg_pixelformat_bytesize(fmt);
|
||||||
|
@ -4307,11 +4315,19 @@ _SOKOL_PRIVATE int _sg_num_rows(sg_pixel_format fmt, int height) {
|
||||||
case SG_PIXELFORMAT_BC6H_RGBF:
|
case SG_PIXELFORMAT_BC6H_RGBF:
|
||||||
case SG_PIXELFORMAT_BC6H_RGBUF:
|
case SG_PIXELFORMAT_BC6H_RGBUF:
|
||||||
case SG_PIXELFORMAT_BC7_RGBA:
|
case SG_PIXELFORMAT_BC7_RGBA:
|
||||||
|
num_rows = ((height + 3) / 4);
|
||||||
|
break;
|
||||||
case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
|
case SG_PIXELFORMAT_PVRTC_RGB_4BPP:
|
||||||
case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
|
case SG_PIXELFORMAT_PVRTC_RGBA_4BPP:
|
||||||
case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
|
case SG_PIXELFORMAT_PVRTC_RGB_2BPP:
|
||||||
case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
|
case SG_PIXELFORMAT_PVRTC_RGBA_2BPP:
|
||||||
num_rows = ((height + 3) / 4);
|
/* NOTE: this is most likely not correct because it ignores any
|
||||||
|
PVCRTC block size, but multiplied with _sg_row_pitch()
|
||||||
|
it gives the correct surface pitch.
|
||||||
|
|
||||||
|
See: https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc.txt
|
||||||
|
*/
|
||||||
|
num_rows = ((_sg_max(height, 8) + 7) / 8) * 8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
num_rows = height;
|
num_rows = height;
|
||||||
|
@ -6327,7 +6343,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_image(_sg_image_t* img, const sg_
|
||||||
gl_img_target = _sg_gl_cubeface_target(face_index);
|
gl_img_target = _sg_gl_cubeface_target(face_index);
|
||||||
}
|
}
|
||||||
const GLvoid* data_ptr = desc->data.subimage[face_index][mip_index].ptr;
|
const GLvoid* data_ptr = desc->data.subimage[face_index][mip_index].ptr;
|
||||||
const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;
|
|
||||||
int mip_width = img->cmn.width >> mip_index;
|
int mip_width = img->cmn.width >> mip_index;
|
||||||
if (mip_width == 0) {
|
if (mip_width == 0) {
|
||||||
mip_width = 1;
|
mip_width = 1;
|
||||||
|
@ -6338,6 +6353,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_image(_sg_image_t* img, const sg_
|
||||||
}
|
}
|
||||||
if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
|
if ((SG_IMAGETYPE_2D == img->cmn.type) || (SG_IMAGETYPE_CUBE == img->cmn.type)) {
|
||||||
if (is_compressed) {
|
if (is_compressed) {
|
||||||
|
const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;
|
||||||
glCompressedTexImage2D(gl_img_target, mip_index, gl_internal_format,
|
glCompressedTexImage2D(gl_img_target, mip_index, gl_internal_format,
|
||||||
mip_width, mip_height, 0, data_size, data_ptr);
|
mip_width, mip_height, 0, data_size, data_ptr);
|
||||||
}
|
}
|
||||||
|
@ -6357,6 +6373,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_image(_sg_image_t* img, const sg_
|
||||||
mip_depth = 1;
|
mip_depth = 1;
|
||||||
}
|
}
|
||||||
if (is_compressed) {
|
if (is_compressed) {
|
||||||
|
const GLsizei data_size = (GLsizei) desc->data.subimage[face_index][mip_index].size;
|
||||||
glCompressedTexImage3D(gl_img_target, mip_index, gl_internal_format,
|
glCompressedTexImage3D(gl_img_target, mip_index, gl_internal_format,
|
||||||
mip_width, mip_height, mip_depth, 0, data_size, data_ptr);
|
mip_width, mip_height, mip_depth, 0, data_size, data_ptr);
|
||||||
}
|
}
|
||||||
|
@ -6585,6 +6602,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_pipeline(_sg_pipeline_t* pip, _sg
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gl_attr->divisor = (int8_t) step_rate;
|
gl_attr->divisor = (int8_t) step_rate;
|
||||||
|
pip->cmn.use_instanced_draw = true;
|
||||||
}
|
}
|
||||||
SOKOL_ASSERT(l_desc->stride > 0);
|
SOKOL_ASSERT(l_desc->stride > 0);
|
||||||
gl_attr->stride = (uint8_t) l_desc->stride;
|
gl_attr->stride = (uint8_t) l_desc->stride;
|
||||||
|
@ -7340,6 +7358,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_uniforms(sg_shader_stage stage_index, int ub_in
|
||||||
}
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE void _sg_gl_draw(int base_element, int num_elements, int num_instances) {
|
_SOKOL_PRIVATE void _sg_gl_draw(int base_element, int num_elements, int num_instances) {
|
||||||
|
SOKOL_ASSERT(_sg.gl.cache.cur_pipeline);
|
||||||
const GLenum i_type = _sg.gl.cache.cur_index_type;
|
const GLenum i_type = _sg.gl.cache.cur_index_type;
|
||||||
const GLenum p_type = _sg.gl.cache.cur_primitive_type;
|
const GLenum p_type = _sg.gl.cache.cur_primitive_type;
|
||||||
if (0 != i_type) {
|
if (0 != i_type) {
|
||||||
|
@ -7347,25 +7366,25 @@ _SOKOL_PRIVATE void _sg_gl_draw(int base_element, int num_elements, int num_inst
|
||||||
const int i_size = (i_type == GL_UNSIGNED_SHORT) ? 2 : 4;
|
const int i_size = (i_type == GL_UNSIGNED_SHORT) ? 2 : 4;
|
||||||
const int ib_offset = _sg.gl.cache.cur_ib_offset;
|
const int ib_offset = _sg.gl.cache.cur_ib_offset;
|
||||||
const GLvoid* indices = (const GLvoid*)(GLintptr)(base_element*i_size+ib_offset);
|
const GLvoid* indices = (const GLvoid*)(GLintptr)(base_element*i_size+ib_offset);
|
||||||
if (num_instances == 1) {
|
if (_sg.gl.cache.cur_pipeline->cmn.use_instanced_draw) {
|
||||||
glDrawElements(p_type, num_elements, i_type, indices);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (_sg.features.instancing) {
|
if (_sg.features.instancing) {
|
||||||
glDrawElementsInstanced(p_type, num_elements, i_type, indices, num_instances);
|
glDrawElementsInstanced(p_type, num_elements, i_type, indices, num_instances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
glDrawElements(p_type, num_elements, i_type, indices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* non-indexed rendering */
|
/* non-indexed rendering */
|
||||||
if (num_instances == 1) {
|
if (_sg.gl.cache.cur_pipeline->cmn.use_instanced_draw) {
|
||||||
glDrawArrays(p_type, base_element, num_elements);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (_sg.features.instancing) {
|
if (_sg.features.instancing) {
|
||||||
glDrawArraysInstanced(p_type, base_element, num_elements, num_instances);
|
glDrawArraysInstanced(p_type, base_element, num_elements, num_instances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
glDrawArrays(p_type, base_element, num_elements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8242,8 +8261,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_buffer(_sg_buffer_t* buf, cons
|
||||||
init_data_ptr = &init_data;
|
init_data_ptr = &init_data;
|
||||||
}
|
}
|
||||||
HRESULT hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &d3d11_desc, init_data_ptr, &buf->d3d11.buf);
|
HRESULT hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &d3d11_desc, init_data_ptr, &buf->d3d11.buf);
|
||||||
_SOKOL_UNUSED(hr);
|
if (!(SUCCEEDED(hr) && buf->d3d11.buf)) {
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && buf->d3d11.buf);
|
SOKOL_LOG("failed to create D3D11 buffer\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SG_RESOURCESTATE_VALID;
|
return SG_RESOURCESTATE_VALID;
|
||||||
}
|
}
|
||||||
|
@ -8289,7 +8310,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
SOKOL_ASSERT(!img->d3d11.tex2d && !img->d3d11.tex3d && !img->d3d11.texds && !img->d3d11.texmsaa);
|
SOKOL_ASSERT(!img->d3d11.tex2d && !img->d3d11.tex3d && !img->d3d11.texds && !img->d3d11.texmsaa);
|
||||||
SOKOL_ASSERT(!img->d3d11.srv && !img->d3d11.smp);
|
SOKOL_ASSERT(!img->d3d11.srv && !img->d3d11.smp);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
_SOKOL_UNUSED(hr);
|
|
||||||
|
|
||||||
_sg_image_common_init(&img->cmn, desc);
|
_sg_image_common_init(&img->cmn, desc);
|
||||||
const bool injected = (0 != desc->d3d11_texture) || (0 != desc->d3d11_shader_resource_view);
|
const bool injected = (0 != desc->d3d11_texture) || (0 != desc->d3d11_shader_resource_view);
|
||||||
|
@ -8316,7 +8336,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
d3d11_desc.SampleDesc.Count = (UINT)img->cmn.sample_count;
|
d3d11_desc.SampleDesc.Count = (UINT)img->cmn.sample_count;
|
||||||
d3d11_desc.SampleDesc.Quality = (UINT) (msaa ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0);
|
d3d11_desc.SampleDesc.Quality = (UINT) (msaa ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0);
|
||||||
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_desc, NULL, &img->d3d11.texds);
|
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_desc, NULL, &img->d3d11.texds);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.texds);
|
if (!(SUCCEEDED(hr) && img->d3d11.texds)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 texture 2D\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* create (or inject) color texture and shader-resource-view */
|
/* create (or inject) color texture and shader-resource-view */
|
||||||
|
@ -8386,7 +8409,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
d3d11_tex_desc.MiscFlags = (img->cmn.type == SG_IMAGETYPE_CUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
|
d3d11_tex_desc.MiscFlags = (img->cmn.type == SG_IMAGETYPE_CUBE) ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
|
||||||
|
|
||||||
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex2d);
|
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex2d);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.tex2d);
|
if (!(SUCCEEDED(hr) && img->d3d11.tex2d)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 texture 2D\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ...and similar, if not injected, create shader-resource-view */
|
/* ...and similar, if not injected, create shader-resource-view */
|
||||||
|
@ -8412,7 +8438,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
SOKOL_UNREACHABLE; break;
|
SOKOL_UNREACHABLE; break;
|
||||||
}
|
}
|
||||||
hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex2d, &d3d11_srv_desc, &img->d3d11.srv);
|
hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex2d, &d3d11_srv_desc, &img->d3d11.srv);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.srv);
|
if (!(SUCCEEDED(hr) && img->d3d11.srv)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 resource view\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -8459,7 +8488,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
return SG_RESOURCESTATE_FAILED;
|
return SG_RESOURCESTATE_FAILED;
|
||||||
}
|
}
|
||||||
hr = _sg_d3d11_CreateTexture3D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex3d);
|
hr = _sg_d3d11_CreateTexture3D(_sg.d3d11.dev, &d3d11_tex_desc, init_data, &img->d3d11.tex3d);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.tex3d);
|
if (!(SUCCEEDED(hr) && img->d3d11.tex3d)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 texture 3D\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == img->d3d11.srv) {
|
if (0 == img->d3d11.srv) {
|
||||||
|
@ -8469,7 +8501,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
d3d11_srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
||||||
d3d11_srv_desc.Texture3D.MipLevels = (UINT)img->cmn.num_mipmaps;
|
d3d11_srv_desc.Texture3D.MipLevels = (UINT)img->cmn.num_mipmaps;
|
||||||
hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex3d, &d3d11_srv_desc, &img->d3d11.srv);
|
hr = _sg_d3d11_CreateShaderResourceView(_sg.d3d11.dev, (ID3D11Resource*)img->d3d11.tex3d, &d3d11_srv_desc, &img->d3d11.srv);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.srv);
|
if (!(SUCCEEDED(hr) && img->d3d11.srv)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 resource view\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8488,7 +8523,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
d3d11_tex_desc.SampleDesc.Count = (UINT)img->cmn.sample_count;
|
d3d11_tex_desc.SampleDesc.Count = (UINT)img->cmn.sample_count;
|
||||||
d3d11_tex_desc.SampleDesc.Quality = (UINT)D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
d3d11_tex_desc.SampleDesc.Quality = (UINT)D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||||
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, NULL, &img->d3d11.texmsaa);
|
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &d3d11_tex_desc, NULL, &img->d3d11.texmsaa);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.texmsaa);
|
if (!(SUCCEEDED(hr) && img->d3d11.texmsaa)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 texture 2D\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sampler state object, note D3D11 implements an internal shared-pool for sampler objects */
|
/* sampler state object, note D3D11 implements an internal shared-pool for sampler objects */
|
||||||
|
@ -8517,7 +8555,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_image(_sg_image_t* img, const
|
||||||
d3d11_smp_desc.MinLOD = desc->min_lod;
|
d3d11_smp_desc.MinLOD = desc->min_lod;
|
||||||
d3d11_smp_desc.MaxLOD = desc->max_lod;
|
d3d11_smp_desc.MaxLOD = desc->max_lod;
|
||||||
hr = _sg_d3d11_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &img->d3d11.smp);
|
hr = _sg_d3d11_CreateSamplerState(_sg.d3d11.dev, &d3d11_smp_desc, &img->d3d11.smp);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && img->d3d11.smp);
|
if (!(SUCCEEDED(hr) && img->d3d11.smp)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 sampler state\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SG_RESOURCESTATE_VALID;
|
return SG_RESOURCESTATE_VALID;
|
||||||
}
|
}
|
||||||
|
@ -8609,7 +8650,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons
|
||||||
SOKOL_ASSERT(shd && desc);
|
SOKOL_ASSERT(shd && desc);
|
||||||
SOKOL_ASSERT(!shd->d3d11.vs && !shd->d3d11.fs && !shd->d3d11.vs_blob);
|
SOKOL_ASSERT(!shd->d3d11.vs && !shd->d3d11.fs && !shd->d3d11.vs_blob);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
_SOKOL_UNUSED(hr);
|
|
||||||
|
|
||||||
_sg_shader_common_init(&shd->cmn, desc);
|
_sg_shader_common_init(&shd->cmn, desc);
|
||||||
|
|
||||||
|
@ -8634,7 +8674,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_shader(_sg_shader_t* shd, cons
|
||||||
cb_desc.Usage = D3D11_USAGE_DEFAULT;
|
cb_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
cb_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
cb_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||||
hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &cb_desc, NULL, &d3d11_stage->cbufs[ub_index]);
|
hr = _sg_d3d11_CreateBuffer(_sg.d3d11.dev, &cb_desc, NULL, &d3d11_stage->cbufs[ub_index]);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && d3d11_stage->cbufs[ub_index]);
|
if (!(SUCCEEDED(hr) && d3d11_stage->cbufs[ub_index])) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 buffer\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8722,7 +8765,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip,
|
||||||
|
|
||||||
/* create input layout object */
|
/* create input layout object */
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
_SOKOL_UNUSED(hr);
|
|
||||||
D3D11_INPUT_ELEMENT_DESC d3d11_comps[SG_MAX_VERTEX_ATTRIBUTES];
|
D3D11_INPUT_ELEMENT_DESC d3d11_comps[SG_MAX_VERTEX_ATTRIBUTES];
|
||||||
memset(d3d11_comps, 0, sizeof(d3d11_comps));
|
memset(d3d11_comps, 0, sizeof(d3d11_comps));
|
||||||
int attr_index = 0;
|
int attr_index = 0;
|
||||||
|
@ -8744,6 +8786,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip,
|
||||||
d3d11_comp->InputSlotClass = _sg_d3d11_input_classification(step_func);
|
d3d11_comp->InputSlotClass = _sg_d3d11_input_classification(step_func);
|
||||||
if (SG_VERTEXSTEP_PER_INSTANCE == step_func) {
|
if (SG_VERTEXSTEP_PER_INSTANCE == step_func) {
|
||||||
d3d11_comp->InstanceDataStepRate = (UINT)step_rate;
|
d3d11_comp->InstanceDataStepRate = (UINT)step_rate;
|
||||||
|
pip->cmn.use_instanced_draw = true;
|
||||||
}
|
}
|
||||||
pip->cmn.vertex_layout_valid[a_desc->buffer_index] = true;
|
pip->cmn.vertex_layout_valid[a_desc->buffer_index] = true;
|
||||||
}
|
}
|
||||||
|
@ -8763,7 +8806,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip,
|
||||||
shd->d3d11.vs_blob, /* pShaderByteCodeWithInputSignature */
|
shd->d3d11.vs_blob, /* pShaderByteCodeWithInputSignature */
|
||||||
shd->d3d11.vs_blob_length, /* BytecodeLength */
|
shd->d3d11.vs_blob_length, /* BytecodeLength */
|
||||||
&pip->d3d11.il);
|
&pip->d3d11.il);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.il);
|
if (!(SUCCEEDED(hr) && pip->d3d11.il)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 input layout\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* create rasterizer state */
|
/* create rasterizer state */
|
||||||
D3D11_RASTERIZER_DESC rs_desc;
|
D3D11_RASTERIZER_DESC rs_desc;
|
||||||
|
@ -8779,7 +8825,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip,
|
||||||
rs_desc.MultisampleEnable = desc->sample_count > 1;
|
rs_desc.MultisampleEnable = desc->sample_count > 1;
|
||||||
rs_desc.AntialiasedLineEnable = FALSE;
|
rs_desc.AntialiasedLineEnable = FALSE;
|
||||||
hr = _sg_d3d11_CreateRasterizerState(_sg.d3d11.dev, &rs_desc, &pip->d3d11.rs);
|
hr = _sg_d3d11_CreateRasterizerState(_sg.d3d11.dev, &rs_desc, &pip->d3d11.rs);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.rs);
|
if (!(SUCCEEDED(hr) && pip->d3d11.rs)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 rasterizer state\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* create depth-stencil state */
|
/* create depth-stencil state */
|
||||||
D3D11_DEPTH_STENCIL_DESC dss_desc;
|
D3D11_DEPTH_STENCIL_DESC dss_desc;
|
||||||
|
@ -8801,7 +8850,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip,
|
||||||
dss_desc.BackFace.StencilPassOp = _sg_d3d11_stencil_op(sb->pass_op);
|
dss_desc.BackFace.StencilPassOp = _sg_d3d11_stencil_op(sb->pass_op);
|
||||||
dss_desc.BackFace.StencilFunc = _sg_d3d11_compare_func(sb->compare);
|
dss_desc.BackFace.StencilFunc = _sg_d3d11_compare_func(sb->compare);
|
||||||
hr = _sg_d3d11_CreateDepthStencilState(_sg.d3d11.dev, &dss_desc, &pip->d3d11.dss);
|
hr = _sg_d3d11_CreateDepthStencilState(_sg.d3d11.dev, &dss_desc, &pip->d3d11.dss);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.dss);
|
if (!(SUCCEEDED(hr) && pip->d3d11.dss)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 depth stencil state\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
/* create blend state */
|
/* create blend state */
|
||||||
D3D11_BLEND_DESC bs_desc;
|
D3D11_BLEND_DESC bs_desc;
|
||||||
|
@ -8832,7 +8884,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pipeline(_sg_pipeline_t* pip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hr = _sg_d3d11_CreateBlendState(_sg.d3d11.dev, &bs_desc, &pip->d3d11.bs);
|
hr = _sg_d3d11_CreateBlendState(_sg.d3d11.dev, &bs_desc, &pip->d3d11.bs);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && pip->d3d11.bs);
|
if (!(SUCCEEDED(hr) && pip->d3d11.bs)) {
|
||||||
|
SOKOL_LOG("failed to create D3D11 blend state\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
return SG_RESOURCESTATE_VALID;
|
return SG_RESOURCESTATE_VALID;
|
||||||
}
|
}
|
||||||
|
@ -8910,8 +8965,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pass(_sg_pass_t* pass, _sg_ima
|
||||||
}
|
}
|
||||||
SOKOL_ASSERT(d3d11_res);
|
SOKOL_ASSERT(d3d11_res);
|
||||||
HRESULT hr = _sg_d3d11_CreateRenderTargetView(_sg.d3d11.dev, d3d11_res, &d3d11_rtv_desc, &pass->d3d11.color_atts[i].rtv);
|
HRESULT hr = _sg_d3d11_CreateRenderTargetView(_sg.d3d11.dev, d3d11_res, &d3d11_rtv_desc, &pass->d3d11.color_atts[i].rtv);
|
||||||
_SOKOL_UNUSED(hr);
|
if (!(SUCCEEDED(hr) && pass->d3d11.color_atts[i].rtv)) {
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && pass->d3d11.color_atts[i].rtv);
|
SOKOL_LOG("failed to create D3D11 render target view\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* optional depth-stencil image */
|
/* optional depth-stencil image */
|
||||||
|
@ -8941,8 +8998,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_d3d11_create_pass(_sg_pass_t* pass, _sg_ima
|
||||||
ID3D11Resource* d3d11_res = (ID3D11Resource*) att_img->d3d11.texds;
|
ID3D11Resource* d3d11_res = (ID3D11Resource*) att_img->d3d11.texds;
|
||||||
SOKOL_ASSERT(d3d11_res);
|
SOKOL_ASSERT(d3d11_res);
|
||||||
HRESULT hr = _sg_d3d11_CreateDepthStencilView(_sg.d3d11.dev, d3d11_res, &d3d11_dsv_desc, &pass->d3d11.ds_att.dsv);
|
HRESULT hr = _sg_d3d11_CreateDepthStencilView(_sg.d3d11.dev, d3d11_res, &d3d11_dsv_desc, &pass->d3d11.ds_att.dsv);
|
||||||
_SOKOL_UNUSED(hr);
|
if (!(SUCCEEDED(hr) && pass->d3d11.ds_att.dsv)) {
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr) && pass->d3d11.ds_att.dsv);
|
SOKOL_LOG("failed to create D3D11 depth stencil view\n");
|
||||||
|
return SG_RESOURCESTATE_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SG_RESOURCESTATE_VALID;
|
return SG_RESOURCESTATE_VALID;
|
||||||
}
|
}
|
||||||
|
@ -9124,6 +9183,7 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) {
|
||||||
_sg.d3d11.cur_pipeline = pip;
|
_sg.d3d11.cur_pipeline = pip;
|
||||||
_sg.d3d11.cur_pipeline_id.id = pip->slot.id;
|
_sg.d3d11.cur_pipeline_id.id = pip->slot.id;
|
||||||
_sg.d3d11.use_indexed_draw = (pip->d3d11.index_format != DXGI_FORMAT_UNKNOWN);
|
_sg.d3d11.use_indexed_draw = (pip->d3d11.index_format != DXGI_FORMAT_UNKNOWN);
|
||||||
|
_sg.d3d11.use_instanced_draw = pip->cmn.use_instanced_draw;
|
||||||
|
|
||||||
_sg_d3d11_RSSetState(_sg.d3d11.ctx, pip->d3d11.rs);
|
_sg_d3d11_RSSetState(_sg.d3d11.ctx, pip->d3d11.rs);
|
||||||
_sg_d3d11_OMSetDepthStencilState(_sg.d3d11.ctx, pip->d3d11.dss, pip->d3d11.stencil_ref);
|
_sg_d3d11_OMSetDepthStencilState(_sg.d3d11.ctx, pip->d3d11.dss, pip->d3d11.stencil_ref);
|
||||||
|
@ -9208,19 +9268,19 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub
|
||||||
_SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_instances) {
|
_SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_instances) {
|
||||||
SOKOL_ASSERT(_sg.d3d11.in_pass);
|
SOKOL_ASSERT(_sg.d3d11.in_pass);
|
||||||
if (_sg.d3d11.use_indexed_draw) {
|
if (_sg.d3d11.use_indexed_draw) {
|
||||||
if (1 == num_instances) {
|
if (_sg.d3d11.use_instanced_draw) {
|
||||||
_sg_d3d11_DrawIndexed(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element, 0);
|
_sg_d3d11_DrawIndexedInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_sg_d3d11_DrawIndexedInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0, 0);
|
_sg_d3d11_DrawIndexed(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (1 == num_instances) {
|
if (_sg.d3d11.use_instanced_draw) {
|
||||||
_sg_d3d11_Draw(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element);
|
_sg_d3d11_DrawInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_sg_d3d11_DrawInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0);
|
_sg_d3d11_Draw(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9235,10 +9295,12 @@ _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* d
|
||||||
SOKOL_ASSERT(buf->d3d11.buf);
|
SOKOL_ASSERT(buf->d3d11.buf);
|
||||||
D3D11_MAPPED_SUBRESOURCE d3d11_msr;
|
D3D11_MAPPED_SUBRESOURCE d3d11_msr;
|
||||||
HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
|
HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
|
||||||
_SOKOL_UNUSED(hr);
|
if (SUCCEEDED(hr)) {
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
memcpy(d3d11_msr.pData, data->ptr, data->size);
|
||||||
memcpy(d3d11_msr.pData, data->ptr, data->size);
|
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);
|
||||||
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);
|
} else {
|
||||||
|
SOKOL_LOG("failed to map buffer while updating!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE int _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {
|
_SOKOL_PRIVATE int _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) {
|
||||||
|
@ -9248,12 +9310,14 @@ _SOKOL_PRIVATE int _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* da
|
||||||
D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
|
D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||||
D3D11_MAPPED_SUBRESOURCE d3d11_msr;
|
D3D11_MAPPED_SUBRESOURCE d3d11_msr;
|
||||||
HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr);
|
HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr);
|
||||||
_SOKOL_UNUSED(hr);
|
if (SUCCEEDED(hr)) {
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData + buf->cmn.append_pos;
|
||||||
uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData + buf->cmn.append_pos;
|
memcpy(dst_ptr, data->ptr, data->size);
|
||||||
memcpy(dst_ptr, data->ptr, data->size);
|
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);
|
||||||
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0);
|
} else {
|
||||||
/* NOTE: this is a requirement from WebGPU, but we want identical behaviour across all backend */
|
SOKOL_LOG("failed to map buffer while appending!\n");
|
||||||
|
}
|
||||||
|
/* NOTE: this alignment is a requirement from WebGPU, but we want identical behaviour across all backend */
|
||||||
return _sg_roundup((int)data->size, 4);
|
return _sg_roundup((int)data->size, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9273,7 +9337,6 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data
|
||||||
const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices:1;
|
const int num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices:1;
|
||||||
UINT subres_index = 0;
|
UINT subres_index = 0;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
_SOKOL_UNUSED(hr);
|
|
||||||
D3D11_MAPPED_SUBRESOURCE d3d11_msr;
|
D3D11_MAPPED_SUBRESOURCE d3d11_msr;
|
||||||
for (int face_index = 0; face_index < num_faces; face_index++) {
|
for (int face_index = 0; face_index < num_faces; face_index++) {
|
||||||
for (int slice_index = 0; slice_index < num_slices; slice_index++) {
|
for (int slice_index = 0; slice_index < num_slices; slice_index++) {
|
||||||
|
@ -9287,22 +9350,25 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data
|
||||||
const size_t slice_offset = slice_size * (size_t)slice_index;
|
const size_t slice_offset = slice_size * (size_t)slice_index;
|
||||||
const uint8_t* slice_ptr = ((const uint8_t*)subimg_data->ptr) + slice_offset;
|
const uint8_t* slice_ptr = ((const uint8_t*)subimg_data->ptr) + slice_offset;
|
||||||
hr = _sg_d3d11_Map(_sg.d3d11.ctx, d3d11_res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
|
hr = _sg_d3d11_Map(_sg.d3d11.ctx, d3d11_res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr);
|
||||||
SOKOL_ASSERT(SUCCEEDED(hr));
|
if (SUCCEEDED(hr)) {
|
||||||
/* FIXME: need to handle difference in depth-pitch for 3D textures as well! */
|
/* FIXME: need to handle difference in depth-pitch for 3D textures as well! */
|
||||||
if (src_pitch == (int)d3d11_msr.RowPitch) {
|
if (src_pitch == (int)d3d11_msr.RowPitch) {
|
||||||
memcpy(d3d11_msr.pData, slice_ptr, slice_size);
|
memcpy(d3d11_msr.pData, slice_ptr, slice_size);
|
||||||
}
|
|
||||||
else {
|
|
||||||
SOKOL_ASSERT(src_pitch < (int)d3d11_msr.RowPitch);
|
|
||||||
const uint8_t* src_ptr = slice_ptr;
|
|
||||||
uint8_t* dst_ptr = (uint8_t*) d3d11_msr.pData;
|
|
||||||
for (int row_index = 0; row_index < mip_height; row_index++) {
|
|
||||||
memcpy(dst_ptr, src_ptr, (size_t)src_pitch);
|
|
||||||
src_ptr += src_pitch;
|
|
||||||
dst_ptr += d3d11_msr.RowPitch;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
SOKOL_ASSERT(src_pitch < (int)d3d11_msr.RowPitch);
|
||||||
|
const uint8_t* src_ptr = slice_ptr;
|
||||||
|
uint8_t* dst_ptr = (uint8_t*) d3d11_msr.pData;
|
||||||
|
for (int row_index = 0; row_index < mip_height; row_index++) {
|
||||||
|
memcpy(dst_ptr, src_ptr, (size_t)src_pitch);
|
||||||
|
src_ptr += src_pitch;
|
||||||
|
dst_ptr += d3d11_msr.RowPitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_sg_d3d11_Unmap(_sg.d3d11.ctx, d3d11_res, subres_index);
|
||||||
|
} else {
|
||||||
|
SOKOL_LOG("failed to map texture!\n");
|
||||||
}
|
}
|
||||||
_sg_d3d11_Unmap(_sg.d3d11.ctx, d3d11_res, subres_index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10110,22 +10176,31 @@ _SOKOL_PRIVATE void _sg_mtl_copy_image_data(const _sg_image_t* img, __unsafe_unr
|
||||||
const uint8_t* data_ptr = (const uint8_t*)data->subimage[face_index][mip_index].ptr;
|
const uint8_t* data_ptr = (const uint8_t*)data->subimage[face_index][mip_index].ptr;
|
||||||
const int mip_width = _sg_max(img->cmn.width >> mip_index, 1);
|
const int mip_width = _sg_max(img->cmn.width >> mip_index, 1);
|
||||||
const int mip_height = _sg_max(img->cmn.height >> mip_index, 1);
|
const int mip_height = _sg_max(img->cmn.height >> mip_index, 1);
|
||||||
/* special case PVRTC formats: bytePerRow must be 0 */
|
/* special case PVRTC formats: bytePerRow and bytesPerImage must be 0 */
|
||||||
int bytes_per_row = 0;
|
int bytes_per_row = 0;
|
||||||
int bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);
|
int bytes_per_slice = 0;
|
||||||
if (!_sg_mtl_is_pvrtc(img->cmn.pixel_format)) {
|
if (!_sg_mtl_is_pvrtc(img->cmn.pixel_format)) {
|
||||||
bytes_per_row = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1);
|
bytes_per_row = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1);
|
||||||
|
bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);
|
||||||
}
|
}
|
||||||
|
/* bytesPerImage special case: https://developer.apple.com/documentation/metal/mtltexture/1515679-replaceregion
|
||||||
|
|
||||||
|
"Supply a nonzero value only when you copy data to a MTLTextureType3D type texture"
|
||||||
|
*/
|
||||||
MTLRegion region;
|
MTLRegion region;
|
||||||
|
int bytes_per_image;
|
||||||
if (img->cmn.type == SG_IMAGETYPE_3D) {
|
if (img->cmn.type == SG_IMAGETYPE_3D) {
|
||||||
const int mip_depth = _sg_max(img->cmn.num_slices >> mip_index, 1);
|
const int mip_depth = _sg_max(img->cmn.num_slices >> mip_index, 1);
|
||||||
region = MTLRegionMake3D(0, 0, 0, (NSUInteger)mip_width, (NSUInteger)mip_height, (NSUInteger)mip_depth);
|
region = MTLRegionMake3D(0, 0, 0, (NSUInteger)mip_width, (NSUInteger)mip_height, (NSUInteger)mip_depth);
|
||||||
|
bytes_per_image = bytes_per_slice;
|
||||||
/* FIXME: apparently the minimal bytes_per_image size for 3D texture
|
/* FIXME: apparently the minimal bytes_per_image size for 3D texture
|
||||||
is 4 KByte... somehow need to handle this */
|
is 4 KByte... somehow need to handle this */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
region = MTLRegionMake2D(0, 0, (NSUInteger)mip_width, (NSUInteger)mip_height);
|
region = MTLRegionMake2D(0, 0, (NSUInteger)mip_width, (NSUInteger)mip_height);
|
||||||
|
bytes_per_image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int slice_index = 0; slice_index < num_slices; slice_index++) {
|
for (int slice_index = 0; slice_index < num_slices; slice_index++) {
|
||||||
const int mtl_slice_index = (img->cmn.type == SG_IMAGETYPE_CUBE) ? face_index : slice_index;
|
const int mtl_slice_index = (img->cmn.type == SG_IMAGETYPE_CUBE) ? face_index : slice_index;
|
||||||
const int slice_offset = slice_index * bytes_per_slice;
|
const int slice_offset = slice_index * bytes_per_slice;
|
||||||
|
@ -10135,7 +10210,7 @@ _SOKOL_PRIVATE void _sg_mtl_copy_image_data(const _sg_image_t* img, __unsafe_unr
|
||||||
slice:(NSUInteger)mtl_slice_index
|
slice:(NSUInteger)mtl_slice_index
|
||||||
withBytes:data_ptr + slice_offset
|
withBytes:data_ptr + slice_offset
|
||||||
bytesPerRow:(NSUInteger)bytes_per_row
|
bytesPerRow:(NSUInteger)bytes_per_row
|
||||||
bytesPerImage:(NSUInteger)bytes_per_slice];
|
bytesPerImage:(NSUInteger)bytes_per_image];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10431,6 +10506,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pipeline(_sg_pipeline_t* pip, _s
|
||||||
vtx_desc.layouts[mtl_vb_slot].stride = (NSUInteger)l_desc->stride;
|
vtx_desc.layouts[mtl_vb_slot].stride = (NSUInteger)l_desc->stride;
|
||||||
vtx_desc.layouts[mtl_vb_slot].stepFunction = _sg_mtl_step_function(l_desc->step_func);
|
vtx_desc.layouts[mtl_vb_slot].stepFunction = _sg_mtl_step_function(l_desc->step_func);
|
||||||
vtx_desc.layouts[mtl_vb_slot].stepRate = (NSUInteger)l_desc->step_rate;
|
vtx_desc.layouts[mtl_vb_slot].stepRate = (NSUInteger)l_desc->step_rate;
|
||||||
|
if (SG_VERTEXSTEP_PER_INSTANCE == l_desc->step_func) {
|
||||||
|
// NOTE: not actually used in _sg_mtl_draw()
|
||||||
|
pip->cmn.use_instanced_draw = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13563,6 +13642,10 @@ _SOKOL_PRIVATE const char* _sg_validate_string(_sg_validate_error_t err) {
|
||||||
case _SG_VALIDATE_BUFFERDESC_DATA_SIZE: return "immutable buffer data size differs from buffer size";
|
case _SG_VALIDATE_BUFFERDESC_DATA_SIZE: return "immutable buffer data size differs from buffer size";
|
||||||
case _SG_VALIDATE_BUFFERDESC_NO_DATA: return "dynamic/stream usage buffers cannot be initialized with data";
|
case _SG_VALIDATE_BUFFERDESC_NO_DATA: return "dynamic/stream usage buffers cannot be initialized with data";
|
||||||
|
|
||||||
|
/* image data (in image creation and updating) */
|
||||||
|
case _SG_VALIDATE_IMAGEDATA_NODATA: return "sg_image_data: no data (.ptr and/or .size is zero)";
|
||||||
|
case _SG_VALIDATE_IMAGEDATA_DATA_SIZE: return "sg_image_data: data size doesn't match expected surface size";
|
||||||
|
|
||||||
/* image creation validation errros */
|
/* image creation validation errros */
|
||||||
case _SG_VALIDATE_IMAGEDESC_CANARY: return "sg_image_desc not initialized";
|
case _SG_VALIDATE_IMAGEDESC_CANARY: return "sg_image_desc not initialized";
|
||||||
case _SG_VALIDATE_IMAGEDESC_WIDTH: return "sg_image_desc.width must be > 0";
|
case _SG_VALIDATE_IMAGEDESC_WIDTH: return "sg_image_desc.width must be > 0";
|
||||||
|
@ -13573,8 +13656,9 @@ _SOKOL_PRIVATE const char* _sg_validate_string(_sg_validate_error_t err) {
|
||||||
case _SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT: return "MSAA not supported for this pixel format";
|
case _SG_VALIDATE_IMAGEDESC_NO_MSAA_RT_SUPPORT: return "MSAA not supported for this pixel format";
|
||||||
case _SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE: return "render target images must be SG_USAGE_IMMUTABLE";
|
case _SG_VALIDATE_IMAGEDESC_RT_IMMUTABLE: return "render target images must be SG_USAGE_IMMUTABLE";
|
||||||
case _SG_VALIDATE_IMAGEDESC_RT_NO_DATA: return "render target images cannot be initialized with data";
|
case _SG_VALIDATE_IMAGEDESC_RT_NO_DATA: return "render target images cannot be initialized with data";
|
||||||
case _SG_VALIDATE_IMAGEDESC_DATA: return "missing or invalid data for immutable image";
|
case _SG_VALIDATE_IMAGEDESC_INJECTED_NO_DATA: return "images with injected textures cannot be initialized with data";
|
||||||
case _SG_VALIDATE_IMAGEDESC_NO_DATA: return "dynamic/stream usage images cannot be initialized with data";
|
case _SG_VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA: return "dynamic/stream images cannot be initialized with data";
|
||||||
|
case _SG_VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE: return "compressed images must be immutable";
|
||||||
|
|
||||||
/* shader creation */
|
/* shader creation */
|
||||||
case _SG_VALIDATE_SHADERDESC_CANARY: return "sg_shader_desc not initialized";
|
case _SG_VALIDATE_SHADERDESC_CANARY: return "sg_shader_desc not initialized";
|
||||||
|
@ -13669,9 +13753,6 @@ _SOKOL_PRIVATE const char* _sg_validate_string(_sg_validate_error_t err) {
|
||||||
|
|
||||||
/* sg_update_image */
|
/* sg_update_image */
|
||||||
case _SG_VALIDATE_UPDIMG_USAGE: return "sg_update_image: cannot update immutable image";
|
case _SG_VALIDATE_UPDIMG_USAGE: return "sg_update_image: cannot update immutable image";
|
||||||
case _SG_VALIDATE_UPDIMG_NOTENOUGHDATA: return "sg_update_image: not enough subimage data provided";
|
|
||||||
case _SG_VALIDATE_UPDIMG_SIZE: return "sg_update_image: provided subimage data size too big";
|
|
||||||
case _SG_VALIDATE_UPDIMG_COMPRESSED: return "sg_update_image: cannot update images with compressed format";
|
|
||||||
case _SG_VALIDATE_UPDIMG_ONCE: return "sg_update_image: only one update allowed per image and frame";
|
case _SG_VALIDATE_UPDIMG_ONCE: return "sg_update_image: only one update allowed per image and frame";
|
||||||
|
|
||||||
default: return "unknown validation error";
|
default: return "unknown validation error";
|
||||||
|
@ -13695,7 +13776,7 @@ _SOKOL_PRIVATE void _sg_validate(bool cond, _sg_validate_error_t err) {
|
||||||
_SOKOL_PRIVATE bool _sg_validate_end(void) {
|
_SOKOL_PRIVATE bool _sg_validate_end(void) {
|
||||||
if (_sg.validate_error != _SG_VALIDATE_SUCCESS) {
|
if (_sg.validate_error != _SG_VALIDATE_SUCCESS) {
|
||||||
#if !defined(SOKOL_VALIDATE_NON_FATAL)
|
#if !defined(SOKOL_VALIDATE_NON_FATAL)
|
||||||
SOKOL_LOG("^^^^ VALIDATION FAILED, TERMINATING ^^^^");
|
SOKOL_LOG("^^^^ SOKOL-GFX VALIDATION FAILED, TERMINATING ^^^^");
|
||||||
SOKOL_ASSERT(false);
|
SOKOL_ASSERT(false);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
@ -13731,6 +13812,31 @@ _SOKOL_PRIVATE bool _sg_validate_buffer_desc(const sg_buffer_desc* desc) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_SOKOL_PRIVATE void _sg_validate_image_data(const sg_image_data* data, sg_pixel_format fmt, int width, int height, int num_faces, int num_mips, int num_slices) {
|
||||||
|
#if !defined(SOKOL_DEBUG)
|
||||||
|
_SOKOL_UNUSED(data);
|
||||||
|
_SOKOL_UNUSED(fmt);
|
||||||
|
_SOKOL_UNUSED(width);
|
||||||
|
_SOKOL_UNUSED(height);
|
||||||
|
_SOKOL_UNUSED(num_faces);
|
||||||
|
_SOKOL_UNUSED(num_mips);
|
||||||
|
_SOKOL_UNUSED(num_slices);
|
||||||
|
#else
|
||||||
|
for (int face_index = 0; face_index < num_faces; face_index++) {
|
||||||
|
for (int mip_index = 0; mip_index < num_mips; mip_index++) {
|
||||||
|
const bool has_data = data->subimage[face_index][mip_index].ptr != 0;
|
||||||
|
const bool has_size = data->subimage[face_index][mip_index].size > 0;
|
||||||
|
SOKOL_VALIDATE(has_data && has_size, _SG_VALIDATE_IMAGEDATA_NODATA);
|
||||||
|
const int mip_width = _sg_max(width >> mip_index, 1);
|
||||||
|
const int mip_height = _sg_max(height >> mip_index, 1);
|
||||||
|
const int bytes_per_slice = _sg_surface_pitch(fmt, mip_width, mip_height, 1);
|
||||||
|
const int expected_size = bytes_per_slice * num_slices;
|
||||||
|
SOKOL_VALIDATE(expected_size == (int)data->subimage[face_index][mip_index].size, _SG_VALIDATE_IMAGEDATA_DATA_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
_SOKOL_PRIVATE bool _sg_validate_image_desc(const sg_image_desc* desc) {
|
_SOKOL_PRIVATE bool _sg_validate_image_desc(const sg_image_desc* desc) {
|
||||||
#if !defined(SOKOL_DEBUG)
|
#if !defined(SOKOL_DEBUG)
|
||||||
_SOKOL_UNUSED(desc);
|
_SOKOL_UNUSED(desc);
|
||||||
|
@ -13768,24 +13874,33 @@ _SOKOL_PRIVATE bool _sg_validate_image_desc(const sg_image_desc* desc) {
|
||||||
SOKOL_VALIDATE(desc->sample_count <= 1, _SG_VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT);
|
SOKOL_VALIDATE(desc->sample_count <= 1, _SG_VALIDATE_IMAGEDESC_MSAA_BUT_NO_RT);
|
||||||
const bool valid_nonrt_fmt = !_sg_is_valid_rendertarget_depth_format(fmt);
|
const bool valid_nonrt_fmt = !_sg_is_valid_rendertarget_depth_format(fmt);
|
||||||
SOKOL_VALIDATE(valid_nonrt_fmt, _SG_VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT);
|
SOKOL_VALIDATE(valid_nonrt_fmt, _SG_VALIDATE_IMAGEDESC_NONRT_PIXELFORMAT);
|
||||||
/* FIXME: should use the same "expected size" computation as in _sg_validate_update_image() here */
|
const bool is_compressed = _sg_is_compressed_pixel_format(desc->pixel_format);
|
||||||
if (!injected && (usage == SG_USAGE_IMMUTABLE)) {
|
const bool is_immutable = (usage == SG_USAGE_IMMUTABLE);
|
||||||
const int num_faces = desc->type == SG_IMAGETYPE_CUBE ? 6:1;
|
if (is_compressed) {
|
||||||
const int num_mips = desc->num_mipmaps;
|
SOKOL_VALIDATE(is_immutable, _SG_VALIDATE_IMAGEDESC_COMPRESSED_IMMUTABLE);
|
||||||
for (int face_index = 0; face_index < num_faces; face_index++) {
|
}
|
||||||
for (int mip_index = 0; mip_index < num_mips; mip_index++) {
|
if (!injected && is_immutable) {
|
||||||
const bool has_data = desc->data.subimage[face_index][mip_index].ptr != 0;
|
// image desc must have valid data
|
||||||
const bool has_size = desc->data.subimage[face_index][mip_index].size > 0;
|
_sg_validate_image_data(&desc->data,
|
||||||
SOKOL_VALIDATE(has_data && has_size, _SG_VALIDATE_IMAGEDESC_DATA);
|
desc->pixel_format,
|
||||||
}
|
desc->width,
|
||||||
}
|
desc->height,
|
||||||
|
(desc->type == SG_IMAGETYPE_CUBE) ? 6 : 1,
|
||||||
|
desc->num_mipmaps,
|
||||||
|
desc->num_slices);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// image desc must not have data
|
||||||
for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) {
|
for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) {
|
||||||
for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) {
|
for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) {
|
||||||
const bool no_data = 0 == desc->data.subimage[face_index][mip_index].ptr;
|
const bool no_data = 0 == desc->data.subimage[face_index][mip_index].ptr;
|
||||||
const bool no_size = 0 == desc->data.subimage[face_index][mip_index].size;
|
const bool no_size = 0 == desc->data.subimage[face_index][mip_index].size;
|
||||||
SOKOL_VALIDATE(no_data && no_size, _SG_VALIDATE_IMAGEDESC_NO_DATA);
|
if (injected) {
|
||||||
|
SOKOL_VALIDATE(no_data && no_size, _SG_VALIDATE_IMAGEDESC_INJECTED_NO_DATA);
|
||||||
|
}
|
||||||
|
if (!is_immutable) {
|
||||||
|
SOKOL_VALIDATE(no_data && no_size, _SG_VALIDATE_IMAGEDESC_DYNAMIC_NO_DATA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13866,6 +13981,9 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) {
|
||||||
#if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
|
#if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
|
||||||
SOKOL_VALIDATE((size_t)uniform_offset == ub_desc->size, _SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH);
|
SOKOL_VALIDATE((size_t)uniform_offset == ub_desc->size, _SG_VALIDATE_SHADERDESC_UB_SIZE_MISMATCH);
|
||||||
SOKOL_VALIDATE(num_uniforms > 0, _SG_VALIDATE_SHADERDESC_NO_UB_MEMBERS);
|
SOKOL_VALIDATE(num_uniforms > 0, _SG_VALIDATE_SHADERDESC_NO_UB_MEMBERS);
|
||||||
|
#else
|
||||||
|
_SOKOL_UNUSED(uniform_offset);
|
||||||
|
_SOKOL_UNUSED(num_uniforms);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -14233,19 +14351,13 @@ _SOKOL_PRIVATE bool _sg_validate_update_image(const _sg_image_t* img, const sg_i
|
||||||
SOKOL_VALIDATE_BEGIN();
|
SOKOL_VALIDATE_BEGIN();
|
||||||
SOKOL_VALIDATE(img->cmn.usage != SG_USAGE_IMMUTABLE, _SG_VALIDATE_UPDIMG_USAGE);
|
SOKOL_VALIDATE(img->cmn.usage != SG_USAGE_IMMUTABLE, _SG_VALIDATE_UPDIMG_USAGE);
|
||||||
SOKOL_VALIDATE(img->cmn.upd_frame_index != _sg.frame_index, _SG_VALIDATE_UPDIMG_ONCE);
|
SOKOL_VALIDATE(img->cmn.upd_frame_index != _sg.frame_index, _SG_VALIDATE_UPDIMG_ONCE);
|
||||||
SOKOL_VALIDATE(!_sg_is_compressed_pixel_format(img->cmn.pixel_format), _SG_VALIDATE_UPDIMG_COMPRESSED);
|
_sg_validate_image_data(data,
|
||||||
const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6 : 1;
|
img->cmn.pixel_format,
|
||||||
const int num_mips = img->cmn.num_mipmaps;
|
img->cmn.width,
|
||||||
for (int face_index = 0; face_index < num_faces; face_index++) {
|
img->cmn.height,
|
||||||
for (int mip_index = 0; mip_index < num_mips; mip_index++) {
|
(img->cmn.type == SG_IMAGETYPE_CUBE) ? 6 : 1,
|
||||||
SOKOL_VALIDATE(0 != data->subimage[face_index][mip_index].ptr, _SG_VALIDATE_UPDIMG_NOTENOUGHDATA);
|
img->cmn.num_mipmaps,
|
||||||
const int mip_width = _sg_max(img->cmn.width >> mip_index, 1);
|
img->cmn.num_slices);
|
||||||
const int mip_height = _sg_max(img->cmn.height >> mip_index, 1);
|
|
||||||
const int bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, 1);
|
|
||||||
const int expected_size = bytes_per_slice * img->cmn.num_slices;
|
|
||||||
SOKOL_VALIDATE(data->subimage[face_index][mip_index].size <= (size_t)expected_size, _SG_VALIDATE_UPDIMG_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SOKOL_VALIDATE_END();
|
return SOKOL_VALIDATE_END();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -768,7 +768,6 @@ pub fn (ctx &Context) draw_slice_empty(x f32, y f32, r f32, start_angle f32, arc
|
||||||
pub fn (mut ctx Context) resize(width int, height int) {
|
pub fn (mut ctx Context) resize(width int, height int) {
|
||||||
ctx.width = width
|
ctx.width = width
|
||||||
ctx.height = height
|
ctx.height = height
|
||||||
// C.sapp_resize_window(width, height)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draws a line between the points provided
|
// Draws a line between the points provided
|
||||||
|
|
|
@ -53,6 +53,8 @@ fn C.saudio_buffer_frames() int
|
||||||
|
|
||||||
fn C.saudio_channels() int
|
fn C.saudio_channels() int
|
||||||
|
|
||||||
|
fn C.saudio_suspended() bool
|
||||||
|
|
||||||
fn C.saudio_expect() int
|
fn C.saudio_expect() int
|
||||||
|
|
||||||
fn C.saudio_push(frames &f32, num_frames int) int
|
fn C.saudio_push(frames &f32, num_frames int) int
|
||||||
|
@ -97,6 +99,12 @@ pub fn channels() int {
|
||||||
return C.saudio_channels()
|
return C.saudio_channels()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// suspended returns true if audio context is currently suspended
|
||||||
|
// (only in WebAudio backend, all other backends return false)
|
||||||
|
pub fn suspended() bool {
|
||||||
|
return C.saudio_suspended()
|
||||||
|
}
|
||||||
|
|
||||||
// audio.expect - get current number of frames to fill packet queue; use in combination with audio.push/2
|
// audio.expect - get current number of frames to fill packet queue; use in combination with audio.push/2
|
||||||
pub fn expect() int {
|
pub fn expect() int {
|
||||||
return C.saudio_expect()
|
return C.saudio_expect()
|
||||||
|
|
|
@ -136,6 +136,12 @@ pub fn frame_count() u64 {
|
||||||
return C.sapp_frame_count()
|
return C.sapp_frame_count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get an averaged/smoothed frame duration in seconds
|
||||||
|
[inline]
|
||||||
|
pub fn frame_duration() f64 {
|
||||||
|
return C.sapp_frame_duration()
|
||||||
|
}
|
||||||
|
|
||||||
// write string into clipboard
|
// write string into clipboard
|
||||||
[inline]
|
[inline]
|
||||||
pub fn set_clipboard_string(str &char) {
|
pub fn set_clipboard_string(str &char) {
|
||||||
|
|
|
@ -56,6 +56,9 @@ fn C.sapp_consume_event()
|
||||||
// get the current frame counter (for comparison with sapp_event.frame_count)
|
// get the current frame counter (for comparison with sapp_event.frame_count)
|
||||||
fn C.sapp_frame_count() u64
|
fn C.sapp_frame_count() u64
|
||||||
|
|
||||||
|
// get an averaged/smoothed frame duration in seconds
|
||||||
|
fn C.sapp_frame_duration() f64
|
||||||
|
|
||||||
// write string into clipboard
|
// write string into clipboard
|
||||||
fn C.sapp_set_clipboard_string(str &byte)
|
fn C.sapp_set_clipboard_string(str &byte)
|
||||||
|
|
||||||
|
@ -115,5 +118,3 @@ fn C.sapp_get_num_dropped_files() int
|
||||||
|
|
||||||
// Get the file path of the droped file
|
// Get the file path of the droped file
|
||||||
fn C.sapp_get_dropped_file_path(int) &byte
|
fn C.sapp_get_dropped_file_path(int) &byte
|
||||||
|
|
||||||
fn C.sapp_resize_window(int, int)
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module sgl
|
module sgl
|
||||||
|
|
||||||
// Error is C.sgl_error_t
|
// SglError is C.sgl_error_t
|
||||||
pub enum SglError {
|
pub enum SglError {
|
||||||
no_error = C.SGL_NO_ERROR // 0
|
no_error = C.SGL_NO_ERROR // 0
|
||||||
vertices_full = C.SGL_ERROR_VERTICES_FULL
|
vertices_full = C.SGL_ERROR_VERTICES_FULL
|
||||||
|
|
|
@ -254,6 +254,11 @@ pub fn c1i(rgba u32) {
|
||||||
C.sgl_c1i(rgba)
|
C.sgl_c1i(rgba)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn point_size(s f32) {
|
||||||
|
C.sgl_point_size(s)
|
||||||
|
}
|
||||||
|
|
||||||
// define primitives, each begin/end is one draw command
|
// define primitives, each begin/end is one draw command
|
||||||
[inline]
|
[inline]
|
||||||
pub fn begin_points() {
|
pub fn begin_points() {
|
||||||
|
|
|
@ -62,6 +62,7 @@ fn C.sgl_c4f(r f32, g f32, b f32, a f32)
|
||||||
fn C.sgl_c3b(r byte, g byte, b byte)
|
fn C.sgl_c3b(r byte, g byte, b byte)
|
||||||
fn C.sgl_c4b(r byte, g byte, b byte, a byte)
|
fn C.sgl_c4b(r byte, g byte, b byte, a byte)
|
||||||
fn C.sgl_c1i(rgba u32)
|
fn C.sgl_c1i(rgba u32)
|
||||||
|
fn C.sgl_point_size(s f32)
|
||||||
|
|
||||||
// define primitives, each begin/end is one draw command
|
// define primitives, each begin/end is one draw command
|
||||||
fn C.sgl_begin_points()
|
fn C.sgl_begin_points()
|
||||||
|
|
Loading…
Reference in New Issue