mirror of
https://github.com/raysan5/raylib.git
synced 2026-05-25 14:10:27 -04:00
Compare commits
3 Commits
95bfa196fd
...
b2ea5eae5e
| Author | SHA1 | Date | |
|---|---|---|---|
| b2ea5eae5e | |||
| 29ff1f02e9 | |||
| d840a100a7 |
@ -7,6 +7,30 @@ if(POLICY CMP0072)
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
function(raylib_check_libatomic_required result)
|
||||
set(_atomic_test_source "
|
||||
int main(void)
|
||||
{
|
||||
volatile long long value = 0;
|
||||
return (int)__atomic_fetch_add(&value, 1, __ATOMIC_SEQ_CST);
|
||||
}")
|
||||
|
||||
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||
|
||||
if (RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||
set(${result} FALSE PARENT_SCOPE)
|
||||
else ()
|
||||
cmake_push_check_state()
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
|
||||
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITH_LIBATOMIC)
|
||||
cmake_pop_check_state()
|
||||
set(${result} ${RAYLIB_ATOMICS_WITH_LIBATOMIC} PARENT_SCOPE)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)")
|
||||
|
||||
if (${PLATFORM} STREQUAL "Desktop")
|
||||
@ -222,6 +246,14 @@ endif ()
|
||||
|
||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
|
||||
|
||||
if (SUPPORT_MODULE_RAUDIO AND UNIX AND NOT APPLE)
|
||||
raylib_check_libatomic_required(RAYLIB_LIBATOMIC_REQUIRED)
|
||||
if (RAYLIB_LIBATOMIC_REQUIRED)
|
||||
message(STATUS "64-bit atomics require libatomic")
|
||||
list(APPEND LIBS_PRIVATE atomic)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (${PLATFORM} MATCHES "Desktop")
|
||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
|
||||
endif ()
|
||||
|
||||
@ -117,8 +117,7 @@ RAYLIB_MODULE_RAYGUI_PATH ?= $(RAYLIB_SRC_PATH)/../../raygui/src
|
||||
# Use external GLFW library instead of rglfw module
|
||||
USE_EXTERNAL_GLFW ?= FALSE
|
||||
|
||||
# Enable support for X11 by default on Linux when using GLFW
|
||||
# NOTE: Wayland is disabled by default, only enable if you are sure
|
||||
# Enable support for Wayland and X11 by default on Linux when using GLFW
|
||||
GLFW_LINUX_ENABLE_WAYLAND ?= TRUE
|
||||
GLFW_LINUX_ENABLE_X11 ?= TRUE
|
||||
|
||||
|
||||
12
src/external/win32_clipboard.h
vendored
12
src/external/win32_clipboard.h
vendored
@ -4,14 +4,14 @@
|
||||
|
||||
#ifndef WIN32_CLIPBOARD_
|
||||
#define WIN32_CLIPBOARD_
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize);
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize);
|
||||
#endif // WIN32_CLIPBOARD_
|
||||
|
||||
#ifdef WIN32_CLIPBOARD_IMPLEMENTATION
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
// NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h
|
||||
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined
|
||||
@ -213,7 +213,7 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih); // Get pixel data offset fr
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize)
|
||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize)
|
||||
{
|
||||
unsigned char *bmpData = NULL;
|
||||
|
||||
@ -228,7 +228,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||
*width = bmpInfoHeader->biWidth;
|
||||
*height = bmpInfoHeader->biHeight;
|
||||
SIZE_T clipDataSize = GlobalSize(clipHandle);
|
||||
if (clipDataSize >= sizeof(BITMAPINFOHEADER))
|
||||
if ((clipDataSize >= sizeof(BITMAPINFOHEADER)) && (clipDataSize < INT_MAX))
|
||||
{
|
||||
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
|
||||
|
||||
@ -236,7 +236,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||
//------------------------------------------------------------------------
|
||||
BITMAPFILEHEADER bmpFileHeader = { 0 };
|
||||
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
|
||||
*dataSize = bmpFileSize;
|
||||
*dataSize = (unsigned int)bmpFileSize;
|
||||
|
||||
bmpFileHeader.bfType = 0x4D42; // BMP fil type constant
|
||||
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
|
||||
@ -254,7 +254,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "Clipboard data is malformed");
|
||||
TRACELOG(LOG_WARNING, "Clipboard data is not supported (>2GB?)");
|
||||
GlobalUnlock(clipHandle);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
@ -656,7 +656,7 @@ double GetTime(void)
|
||||
double time = 0.0;
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
|
||||
@ -1054,7 +1054,8 @@ Image GetClipboardImage(void)
|
||||
|
||||
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
||||
#if defined(_WIN32)
|
||||
unsigned long long int dataSize = 0;
|
||||
|
||||
unsigned int dataSize = 0;
|
||||
void *bmpData = NULL;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
@ -1112,7 +1113,7 @@ Image GetClipboardImage(void)
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
|
||||
#endif // defined(_WIN32)
|
||||
#endif // _WIN32
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
|
||||
@ -1024,15 +1024,15 @@ Image GetClipboardImage(void)
|
||||
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
|
||||
#if defined(_WIN32)
|
||||
|
||||
unsigned long long int dataSize = 0; // moved into _WIN32 scope until other platforms gain support
|
||||
void *fileData = NULL; // moved into _WIN32 scope until other platforms gain support
|
||||
unsigned int dataSize = 0;
|
||||
void *fileData = NULL;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
|
||||
|
||||
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
|
||||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize);
|
||||
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, (int)dataSize);
|
||||
|
||||
#elif defined(__linux__) && defined(DRGFW_X11)
|
||||
|
||||
@ -1082,7 +1082,7 @@ Image GetClipboardImage(void)
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
|
||||
#endif // defined(_WIN32)
|
||||
#endif // _WIN32
|
||||
#else
|
||||
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
|
||||
#endif // SUPPORT_CLIPBOARD_IMAGE
|
||||
|
||||
@ -1006,7 +1006,7 @@ double GetTime(void)
|
||||
double time = 0.0;
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
|
||||
@ -364,13 +364,15 @@ double GetTime(void)
|
||||
{
|
||||
double time = 0.0;
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER now = { 0 };
|
||||
QueryPerformanceCounter(&now);
|
||||
return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
||||
LARGE_INTEGER currentTicks = { 0 };
|
||||
QueryPerformanceCounter(¤tTicks);
|
||||
|
||||
time = (double)(currentTicks.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
|
||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
#endif
|
||||
return time;
|
||||
|
||||
@ -341,9 +341,11 @@ void SwapScreenBuffer(void)
|
||||
double GetTime(void)
|
||||
{
|
||||
double time = 0.0;
|
||||
|
||||
struct timespec ts = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
|
||||
unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
|
||||
|
||||
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
|
||||
|
||||
return time;
|
||||
|
||||
@ -858,7 +858,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
|
||||
{
|
||||
drmp3_config config = { 0 };
|
||||
unsigned long long int totalFrameCount = 0;
|
||||
unsigned long long totalFrameCount = 0;
|
||||
|
||||
// NOTE: Forcing conversion to 32bit float sample size on reading
|
||||
wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL);
|
||||
@ -868,7 +868,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
{
|
||||
wave.channels = config.channels;
|
||||
wave.sampleRate = config.sampleRate;
|
||||
wave.frameCount = (int)totalFrameCount;
|
||||
wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
|
||||
|
||||
@ -896,13 +896,13 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
#if SUPPORT_FILEFORMAT_FLAC
|
||||
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
|
||||
{
|
||||
unsigned long long int totalFrameCount = 0;
|
||||
unsigned long long totalFrameCount = 0;
|
||||
|
||||
// NOTE: Forcing conversion to 16bit sample size on reading
|
||||
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
|
||||
wave.sampleSize = 16;
|
||||
|
||||
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
|
||||
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
|
||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
|
||||
}
|
||||
#endif
|
||||
|
||||
12
src/rcore.c
12
src/rcore.c
@ -385,7 +385,7 @@ typedef struct CoreData {
|
||||
double draw; // Time measure for frame draw (seconds)
|
||||
double frame; // Time measure for one frame (seconds)
|
||||
double target; // Desired time for one frame, if 0 not applied (seconds)
|
||||
unsigned long long int base; // Base time measure for hi-res timer (ticks or nanoseconds)
|
||||
unsigned long long base; // Base time measure for hi-res timer (ticks or nanoseconds)
|
||||
unsigned int frameCounter; // Frame counter (frames)
|
||||
|
||||
} Time;
|
||||
@ -3453,8 +3453,8 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||
hash[6] = 0x1f83d9ab;
|
||||
hash[7] = 0x5be0cd19;
|
||||
|
||||
const unsigned long long int bitLen = ((unsigned long long int)dataSize)*8;
|
||||
unsigned long long int paddedSize = dataSize + sizeof(dataSize);
|
||||
const unsigned long long bitLen = 8ULL*dataSize;
|
||||
unsigned long long paddedSize = dataSize + sizeof(dataSize);
|
||||
paddedSize += (64 - (paddedSize%64));
|
||||
unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char));
|
||||
|
||||
@ -3465,7 +3465,7 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||
buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF;
|
||||
}
|
||||
|
||||
for (unsigned long long int blockN = 0; blockN < paddedSize/64; blockN++)
|
||||
for (unsigned long long blockN = 0; blockN < paddedSize/64; blockN++)
|
||||
{
|
||||
unsigned int a = hash[0];
|
||||
unsigned int b = hash[1];
|
||||
@ -3487,7 +3487,7 @@ unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
|
||||
}
|
||||
for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16];
|
||||
|
||||
for (unsigned long long int t = 0; t < 64; t++)
|
||||
for (int t = 0; t < 64; t++)
|
||||
{
|
||||
unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25));
|
||||
unsigned int ch = ((e & f) ^ (~e & g));
|
||||
@ -4219,7 +4219,7 @@ void InitTimer(void)
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
|
||||
{
|
||||
CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;
|
||||
CORE.Time.base = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
|
||||
#endif
|
||||
|
||||
@ -157,8 +157,8 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
// Functions required to query time on Windows
|
||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||
int __stdcall QueryPerformanceCounter(unsigned long long *lpPerformanceCount);
|
||||
int __stdcall QueryPerformanceFrequency(unsigned long long *lpFrequency);
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@ -518,37 +518,36 @@ static double rgGetCurrentTime(void)
|
||||
time = GetTime();
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
unsigned long long int clockFrequency, currentTime;
|
||||
unsigned long long clockFrequency = 0;
|
||||
unsigned long long currentClockTicks = 0;
|
||||
|
||||
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
||||
QueryPerformanceCounter(¤tTime);
|
||||
QueryPerformanceCounter(¤tClockTicks);
|
||||
|
||||
time = (double)currentTime/clockFrequency; // Time in seconds
|
||||
time = (double)currentClockTicks/clockFrequency; // Time in seconds
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
// NOTE: Only for Linux-based systems
|
||||
struct timespec now;
|
||||
struct timespec now = { 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||
unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||
|
||||
time = ((double)nowTime*1e-9); // Time in seconds
|
||||
time = ((double)nanoSeconds*1e-9); // Time in seconds
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
|
||||
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
|
||||
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t now;
|
||||
clock_serv_t cclock = { 0 };
|
||||
mach_timespec_t now = { 0 };
|
||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
||||
|
||||
// NOTE: OS X does not have clock_gettime(), using clock_get_time()
|
||||
clock_get_time(cclock, &now);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||
unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
|
||||
|
||||
time = ((double)nowTime*1e-9); // Time in seconds
|
||||
time = ((double)nanoSeconds*1e-9); // Time in seconds
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -3647,7 +3647,7 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
|
||||
#else // defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#else // GRAPHICS_API_OPENGL_ES2
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
|
||||
|
||||
Reference in New Issue
Block a user