mirror of
https://github.com/love2d/love-android.git
synced 2026-08-19 20:20:25 +02:00
updated to latest mobile-common branch of Löve
This commit is contained in:
@@ -27,9 +27,9 @@ namespace love
|
||||
// Version stuff.
|
||||
const int VERSION_MAJOR = 0;
|
||||
const int VERSION_MINOR = 9;
|
||||
const int VERSION_REV = 0;
|
||||
const char *VERSION = "0.9.0";
|
||||
const char *VERSION_COMPATIBILITY[] = { VERSION, 0 };
|
||||
const int VERSION_REV = 1;
|
||||
const char *VERSION = "0.9.1";
|
||||
const char *VERSION_COMPATIBILITY[] = { VERSION, "0.9.0", 0 };
|
||||
const char *VERSION_CODENAME = "Baby Inspector";
|
||||
|
||||
} // love
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
* Play the specified Source.
|
||||
* @param source The Source to play.
|
||||
**/
|
||||
virtual void play(Source *source) = 0;
|
||||
virtual bool play(Source *source) = 0;
|
||||
|
||||
/**
|
||||
* Stops playback on the specified source.
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
|
||||
virtual Source *clone() = 0;
|
||||
|
||||
virtual void play() = 0;
|
||||
virtual bool play() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void pause() = 0;
|
||||
virtual void resume() = 0;
|
||||
|
||||
@@ -61,12 +61,9 @@ int Audio::getMaxSources() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Source *)
|
||||
{
|
||||
}
|
||||
|
||||
void Audio::play()
|
||||
bool Audio::play(love::audio::Source *)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Audio::stop(love::audio::Source *)
|
||||
|
||||
@@ -48,8 +48,7 @@ public:
|
||||
love::audio::Source *newSource(love::sound::SoundData *soundData);
|
||||
int getSourceCount() const;
|
||||
int getMaxSources() const;
|
||||
void play(love::audio::Source *source);
|
||||
void play();
|
||||
bool play(love::audio::Source *source);
|
||||
void stop(love::audio::Source *source);
|
||||
void stop();
|
||||
void pause(love::audio::Source *source);
|
||||
|
||||
@@ -42,8 +42,9 @@ love::audio::Source *Source::clone()
|
||||
return this;
|
||||
}
|
||||
|
||||
void Source::play()
|
||||
bool Source::play()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Source::stop()
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
virtual ~Source();
|
||||
|
||||
virtual love::audio::Source *clone();
|
||||
virtual void play();
|
||||
virtual bool play();
|
||||
virtual void stop();
|
||||
virtual void pause();
|
||||
virtual void resume();
|
||||
|
||||
@@ -69,22 +69,25 @@ void Audio::PoolThread::setFinish()
|
||||
}
|
||||
|
||||
Audio::Audio()
|
||||
: distanceModel(DISTANCE_INVERSE_CLAMPED)
|
||||
: device(nullptr)
|
||||
, capture(nullptr)
|
||||
, context(nullptr)
|
||||
, pool(nullptr)
|
||||
, poolThread(nullptr)
|
||||
, distanceModel(DISTANCE_INVERSE_CLAMPED)
|
||||
{
|
||||
// Passing zero for default device.
|
||||
device = alcOpenDevice(0);
|
||||
// Passing null for default device.
|
||||
device = alcOpenDevice(nullptr);
|
||||
|
||||
if (device == 0)
|
||||
if (device == nullptr)
|
||||
throw love::Exception("Could not open device.");
|
||||
|
||||
context = alcCreateContext(device, 0);
|
||||
context = alcCreateContext(device, nullptr);
|
||||
|
||||
if (context == 0)
|
||||
if (context == nullptr)
|
||||
throw love::Exception("Could not create context.");
|
||||
|
||||
alcMakeContextCurrent(context);
|
||||
|
||||
if (alcGetError(device) != ALC_NO_ERROR)
|
||||
if (!alcMakeContextCurrent(context) || alcGetError(device) != ALC_NO_ERROR)
|
||||
throw love::Exception("Could not make context current.");
|
||||
|
||||
/*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
|
||||
@@ -108,7 +111,18 @@ Audio::Audio()
|
||||
}*/
|
||||
|
||||
// pool must be allocated after AL context.
|
||||
pool = new Pool();
|
||||
try
|
||||
{
|
||||
pool = new Pool();
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcDestroyContext(context);
|
||||
//if (capture) alcCaptureCloseDevice(capture);
|
||||
alcCloseDevice(device);
|
||||
throw;
|
||||
}
|
||||
|
||||
poolThread = new PoolThread(pool);
|
||||
poolThread->start();
|
||||
@@ -122,7 +136,7 @@ Audio::~Audio()
|
||||
delete poolThread;
|
||||
delete pool;
|
||||
|
||||
alcMakeContextCurrent(0);
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcDestroyContext(context);
|
||||
//if (capture) alcCaptureCloseDevice(capture);
|
||||
alcCloseDevice(device);
|
||||
@@ -154,9 +168,9 @@ int Audio::getMaxSources() const
|
||||
return pool->getMaxSources();
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Source *source)
|
||||
bool Audio::play(love::audio::Source *source)
|
||||
{
|
||||
source->play();
|
||||
return source->play();
|
||||
}
|
||||
|
||||
void Audio::stop(love::audio::Source *source)
|
||||
@@ -281,7 +295,7 @@ bool Audio::canRecord()
|
||||
|
||||
Audio::DistanceModel Audio::getDistanceModel() const
|
||||
{
|
||||
return this->distanceModel;
|
||||
return distanceModel;
|
||||
}
|
||||
|
||||
void Audio::setDistanceModel(DistanceModel distanceModel)
|
||||
|
||||
@@ -67,8 +67,7 @@ public:
|
||||
love::audio::Source *newSource(love::sound::SoundData *soundData);
|
||||
int getSourceCount() const;
|
||||
int getMaxSources() const;
|
||||
void play(love::audio::Source *source);
|
||||
void play();
|
||||
bool play(love::audio::Source *source);
|
||||
void stop(love::audio::Source *source);
|
||||
void stop();
|
||||
void pause(love::audio::Source *source);
|
||||
|
||||
@@ -30,23 +30,43 @@ namespace openal
|
||||
{
|
||||
|
||||
Pool::Pool()
|
||||
: sources()
|
||||
, totalSources(0)
|
||||
, mutex(nullptr)
|
||||
{
|
||||
// Clear errors.
|
||||
alGetError();
|
||||
|
||||
// Generate sources.
|
||||
alGenSources(NUM_SOURCES, sources);
|
||||
for (int i = 0; i < MAX_SOURCES; i++)
|
||||
{
|
||||
alGenSources(1, &sources[i]);
|
||||
|
||||
// We might hit an implementation-dependent limit on the total number
|
||||
// of sources before reaching MAX_SOURCES.
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
break;
|
||||
|
||||
totalSources++;
|
||||
}
|
||||
|
||||
if (totalSources < 4)
|
||||
throw love::Exception("Could not generate sources.");
|
||||
|
||||
// Create the mutex.
|
||||
mutex = thread::newMutex();
|
||||
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
throw love::Exception("Could not generate sources.");
|
||||
ALboolean hasext = alIsExtensionPresent("AL_SOFT_direct_channels");
|
||||
|
||||
// Make all sources available initially.
|
||||
for (int i = 0; i < NUM_SOURCES; i++)
|
||||
for (int i = 0; i < totalSources; i++)
|
||||
{
|
||||
#ifdef AL_DIRECT_CHANNELS_SOFT
|
||||
// Bypassing virtualization of speakers for multi-channel sources in OpenAL Soft.
|
||||
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
|
||||
#endif
|
||||
if (hasext)
|
||||
{
|
||||
// Bypass virtualization of speakers for multi-channel sources in OpenAL Soft.
|
||||
alSourcei(sources[i], AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
|
||||
}
|
||||
|
||||
available.push(sources[i]);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +78,7 @@ Pool::~Pool()
|
||||
delete mutex;
|
||||
|
||||
// Free all sources.
|
||||
alDeleteSources(NUM_SOURCES, sources);
|
||||
alDeleteSources(totalSources, sources);
|
||||
}
|
||||
|
||||
bool Pool::isAvailable() const
|
||||
@@ -113,7 +133,7 @@ int Pool::getSourceCount() const
|
||||
|
||||
int Pool::getMaxSources() const
|
||||
{
|
||||
return NUM_SOURCES;
|
||||
return totalSources;
|
||||
}
|
||||
|
||||
bool Pool::play(Source *source, ALuint &out)
|
||||
@@ -141,9 +161,7 @@ bool Pool::play(Source *source, ALuint &out)
|
||||
|
||||
source->retain();
|
||||
|
||||
source->playAtomic();
|
||||
|
||||
ok = true;
|
||||
ok = source->playAtomic();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#ifdef LOVE_MACOSX_USE_FRAMEWORKS
|
||||
#include <OpenAL-Soft/alc.h>
|
||||
#include <OpenAL-Soft/al.h>
|
||||
#include <OpenAL-Soft/alext.h>
|
||||
#else
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
@@ -99,11 +100,15 @@ private:
|
||||
|
||||
bool findSource(Source *source, ALuint &out);
|
||||
bool removeSource(Source *source);
|
||||
// Number of OpenAL sources.
|
||||
static const int NUM_SOURCES = 64;
|
||||
|
||||
// Maximum possible number of OpenAL sources the pool attempts to generate.
|
||||
static const int MAX_SOURCES = 64;
|
||||
|
||||
// OpenAL sources
|
||||
ALuint sources[NUM_SOURCES];
|
||||
ALuint sources[MAX_SOURCES];
|
||||
|
||||
// Total number of created sources in the pool.
|
||||
int totalSources;
|
||||
|
||||
// A queue of available sources.
|
||||
std::queue<ALuint> available;
|
||||
|
||||
@@ -165,15 +165,16 @@ love::audio::Source *Source::clone()
|
||||
return new Source(*this);
|
||||
}
|
||||
|
||||
void Source::play()
|
||||
bool Source::play()
|
||||
{
|
||||
if (valid && paused)
|
||||
{
|
||||
pool->resume(this);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
valid = pool->play(this, source);
|
||||
return valid;
|
||||
}
|
||||
|
||||
void Source::stop()
|
||||
@@ -512,7 +513,7 @@ bool Source::isLooping() const
|
||||
return looping;
|
||||
}
|
||||
|
||||
void Source::playAtomic()
|
||||
bool Source::playAtomic()
|
||||
{
|
||||
if (type == TYPE_STATIC)
|
||||
{
|
||||
@@ -539,10 +540,19 @@ void Source::playAtomic()
|
||||
// of the new one.
|
||||
reset();
|
||||
|
||||
// Clear errors.
|
||||
alGetError();
|
||||
|
||||
alSourcePlay(source);
|
||||
|
||||
// alSourcePlay may fail if the system has reached its limit of simultaneous
|
||||
// playing sources.
|
||||
bool success = alGetError() == AL_NO_ERROR;
|
||||
|
||||
valid = true; //if it fails it will be set to false again
|
||||
//but this prevents a horrible, horrible bug
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void Source::stopAtomic()
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
virtual ~Source();
|
||||
|
||||
virtual love::audio::Source *clone();
|
||||
virtual void play();
|
||||
virtual bool play();
|
||||
virtual void stop();
|
||||
virtual void pause();
|
||||
virtual void resume();
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
virtual float getMaxDistance() const;
|
||||
virtual int getChannels() const;
|
||||
|
||||
void playAtomic();
|
||||
bool playAtomic();
|
||||
void stopAtomic();
|
||||
void pauseAtomic();
|
||||
void resumeAtomic();
|
||||
|
||||
@@ -75,8 +75,8 @@ int w_newSource(lua_State *L)
|
||||
int w_play(lua_State *L)
|
||||
{
|
||||
Source *s = luax_checksource(L, 1);
|
||||
instance->play(s);
|
||||
return 0;
|
||||
luax_pushboolean(L, instance->play(s));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_stop(lua_State *L)
|
||||
|
||||
@@ -44,8 +44,8 @@ int w_Source_clone(lua_State *L)
|
||||
int w_Source_play(lua_State *L)
|
||||
{
|
||||
Source *t = luax_checksource(L, 1);
|
||||
t->play();
|
||||
return 0;
|
||||
luax_pushboolean(L, t->play());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Source_stop(lua_State *L)
|
||||
|
||||
@@ -224,6 +224,14 @@ Message *Event::convert(const SDL_Event &e) const
|
||||
txt = "touchmoved";
|
||||
msg = new Message(txt, vargs);
|
||||
break;
|
||||
case SDL_MULTIGESTURE:
|
||||
vargs.push_back(new Variant((double) e.mgesture.x));
|
||||
vargs.push_back(new Variant((double) e.mgesture.y));
|
||||
vargs.push_back(new Variant((double) e.mgesture.dTheta));
|
||||
vargs.push_back(new Variant((double) e.mgesture.dDist));
|
||||
vargs.push_back(new Variant((double) e.mgesture.numFingers));
|
||||
msg = new Message("touchgestured", vargs);
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYAXISMOTION:
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
* @param kx Shear along the x-axis.
|
||||
* @param ky Shear along the y-axis.
|
||||
**/
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) = 0;
|
||||
};
|
||||
|
||||
} // graphics
|
||||
|
||||
@@ -99,6 +99,16 @@ bool Graphics::getConstant(Support in, const char *&out)
|
||||
return support.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, SystemLimit &out)
|
||||
{
|
||||
return systemLimits.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(SystemLimit in, const char *&out)
|
||||
{
|
||||
return systemLimits.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM>::Entry Graphics::drawModeEntries[] =
|
||||
{
|
||||
{ "line", Graphics::DRAW_LINE },
|
||||
@@ -170,5 +180,15 @@ StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::suppor
|
||||
|
||||
StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));
|
||||
|
||||
StringMap<Graphics::SystemLimit, Graphics::LIMIT_MAX_ENUM>::Entry Graphics::systemLimitEntries[] =
|
||||
{
|
||||
{"pointsize", Graphics::LIMIT_POINT_SIZE},
|
||||
{"texturesize", Graphics::LIMIT_TEXTURE_SIZE},
|
||||
{"multicanvas", Graphics::LIMIT_MULTI_CANVAS},
|
||||
{"canvasfsaa", Graphics::LIMIT_CANVAS_FSAA},
|
||||
};
|
||||
|
||||
StringMap<Graphics::SystemLimit, Graphics::LIMIT_MAX_ENUM> Graphics::systemLimits(Graphics::systemLimitEntries, sizeof(Graphics::systemLimitEntries));
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -114,6 +114,15 @@ public:
|
||||
RENDERER_INFO_MAX_ENUM
|
||||
};
|
||||
|
||||
enum SystemLimit
|
||||
{
|
||||
LIMIT_POINT_SIZE,
|
||||
LIMIT_TEXTURE_SIZE,
|
||||
LIMIT_MULTI_CANVAS,
|
||||
LIMIT_CANVAS_FSAA,
|
||||
LIMIT_MAX_ENUM
|
||||
};
|
||||
|
||||
virtual ~Graphics();
|
||||
|
||||
/**
|
||||
@@ -155,6 +164,9 @@ public:
|
||||
static bool getConstant(const char *in, Support &out);
|
||||
static bool getConstant(Support in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, SystemLimit &out);
|
||||
static bool getConstant(SystemLimit in, const char *&out);
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
|
||||
@@ -178,6 +190,9 @@ private:
|
||||
static StringMap<Support, SUPPORT_MAX_ENUM>::Entry supportEntries[];
|
||||
static StringMap<Support, SUPPORT_MAX_ENUM> support;
|
||||
|
||||
static StringMap<SystemLimit, LIMIT_MAX_ENUM>::Entry systemLimitEntries[];
|
||||
static StringMap<SystemLimit, LIMIT_MAX_ENUM> systemLimits;
|
||||
|
||||
}; // Graphics
|
||||
|
||||
} // graphics
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
* @param kx Shear along the x-axis.
|
||||
* @param ky Shear along the y-axis.
|
||||
**/
|
||||
virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const = 0;
|
||||
virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) = 0;
|
||||
|
||||
virtual int getWidth() const;
|
||||
virtual int getHeight() const;
|
||||
|
||||
@@ -63,12 +63,26 @@ struct FramebufferStrategy
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Create a MSAA renderbuffer and attach it to the active FBO.
|
||||
/**
|
||||
* @param[in] width Width of the MSAA buffer
|
||||
* @param[in] height Height of the MSAA buffer
|
||||
* @param[inout] samples Number of samples to use
|
||||
* @param[in] internalformat The internal format to use for the buffer
|
||||
* @param[out] buffer Name for the MSAA buffer
|
||||
* @return Whether the MSAA buffer was successfully created and attached
|
||||
**/
|
||||
virtual bool createMSAABuffer(int, int, int &, GLenum, GLuint &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// remove objects
|
||||
/**
|
||||
* @param[in] framebuffer Framebuffer name
|
||||
* @param[in] depth_stencil Name for packed depth and stencil buffer
|
||||
*/
|
||||
virtual void deleteFBO(GLuint, GLuint) {}
|
||||
virtual void deleteFBO(GLuint, GLuint, GLuint) {}
|
||||
virtual void bindFBO(GLuint) {}
|
||||
|
||||
/// attach additional canvases to the active framebuffer for rendering
|
||||
@@ -93,8 +107,11 @@ struct FramebufferStrategyCore : public FramebufferStrategy
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, texture, 0);
|
||||
if (texture != 0)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, texture, 0);
|
||||
}
|
||||
|
||||
// check status
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
@@ -118,13 +135,44 @@ struct FramebufferStrategyCore : public FramebufferStrategy
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
// check status
|
||||
return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &stencil);
|
||||
stencil = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
|
||||
virtual bool createMSAABuffer(int width, int height, int &samples, GLenum internalformat, GLuint &buffer)
|
||||
{
|
||||
glGenRenderbuffers(1, &buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, buffer);
|
||||
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, internalformat,
|
||||
width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, buffer);
|
||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &buffer);
|
||||
buffer = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint msaa_buffer)
|
||||
{
|
||||
if (depth_stencil != 0)
|
||||
glDeleteRenderbuffers(1, &depth_stencil);
|
||||
if (msaa_buffer != 0)
|
||||
glDeleteRenderbuffers(1, &msaa_buffer);
|
||||
if (framebuffer != 0)
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
}
|
||||
@@ -212,7 +260,7 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
|
||||
virtual bool createStencil(int width, int height, GLuint &stencil)
|
||||
{
|
||||
// create combined depth/stencil buffer
|
||||
glDeleteRenderbuffers(1, &stencil);
|
||||
glDeleteRenderbuffersEXT(1, &stencil);
|
||||
glGenRenderbuffersEXT(1, &stencil);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
|
||||
@@ -223,13 +271,47 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
// check status
|
||||
return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glDeleteRenderbuffersEXT(1, &stencil);
|
||||
stencil = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
|
||||
virtual bool createMSAABuffer(int width, int height, int &samples, GLenum internalformat, GLuint &buffer)
|
||||
{
|
||||
if (!GLAD_EXT_framebuffer_multisample)
|
||||
return false;
|
||||
|
||||
glGenRenderbuffersEXT(1, &buffer);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, buffer);
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples,
|
||||
internalformat, width, height);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, buffer);
|
||||
glGetRenderbufferParameterivEXT(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
|
||||
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glDeleteRenderbuffersEXT(1, &buffer);
|
||||
buffer = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint msaa_buffer)
|
||||
{
|
||||
if (depth_stencil != 0)
|
||||
glDeleteRenderbuffersEXT(1, &depth_stencil);
|
||||
if (msaa_buffer != 0)
|
||||
glDeleteRenderbuffersEXT(1, &msaa_buffer);
|
||||
if (framebuffer != 0)
|
||||
glDeleteFramebuffersEXT(1, &framebuffer);
|
||||
}
|
||||
@@ -277,7 +359,7 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
|
||||
virtual bool createStencil(int width, int height, GLuint &stencil)
|
||||
{
|
||||
// create stencil buffer
|
||||
glDeleteRenderbuffers(1, &stencil);
|
||||
glDeleteRenderbuffersEXT(1, &stencil);
|
||||
glGenRenderbuffersEXT(1, &stencil);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
|
||||
@@ -288,14 +370,21 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
// check status
|
||||
return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glDeleteRenderbuffersEXT(1, &stencil);
|
||||
stencil = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isSupported()
|
||||
{
|
||||
GLuint fb = 0, stencil = 0;
|
||||
GLenum status = createFBO(fb, 0);
|
||||
deleteFBO(fb, stencil);
|
||||
deleteFBO(fb, stencil, 0);
|
||||
return status == GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
};
|
||||
@@ -335,11 +424,15 @@ static void getStrategy()
|
||||
static int maxFBOColorAttachments = 0;
|
||||
static int maxDrawBuffers = 0;
|
||||
|
||||
Canvas::Canvas(int width, int height, TextureType texture_type)
|
||||
Canvas::Canvas(int width, int height, TextureType texture_type, int fsaa)
|
||||
: fbo(0)
|
||||
, resolve_fbo(0)
|
||||
, texture(0)
|
||||
, fsaa_buffer(0)
|
||||
, depth_stencil(0)
|
||||
, texture_type(texture_type)
|
||||
, fsaa_samples(fsaa)
|
||||
, fsaa_dirty(false)
|
||||
{
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
@@ -381,9 +474,50 @@ Canvas::~Canvas()
|
||||
unloadVolatile();
|
||||
}
|
||||
|
||||
bool Canvas::createFSAAFBO(GLenum internalformat)
|
||||
{
|
||||
// Create our FBO without a texture.
|
||||
status = strategy->createFBO(fbo, 0);
|
||||
|
||||
GLuint previous = 0;
|
||||
if (current != this)
|
||||
{
|
||||
if (current != nullptr)
|
||||
previous = current->fbo;
|
||||
|
||||
strategy->bindFBO(fbo);
|
||||
}
|
||||
|
||||
// Create and attach the MSAA buffer for our FBO.
|
||||
if (strategy->createMSAABuffer(width, height, fsaa_samples, internalformat, fsaa_buffer))
|
||||
status = GL_FRAMEBUFFER_COMPLETE;
|
||||
else
|
||||
status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
|
||||
// Create the FBO used for the MSAA resolve, and attach the texture.
|
||||
if (status == GL_FRAMEBUFFER_COMPLETE)
|
||||
status = strategy->createFBO(resolve_fbo, texture);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
// Clean up.
|
||||
strategy->deleteFBO(fbo, 0, fsaa_buffer);
|
||||
strategy->deleteFBO(resolve_fbo, 0, 0);
|
||||
fbo = fsaa_buffer = resolve_fbo = 0;
|
||||
fsaa_samples = 0;
|
||||
}
|
||||
|
||||
if (current != this)
|
||||
strategy->bindFBO(previous);
|
||||
|
||||
return status == GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
bool Canvas::loadVolatile()
|
||||
{
|
||||
fbo = depth_stencil = texture = 0;
|
||||
resolve_fbo = fsaa_buffer = 0;
|
||||
status = GL_FRAMEBUFFER_COMPLETE;
|
||||
|
||||
// glTexImage2D is guaranteed to error in this case.
|
||||
if (width > gl.getMaxTextureSize() || height > gl.getMaxTextureSize())
|
||||
@@ -430,7 +564,25 @@ bool Canvas::loadVolatile()
|
||||
return false;
|
||||
}
|
||||
|
||||
status = strategy->createFBO(fbo, texture);
|
||||
int max_samples = 0;
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object
|
||||
|| GLAD_EXT_framebuffer_multisample)
|
||||
{
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
|
||||
}
|
||||
|
||||
if (fsaa_samples > max_samples)
|
||||
fsaa_samples = max_samples;
|
||||
|
||||
// Try to create a FSAA FBO if requested.
|
||||
bool fsaasuccess = false;
|
||||
if (fsaa_samples > 1)
|
||||
fsaasuccess = createFSAAFBO(internalformat);
|
||||
|
||||
// On failure (or no requested FSAA), fall back to a regular FBO.
|
||||
if (!fsaasuccess)
|
||||
status = strategy->createFBO(fbo, texture);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
@@ -440,11 +592,13 @@ bool Canvas::loadVolatile()
|
||||
|
||||
void Canvas::unloadVolatile()
|
||||
{
|
||||
strategy->deleteFBO(fbo, depth_stencil);
|
||||
strategy->deleteFBO(fbo, depth_stencil, fsaa_buffer);
|
||||
strategy->deleteFBO(resolve_fbo, 0, 0);
|
||||
|
||||
gl.deleteTexture(texture);
|
||||
|
||||
fbo = depth_stencil = texture = 0;
|
||||
resolve_fbo = fsaa_buffer = 0;
|
||||
|
||||
for (size_t i = 0; i < attachedCanvases.size(); i++)
|
||||
attachedCanvases[i]->release();
|
||||
@@ -452,7 +606,7 @@ void Canvas::unloadVolatile()
|
||||
attachedCanvases.clear();
|
||||
}
|
||||
|
||||
void Canvas::drawv(const Matrix &t, const Vertex *v) const
|
||||
void Canvas::drawv(const Matrix &t, const Vertex *v)
|
||||
{
|
||||
gl.matrices.transform.push(gl.matrices.transform.top());
|
||||
gl.matrices.transform.top() *= t;
|
||||
@@ -475,10 +629,9 @@ void Canvas::drawv(const Matrix &t, const Vertex *v) const
|
||||
postdraw();
|
||||
|
||||
gl.matrices.transform.pop();
|
||||
|
||||
}
|
||||
|
||||
void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
static Matrix t;
|
||||
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
@@ -486,7 +639,7 @@ void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, f
|
||||
drawv(t, vertices);
|
||||
}
|
||||
|
||||
void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void Canvas::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
static Matrix t;
|
||||
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
@@ -514,8 +667,12 @@ GLuint Canvas::getGLTexture() const
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Canvas::predraw() const
|
||||
void Canvas::predraw()
|
||||
{
|
||||
// We need to make sure the texture is up-to-date by resolving the MSAA
|
||||
// buffer (which we render to when the canvas is active) to it.
|
||||
resolveMSAA();
|
||||
|
||||
gl.bindTexture(texture);
|
||||
}
|
||||
|
||||
@@ -539,6 +696,9 @@ void Canvas::setupGrab()
|
||||
|
||||
// indicate we are using this fbo
|
||||
current = this;
|
||||
|
||||
if (fsaa_buffer != 0)
|
||||
fsaa_dirty = true;
|
||||
}
|
||||
|
||||
void Canvas::startGrab(const std::vector<Canvas *> &canvases)
|
||||
@@ -554,6 +714,9 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
|
||||
|
||||
if (canvases.size()+1 > size_t(maxDrawBuffers) || canvases.size()+1 > size_t(maxFBOColorAttachments))
|
||||
throw love::Exception("This system can't simultaniously render to %d canvases.", canvases.size()+1);
|
||||
|
||||
if (fsaa_samples != 0)
|
||||
throw love::Exception("Multi-canvas rendering is not supported with FSAA.");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < canvases.size(); i++)
|
||||
@@ -564,6 +727,9 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
|
||||
if (canvases[i]->getTextureType() != texture_type)
|
||||
throw love::Exception("All canvas arguments must have the same texture type.");
|
||||
|
||||
if (canvases[i]->getFSAA() != 0)
|
||||
throw love::Exception("Multi-canvas rendering is not supported with FSAA.");
|
||||
|
||||
if (!canvaseschanged && canvases[i] != attachedCanvases[i])
|
||||
canvaseschanged = true;
|
||||
}
|
||||
@@ -698,12 +864,22 @@ bool Canvas::checkCreateStencil()
|
||||
|
||||
love::image::ImageData *Canvas::getImageData(love::image::Image *image)
|
||||
{
|
||||
resolveMSAA();
|
||||
|
||||
int row = 4 * width;
|
||||
int size = row * height;
|
||||
GLubyte *pixels = new GLubyte[size];
|
||||
|
||||
strategy->bindFBO(fbo);
|
||||
// Our texture is attached to 'resolve_fbo' when we use MSAA.
|
||||
if (fsaa_samples > 1 && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
|
||||
else if (fsaa_samples > 1 && GLAD_EXT_framebuffer_multisample)
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, resolve_fbo);
|
||||
else
|
||||
strategy->bindFBO(fbo);
|
||||
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
if (current)
|
||||
strategy->bindFBO(current->fbo);
|
||||
else
|
||||
@@ -716,10 +892,17 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
|
||||
|
||||
void Canvas::getPixel(unsigned char* pixel_rgba, int x, int y)
|
||||
{
|
||||
if (current != this)
|
||||
resolveMSAA();
|
||||
|
||||
// Our texture is attached to 'resolve_fbo' when we use MSAA.
|
||||
if (fsaa_samples > 1 && (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
|
||||
else if (fsaa_samples > 1 && GLAD_EXT_framebuffer_multisample)
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, resolve_fbo);
|
||||
else if (current != this)
|
||||
strategy->bindFBO(fbo);
|
||||
|
||||
glReadPixels(x, height - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel_rgba);
|
||||
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel_rgba);
|
||||
|
||||
if (current && current != this)
|
||||
strategy->bindFBO(current->fbo);
|
||||
@@ -727,6 +910,44 @@ void Canvas::getPixel(unsigned char* pixel_rgba, int x, int y)
|
||||
strategy->bindFBO(gl.getDefaultFBO());
|
||||
}
|
||||
|
||||
bool Canvas::resolveMSAA()
|
||||
{
|
||||
if (resolve_fbo == 0 || fsaa_buffer == 0)
|
||||
return false;
|
||||
|
||||
if (!fsaa_dirty)
|
||||
return true;
|
||||
|
||||
GLuint previous = 0;
|
||||
if (current != nullptr)
|
||||
previous = current->fbo;
|
||||
|
||||
// Do the MSAA resolve by blitting the MSAA renderbuffer to the texture.
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object)
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
else if (GLAD_EXT_framebuffer_multisample && GLAD_EXT_framebuffer_blit)
|
||||
{
|
||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo);
|
||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, resolve_fbo);
|
||||
glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
strategy->bindFBO(previous);
|
||||
|
||||
if (current != this)
|
||||
fsaa_dirty = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Canvas::isSupported()
|
||||
{
|
||||
getStrategy();
|
||||
@@ -740,17 +961,8 @@ bool Canvas::isHDRSupported()
|
||||
|
||||
bool Canvas::isMultiCanvasSupported()
|
||||
{
|
||||
if (!(isSupported() && (GLAD_VERSION_2_0 || GLAD_ARB_draw_buffers)))
|
||||
return false;
|
||||
|
||||
if (maxFBOColorAttachments == 0 || maxDrawBuffers == 0)
|
||||
{
|
||||
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxFBOColorAttachments);
|
||||
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||
}
|
||||
|
||||
// system must support at least 4 simultanious active canvases
|
||||
return maxFBOColorAttachments >= 4 && maxDrawBuffers >= 4;
|
||||
// system must support at least 4 simultanious active canvases.
|
||||
return gl.getMaxRenderTargets() >= 4;
|
||||
}
|
||||
|
||||
void Canvas::bindDefaultCanvas()
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
TYPE_MAX_ENUM
|
||||
};
|
||||
|
||||
Canvas(int width, int height, TextureType texture_type = TYPE_NORMAL);
|
||||
Canvas(int width, int height, TextureType texture_type = TYPE_NORMAL, int fsaa = 0);
|
||||
virtual ~Canvas();
|
||||
|
||||
// Implements Volatile.
|
||||
@@ -54,14 +54,14 @@ public:
|
||||
virtual void unloadVolatile();
|
||||
|
||||
// Implements Drawable.
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
|
||||
// Implements Texture.
|
||||
virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
virtual void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
virtual void setFilter(const Texture::Filter &f);
|
||||
virtual void setWrap(const Texture::Wrap &w);
|
||||
virtual GLuint getGLTexture() const;
|
||||
virtual void predraw() const;
|
||||
virtual void predraw();
|
||||
|
||||
/**
|
||||
* @param canvases A list of other canvases to temporarily attach to this one,
|
||||
@@ -97,6 +97,13 @@ public:
|
||||
return texture_type;
|
||||
}
|
||||
|
||||
inline int getFSAA() const
|
||||
{
|
||||
return fsaa_samples;
|
||||
}
|
||||
|
||||
bool resolveMSAA();
|
||||
|
||||
static bool isSupported();
|
||||
static bool isHDRSupported();
|
||||
static bool isMultiCanvasSupported();
|
||||
@@ -112,8 +119,13 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
bool createFSAAFBO(GLenum internalformat);
|
||||
|
||||
GLuint fbo;
|
||||
GLuint resolve_fbo;
|
||||
|
||||
GLuint texture;
|
||||
GLuint fsaa_buffer;
|
||||
GLuint depth_stencil;
|
||||
|
||||
TextureType texture_type;
|
||||
@@ -122,8 +134,11 @@ private:
|
||||
|
||||
std::vector<Canvas *> attachedCanvases;
|
||||
|
||||
int fsaa_samples;
|
||||
bool fsaa_dirty;
|
||||
|
||||
void setupGrab();
|
||||
void drawv(const Matrix &t, const Vertex *v) const;
|
||||
void drawv(const Matrix &t, const Vertex *v);
|
||||
|
||||
static StringMap<TextureType, TYPE_MAX_ENUM>::Entry textureTypeEntries[];
|
||||
static StringMap<TextureType, TYPE_MAX_ENUM> textureTypes;
|
||||
|
||||
@@ -228,6 +228,18 @@ bool Graphics::setMode(int width, int height)
|
||||
Shader::defaultShader->attach();
|
||||
}
|
||||
|
||||
bool enabledebug = false;
|
||||
|
||||
if (GLAD_VERSION_3_0)
|
||||
{
|
||||
// Enable OpenGL's debug output if a debug context has been created.
|
||||
GLint flags = 0;
|
||||
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||
enabledebug = (flags & GL_CONTEXT_FLAG_DEBUG_BIT) != 0;
|
||||
}
|
||||
|
||||
setDebug(enabledebug);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -246,6 +258,63 @@ void Graphics::unSetMode()
|
||||
}
|
||||
}
|
||||
|
||||
static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, const GLvoid* /*usr*/)
|
||||
{
|
||||
// Human-readable strings for the debug info.
|
||||
const char *sourceStr = OpenGL::debugSourceString(source);
|
||||
const char *typeStr = OpenGL::debugTypeString(type);
|
||||
const char *severityStr = OpenGL::debugSeverityString(severity);
|
||||
|
||||
const char *fmt = "OpenGL: %s [source=%s, type=%s, severity=%s, id=%d]\n";
|
||||
printf(fmt, msg, sourceStr, typeStr, severityStr, id);
|
||||
}
|
||||
|
||||
void Graphics::setDebug(bool enable)
|
||||
{
|
||||
// Make sure debug output is supported. The AMD ext. is a bit different
|
||||
// so we don't make use of it, since AMD drivers now support KHR_debug.
|
||||
if (!(GLAD_VERSION_4_3 || GLAD_KHR_debug || GLAD_ARB_debug_output))
|
||||
return;
|
||||
|
||||
// Ugly hack to reduce code duplication.
|
||||
if (GLAD_ARB_debug_output && !(GLAD_VERSION_4_3 || GLAD_KHR_debug))
|
||||
{
|
||||
fp_glDebugMessageCallback = (pfn_glDebugMessageCallback) fp_glDebugMessageCallbackARB;
|
||||
fp_glDebugMessageControl = (pfn_glDebugMessageControl) fp_glDebugMessageControlARB;
|
||||
}
|
||||
else if (GLAD_ES_VERSION_2_0 && GLAD_KHR_debug)
|
||||
{
|
||||
fp_glDebugMessageCallback = (pfn_glDebugMessageCallback) fp_glDebugMessageCallbackKHR;
|
||||
fp_glDebugMessageControl = (pfn_glDebugMessageControl) fp_glDebugMessageControlKHR;
|
||||
}
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
// Disable the debug callback function.
|
||||
glDebugMessageCallback(nullptr, nullptr);
|
||||
|
||||
// We can disable debug output entirely with KHR_debug.
|
||||
if (GLAD_VERSION_4_3 || GLAD_KHR_debug)
|
||||
glDisable(GL_DEBUG_OUTPUT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't want asynchronous debug output.
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
|
||||
glDebugMessageCallback(debugCB, nullptr);
|
||||
|
||||
// Initially, enable everything.
|
||||
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
|
||||
|
||||
// Disable messages about deprecated OpenGL functionality.
|
||||
glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE);
|
||||
glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE);
|
||||
|
||||
::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n");
|
||||
}
|
||||
|
||||
void Graphics::reset()
|
||||
{
|
||||
DisplayState s;
|
||||
@@ -361,11 +430,6 @@ void Graphics::discardStencil()
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
int Graphics::getMaxTextureSize() const
|
||||
{
|
||||
return gl.getMaxTextureSize();
|
||||
}
|
||||
|
||||
Image *Graphics::newImage(love::image::ImageData *data)
|
||||
{
|
||||
// Create the image.
|
||||
@@ -440,7 +504,7 @@ ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
|
||||
return new ParticleSystem(texture, size);
|
||||
}
|
||||
|
||||
Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_type)
|
||||
Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_type, int fsaa)
|
||||
{
|
||||
if (texture_type == Canvas::TYPE_HDR && !Canvas::isHDRSupported())
|
||||
throw Exception("HDR Canvases are not supported by your OpenGL implementation");
|
||||
@@ -453,7 +517,7 @@ Canvas *Graphics::newCanvas(int width, int height, Canvas::TextureType texture_t
|
||||
while (GL_NO_ERROR != glGetError())
|
||||
/* clear opengl error flag */;
|
||||
|
||||
Canvas *canvas = new Canvas(width, height, texture_type);
|
||||
Canvas *canvas = new Canvas(width, height, texture_type, fsaa);
|
||||
GLenum err = canvas->getStatus();
|
||||
|
||||
// everything ok, return canvas (early out)
|
||||
@@ -771,13 +835,6 @@ Graphics::PointStyle Graphics::getPointStyle() const
|
||||
return POINT_ROUGH;
|
||||
}
|
||||
|
||||
int Graphics::getMaxPointSize() const
|
||||
{
|
||||
GLint max;
|
||||
glGetIntegerv(GL_POINT_SIZE_MAX, &max);
|
||||
return (int)max;
|
||||
}
|
||||
|
||||
void Graphics::print(const std::string &str, float x, float y , float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
if (currentFont != nullptr)
|
||||
@@ -1103,6 +1160,41 @@ std::string Graphics::getRendererInfo(Graphics::RendererInfo infotype) const
|
||||
return std::string(infostr);
|
||||
}
|
||||
|
||||
double Graphics::getSystemLimit(SystemLimit limittype) const
|
||||
{
|
||||
double limit = 0.0;
|
||||
|
||||
switch (limittype)
|
||||
{
|
||||
case Graphics::LIMIT_POINT_SIZE:
|
||||
{
|
||||
GLfloat limits[2];
|
||||
glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, limits);
|
||||
limit = limits[1];
|
||||
}
|
||||
break;
|
||||
case Graphics::LIMIT_TEXTURE_SIZE:
|
||||
limit = (double) gl.getMaxTextureSize();
|
||||
break;
|
||||
case Graphics::LIMIT_MULTI_CANVAS:
|
||||
limit = (double) gl.getMaxRenderTargets();
|
||||
break;
|
||||
case Graphics::LIMIT_CANVAS_FSAA:
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object
|
||||
|| GLAD_EXT_framebuffer_multisample)
|
||||
{
|
||||
GLint intlimit = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &intlimit);
|
||||
limit = (double) intlimit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
void Graphics::push()
|
||||
{
|
||||
if (gl.matrices.transform.size() == matrixLimit)
|
||||
|
||||
@@ -115,6 +115,8 @@ public:
|
||||
virtual bool setMode(int width, int height);
|
||||
virtual void unSetMode();
|
||||
|
||||
void setDebug(bool enable);
|
||||
|
||||
/**
|
||||
* Resets the current color, background color,
|
||||
* line style, and so forth. (This will be called
|
||||
@@ -186,11 +188,6 @@ public:
|
||||
*/
|
||||
void discardStencil();
|
||||
|
||||
/**
|
||||
* Gets the maximum supported width or height of Textures on this system.
|
||||
**/
|
||||
int getMaxTextureSize() const;
|
||||
|
||||
/**
|
||||
* Creates an Image object with padding and/or optimization.
|
||||
**/
|
||||
@@ -208,7 +205,7 @@ public:
|
||||
|
||||
ParticleSystem *newParticleSystem(Texture *texture, int size);
|
||||
|
||||
Canvas *newCanvas(int width, int height, Canvas::TextureType texture_type = Canvas::TYPE_NORMAL);
|
||||
Canvas *newCanvas(int width, int height, Canvas::TextureType texture_type = Canvas::TYPE_NORMAL, int fsaa = 0);
|
||||
|
||||
Shader *newShader(const Shader::ShaderSources &sources);
|
||||
|
||||
@@ -337,12 +334,6 @@ public:
|
||||
**/
|
||||
PointStyle getPointStyle() const;
|
||||
|
||||
/**
|
||||
* Gets the maximum point size supported.
|
||||
* This may vary from computer to computer.
|
||||
**/
|
||||
int getMaxPointSize() const;
|
||||
|
||||
/**
|
||||
* Draws text at the specified coordinates, with rotation and
|
||||
* scaling along both axes.
|
||||
@@ -444,6 +435,11 @@ public:
|
||||
**/
|
||||
std::string getRendererInfo(Graphics::RendererInfo infotype) const;
|
||||
|
||||
/**
|
||||
* Gets the system-dependent numeric limit for the specified parameter.
|
||||
**/
|
||||
double getSystemLimit(SystemLimit limittype) const;
|
||||
|
||||
void push();
|
||||
void pop();
|
||||
void rotate(float r);
|
||||
|
||||
@@ -91,7 +91,7 @@ love::image::CompressedData *Image::getCompressedData() const
|
||||
return cdata;
|
||||
}
|
||||
|
||||
void Image::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void Image::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
Matrix t;
|
||||
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
@@ -99,7 +99,7 @@ void Image::draw(float x, float y, float angle, float sx, float sy, float ox, fl
|
||||
drawv(t, vertices);
|
||||
}
|
||||
|
||||
void Image::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void Image::drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
Matrix t;
|
||||
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
@@ -107,7 +107,7 @@ void Image::drawq(Quad *quad, float x, float y, float angle, float sx, float sy,
|
||||
drawv(t, quad->getVertices());
|
||||
}
|
||||
|
||||
void Image::predraw() const
|
||||
void Image::predraw()
|
||||
{
|
||||
bind();
|
||||
|
||||
@@ -121,7 +121,7 @@ void Image::predraw() const
|
||||
}
|
||||
}
|
||||
|
||||
void Image::postdraw() const
|
||||
void Image::postdraw()
|
||||
{
|
||||
if (width != paddedWidth || height != paddedHeight)
|
||||
{
|
||||
@@ -511,7 +511,7 @@ void Image::uploadDefaultTexture()
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, px);
|
||||
}
|
||||
|
||||
void Image::drawv(const Matrix &t, const Vertex *v) const
|
||||
void Image::drawv(const Matrix &t, const Vertex *v)
|
||||
{
|
||||
predraw();
|
||||
|
||||
|
||||
@@ -76,20 +76,20 @@ public:
|
||||
/**
|
||||
* @copydoc Drawable::draw()
|
||||
**/
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
|
||||
/**
|
||||
* @copydoc Texture::drawq()
|
||||
**/
|
||||
void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
void drawq(Quad *quad, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
|
||||
/**
|
||||
* Call before using this Image's texture to draw. Binds the texture,
|
||||
* globally scales texture coordinates if the Image has NPOT dimensions and
|
||||
* NPOT isn't supported, etc.
|
||||
**/
|
||||
virtual void predraw() const;
|
||||
virtual void postdraw() const;
|
||||
virtual void predraw();
|
||||
virtual void postdraw();
|
||||
|
||||
virtual GLuint getGLTexture() const;
|
||||
|
||||
@@ -136,7 +136,7 @@ private:
|
||||
|
||||
void uploadDefaultTexture();
|
||||
|
||||
void drawv(const Matrix &t, const Vertex *v) const;
|
||||
void drawv(const Matrix &t, const Vertex *v);
|
||||
|
||||
// The ImageData from which the texture is created. May be null if
|
||||
// Compressed image data was used to create the texture.
|
||||
|
||||
@@ -288,7 +288,7 @@ bool Mesh::isWireframe() const
|
||||
return wireframe;
|
||||
}
|
||||
|
||||
void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
const size_t pos_offset = offsetof(Vertex, x);
|
||||
const size_t tex_offset = offsetof(Vertex, s);
|
||||
|
||||
@@ -172,7 +172,7 @@ public:
|
||||
bool isWireframe() const;
|
||||
|
||||
// Implements Drawable.
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
|
||||
static bool getConstant(const char *in, DrawMode &out);
|
||||
static bool getConstant(DrawMode in, const char *&out);
|
||||
|
||||
@@ -43,6 +43,7 @@ OpenGL::OpenGL()
|
||||
: contextInitialized(false)
|
||||
, maxAnisotropy(1.0f)
|
||||
, maxTextureSize(0)
|
||||
, maxRenderTargets(0)
|
||||
, vendor(VENDOR_UNKNOWN)
|
||||
, state()
|
||||
{
|
||||
@@ -202,6 +203,19 @@ void OpenGL::initMaxValues()
|
||||
maxAnisotropy = 1.0f;
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||
|
||||
if (Canvas::isSupported() && (GLAD_VERSION_2_0 || GLAD_ARB_draw_buffers))
|
||||
{
|
||||
int maxattachments = 0;
|
||||
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
|
||||
|
||||
int maxdrawbuffers = 0;
|
||||
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
|
||||
|
||||
maxRenderTargets = std::min(maxattachments, maxdrawbuffers);
|
||||
}
|
||||
else
|
||||
maxRenderTargets = 0;
|
||||
}
|
||||
|
||||
void OpenGL::initMatrices()
|
||||
@@ -260,6 +274,18 @@ void OpenGL::prepareDraw()
|
||||
glVertexAttrib1f((GLuint) ATTRIB_PSEUDO_INSTANCE_ID, 0.0f);
|
||||
state.lastPseudoInstanceID = 0;
|
||||
}
|
||||
|
||||
// We need to make sure antialiased Canvases are properly resolved
|
||||
// before sampling from their textures in a shader.
|
||||
// This is kind of a big hack. :(
|
||||
const std::map<std::string, Object *> &r = shader->getBoundRetainables();
|
||||
for (auto it = r.begin(); it != r.end(); ++it)
|
||||
{
|
||||
// Even bigger hack! D:
|
||||
Canvas *canvas = dynamic_cast<Canvas *>(it->second);
|
||||
if (canvas != nullptr)
|
||||
canvas->resolveMSAA();
|
||||
}
|
||||
}
|
||||
|
||||
if (GLAD_ES_VERSION_2_0 && shader)
|
||||
@@ -716,11 +742,77 @@ int OpenGL::getMaxTextureSize() const
|
||||
return maxTextureSize;
|
||||
}
|
||||
|
||||
int OpenGL::getMaxRenderTargets() const
|
||||
{
|
||||
return maxRenderTargets;
|
||||
}
|
||||
|
||||
OpenGL::Vendor OpenGL::getVendor() const
|
||||
{
|
||||
return vendor;
|
||||
}
|
||||
|
||||
const char *OpenGL::debugSeverityString(GLenum severity)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
return "high";
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
return "medium";
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
return "low";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char *OpenGL::debugSourceString(GLenum source)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case GL_DEBUG_SOURCE_API:
|
||||
return "API";
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
|
||||
return "window";
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER:
|
||||
return "shader";
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY:
|
||||
return "external";
|
||||
case GL_DEBUG_SOURCE_APPLICATION:
|
||||
return "LOVE";
|
||||
case GL_DEBUG_SOURCE_OTHER:
|
||||
return "other";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char *OpenGL::debugTypeString(GLenum type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GL_DEBUG_TYPE_ERROR:
|
||||
return "error";
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
return "deprecated behavior";
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
return "undefined behavior";
|
||||
case GL_DEBUG_TYPE_PERFORMANCE:
|
||||
return "performance";
|
||||
case GL_DEBUG_TYPE_PORTABILITY:
|
||||
return "portability";
|
||||
case GL_DEBUG_TYPE_OTHER:
|
||||
return "other";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
// OpenGL class instance singleton.
|
||||
OpenGL gl;
|
||||
|
||||
|
||||
@@ -96,6 +96,11 @@ public:
|
||||
Viewport(int _x, int _y, int _w, int _h)
|
||||
: x(_x), y(_y), w(_w), h(_h)
|
||||
{}
|
||||
|
||||
bool operator == (const Viewport &rhs) const
|
||||
{
|
||||
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
||||
}
|
||||
};
|
||||
|
||||
// Transformation matrix stacks.
|
||||
@@ -271,11 +276,21 @@ public:
|
||||
**/
|
||||
int getMaxTextureSize() const;
|
||||
|
||||
/**
|
||||
* Returns the maximum supported number of simultaneous render targets.
|
||||
**/
|
||||
int getMaxRenderTargets() const;
|
||||
|
||||
/**
|
||||
* Get the GPU vendor of this OpenGL context.
|
||||
**/
|
||||
Vendor getVendor() const;
|
||||
|
||||
// Get human-readable strings for debug info.
|
||||
static const char *debugSeverityString(GLenum severity);
|
||||
static const char *debugSourceString(GLenum source);
|
||||
static const char *debugTypeString(GLenum type);
|
||||
|
||||
private:
|
||||
|
||||
void initVendor();
|
||||
@@ -290,6 +305,7 @@ private:
|
||||
|
||||
float maxAnisotropy;
|
||||
int maxTextureSize;
|
||||
int maxRenderTargets;
|
||||
|
||||
Vendor vendor;
|
||||
|
||||
|
||||
@@ -442,14 +442,14 @@ ParticleSystem::InsertMode ParticleSystem::getInsertMode() const
|
||||
return insertMode;
|
||||
}
|
||||
|
||||
void ParticleSystem::setEmissionRate(int rate)
|
||||
void ParticleSystem::setEmissionRate(float rate)
|
||||
{
|
||||
if (rate < 0)
|
||||
if (rate < 0.0f)
|
||||
throw love::Exception("Invalid emission rate");
|
||||
emissionRate = rate;
|
||||
}
|
||||
|
||||
int ParticleSystem::getEmissionRate() const
|
||||
float ParticleSystem::getEmissionRate() const
|
||||
{
|
||||
return emissionRate;
|
||||
}
|
||||
@@ -484,6 +484,7 @@ void ParticleSystem::getParticleLifetime(float *min, float *max) const
|
||||
void ParticleSystem::setPosition(float x, float y)
|
||||
{
|
||||
position = love::Vector(x, y);
|
||||
prevPosition = position;
|
||||
}
|
||||
|
||||
const love::Vector &ParticleSystem::getPosition() const
|
||||
@@ -491,6 +492,11 @@ const love::Vector &ParticleSystem::getPosition() const
|
||||
return position;
|
||||
}
|
||||
|
||||
void ParticleSystem::moveTo(float x, float y)
|
||||
{
|
||||
position = love::Vector(x, y);
|
||||
}
|
||||
|
||||
void ParticleSystem::setAreaSpread(AreaSpreadDistribution distribution, float x, float y)
|
||||
{
|
||||
areaSpread = love::Vector(x, y);
|
||||
@@ -790,7 +796,7 @@ bool ParticleSystem::isFull() const
|
||||
return activeParticles == maxParticles;
|
||||
}
|
||||
|
||||
void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
uint32 pCount = getCount();
|
||||
if (pCount == 0 || texture == nullptr || pMem == nullptr || particleVerts == nullptr)
|
||||
|
||||
@@ -132,12 +132,12 @@ public:
|
||||
* Sets the emission rate.
|
||||
* @param rate The amount of particles per second.
|
||||
**/
|
||||
void setEmissionRate(int rate);
|
||||
void setEmissionRate(float rate);
|
||||
|
||||
/**
|
||||
* Returns the number of particles created per second.
|
||||
**/
|
||||
int getEmissionRate() const;
|
||||
float getEmissionRate() const;
|
||||
|
||||
/**
|
||||
* Sets the lifetime of the particle emitter (-1 means eternal)
|
||||
@@ -177,6 +177,15 @@ public:
|
||||
**/
|
||||
const love::Vector &getPosition() const;
|
||||
|
||||
/**
|
||||
* Moves the position of the center of the emitter.
|
||||
* When update is called, newly spawned particles will appear in a line
|
||||
* between the old emitter position and where the emitter was moved to,
|
||||
* resulting in a smoother-feeling particle system if moveTo is called
|
||||
* repeatedly.
|
||||
**/
|
||||
void moveTo(float x, float y);
|
||||
|
||||
/**
|
||||
* Sets the emission area spread parameters and distribution type. The interpretation of
|
||||
* the parameters depends on the distribution type:
|
||||
@@ -471,7 +480,7 @@ public:
|
||||
* @param x The x-coordinate.
|
||||
* @param y The y-coordinate.
|
||||
**/
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
|
||||
/**
|
||||
* Updates the particle system.
|
||||
@@ -551,7 +560,7 @@ protected:
|
||||
uint32 activeParticles;
|
||||
|
||||
// The emission rate (particles/sec).
|
||||
int emissionRate;
|
||||
float emissionRate;
|
||||
|
||||
// Used to determine when a particle should be emitted.
|
||||
float emitCounter;
|
||||
|
||||
@@ -75,6 +75,7 @@ Shader::Shader(const ShaderSources &sources)
|
||||
, builtinUniforms()
|
||||
, vertexAttributes()
|
||||
, lastCanvas((Canvas *) -1)
|
||||
, lastViewport()
|
||||
{
|
||||
if (shaderSources.empty())
|
||||
throw love::Exception("Cannot create shader: no source code!");
|
||||
@@ -753,30 +754,42 @@ bool Shader::sendBuiltinMatrix(BuiltinExtern builtin, int size, const GLfloat *m
|
||||
|
||||
void Shader::checkSetScreenParams()
|
||||
{
|
||||
if (lastCanvas == Canvas::current)
|
||||
OpenGL::Viewport view = gl.getViewport();
|
||||
|
||||
if (view == lastViewport && lastCanvas == Canvas::current)
|
||||
return;
|
||||
|
||||
// In the shader, we do pixcoord.y = gl_FragCoord.y * params[0] + params[1].
|
||||
// In the shader, we do pixcoord.y = gl_FragCoord.y * params.z + params.w.
|
||||
// This lets us flip pixcoord.y when needed, to be consistent (Canvases
|
||||
// have flipped y-values for pixel coordinates.)
|
||||
GLfloat params[] = {0.0f, 0.0f};
|
||||
GLfloat params[] = {
|
||||
(GLfloat) view.w, (GLfloat) view.h,
|
||||
0.0f, 0.0f,
|
||||
};
|
||||
|
||||
if (Canvas::current != nullptr)
|
||||
{
|
||||
// gl_FragCoord.y is flipped in Canvases, so we un-flip:
|
||||
// pixcoord.y = gl_FragCoord.y * -1.0 + height.
|
||||
params[0] = -1.0f;
|
||||
params[1] = (float) Canvas::current->getHeight();
|
||||
params[2] = -1.0f;
|
||||
params[3] = (GLfloat) view.h;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No flipping: pixcoord.y = gl_FragCoord.y * 1.0 + 0.0.
|
||||
params[0] = 1.0f;
|
||||
params[1] = 0.0f;
|
||||
params[2] = 1.0f;
|
||||
params[3] = 0.0f;
|
||||
}
|
||||
|
||||
sendBuiltinFloat(BUILTIN_SCREEN_PARAMS, 2, params, 1);
|
||||
sendBuiltinFloat(BUILTIN_SCREEN_SIZE, 4, params, 1);
|
||||
|
||||
lastCanvas = Canvas::current;
|
||||
lastViewport = view;
|
||||
}
|
||||
|
||||
const std::map<std::string, Object *> &Shader::getBoundRetainables() const
|
||||
{
|
||||
return boundRetainables;
|
||||
}
|
||||
|
||||
std::string Shader::getGLSLVersion()
|
||||
@@ -829,7 +842,7 @@ StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builti
|
||||
{"ProjectionMatrix", Shader::BUILTIN_PROJECTION_MATRIX},
|
||||
{"TransformProjectionMatrix", Shader::BUILTIN_TRANSFORM_PROJECTION_MATRIX},
|
||||
{"love_PointSize", Shader::BUILTIN_POINT_SIZE},
|
||||
{"love_ScreenParams", Shader::BUILTIN_SCREEN_PARAMS},
|
||||
{"love_ScreenSize", Shader::BUILTIN_SCREEN_SIZE},
|
||||
};
|
||||
|
||||
StringMap<Shader::BuiltinExtern, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries));
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
BUILTIN_PROJECTION_MATRIX,
|
||||
BUILTIN_TRANSFORM_PROJECTION_MATRIX,
|
||||
BUILTIN_POINT_SIZE,
|
||||
BUILTIN_SCREEN_PARAMS,
|
||||
BUILTIN_SCREEN_SIZE,
|
||||
BUILTIN_MAX_ENUM
|
||||
};
|
||||
|
||||
@@ -152,6 +152,8 @@ public:
|
||||
bool sendBuiltinFloat(BuiltinExtern builtin, int size, const GLfloat *m, int count);
|
||||
void checkSetScreenParams();
|
||||
|
||||
const std::map<std::string, Object *> &getBoundRetainables() const;
|
||||
|
||||
static std::string getGLSLVersion();
|
||||
static bool isSupported();
|
||||
|
||||
@@ -227,6 +229,7 @@ private:
|
||||
|
||||
// Pointer to the active Canvas when the screen params were last checked.
|
||||
Canvas *lastCanvas;
|
||||
OpenGL::Viewport lastViewport;
|
||||
|
||||
// Max GPU texture units available for sent images
|
||||
static GLint maxTexUnits;
|
||||
|
||||
@@ -263,7 +263,7 @@ int SpriteBatch::getBufferSize() const
|
||||
return size;
|
||||
}
|
||||
|
||||
void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
|
||||
void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
{
|
||||
const size_t vertex_offset = offsetof(Vertex, x);
|
||||
const size_t texel_offset = offsetof(Vertex, s);
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
int getBufferSize() const;
|
||||
|
||||
// Implements Drawable.
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const;
|
||||
void draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
|
||||
|
||||
static bool getConstant(const char *in, UsageHint &out);
|
||||
static bool getConstant(UsageHint in, const char *&out);
|
||||
|
||||
@@ -48,12 +48,12 @@ public:
|
||||
* Any setup the texture might need to do before drawing, e.g. binding
|
||||
* the OpenGL texture for use.
|
||||
**/
|
||||
virtual void predraw() const {}
|
||||
virtual void predraw() {}
|
||||
|
||||
/**
|
||||
* Any cleanup the texture might need to do directly after drawing.
|
||||
**/
|
||||
virtual void postdraw() const {}
|
||||
virtual void postdraw() {}
|
||||
|
||||
|
||||
}; // Texture
|
||||
|
||||
@@ -120,6 +120,13 @@ int w_Canvas_getType(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Canvas_getFSAA(lua_State *L)
|
||||
{
|
||||
Canvas *canvas = luax_checkcanvas(L, 1);
|
||||
lua_pushinteger(L, canvas->getFSAA());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
// From wrap_Texture.
|
||||
@@ -136,6 +143,7 @@ static const luaL_Reg functions[] =
|
||||
{ "getPixel", w_Canvas_getPixel },
|
||||
{ "clear", w_Canvas_clear },
|
||||
{ "getType", w_Canvas_getType },
|
||||
{ "getFSAA", w_Canvas_getFSAA },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ int w_Canvas_getImageData(lua_State *L);
|
||||
int w_Canvas_getPixel(lua_State * L);
|
||||
int w_Canvas_clear(lua_State *L);
|
||||
int w_Canvas_getType(lua_State *L);
|
||||
int w_Canvas_getFSAA(lua_State *L);
|
||||
extern "C" int luaopen_canvas(lua_State *L);
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -146,7 +146,7 @@ int w_setInvertedStencil(lua_State *L)
|
||||
|
||||
int w_getMaxTextureSize(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance->getMaxTextureSize());
|
||||
lua_pushinteger(L, instance->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -323,15 +323,16 @@ int w_newCanvas(lua_State *L)
|
||||
int width = luaL_optint(L, 1, instance->getWidth());
|
||||
int height = luaL_optint(L, 2, instance->getHeight());
|
||||
const char *str = luaL_optstring(L, 3, "normal");
|
||||
int fsaa = luaL_optint(L, 4, 0);
|
||||
|
||||
Canvas::TextureType texture_type;
|
||||
if (!Canvas::getConstant(str, texture_type))
|
||||
return luaL_error(L, "Invalid canvas type: %s", str);
|
||||
|
||||
Canvas *canvas = 0;
|
||||
EXCEPT_GUARD(canvas = instance->newCanvas(width, height, texture_type);)
|
||||
Canvas *canvas = nullptr;
|
||||
EXCEPT_GUARD(canvas = instance->newCanvas(width, height, texture_type, fsaa);)
|
||||
|
||||
if (canvas == 0)
|
||||
if (canvas == nullptr)
|
||||
return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
|
||||
|
||||
luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
|
||||
@@ -830,7 +831,7 @@ int w_getPointStyle(lua_State *L)
|
||||
|
||||
int w_getMaxPointSize(lua_State *L)
|
||||
{
|
||||
lua_pushnumber(L, instance->getMaxPointSize());
|
||||
lua_pushnumber(L, instance->getSystemLimit(Graphics::LIMIT_POINT_SIZE));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1025,7 +1026,7 @@ int w_isSupported(lua_State *L)
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_INSTANCING:
|
||||
if (!GLAD_ARB_draw_instanced)
|
||||
if (!(GLAD_ARB_draw_instanced || (GLAD_ES_VERSION_2_0 && GLAD_EXT_draw_instanced)))
|
||||
supported = false;
|
||||
break;
|
||||
default:
|
||||
@@ -1055,6 +1056,18 @@ int w_getRendererInfo(lua_State *L)
|
||||
return 4;
|
||||
}
|
||||
|
||||
int w_getSystemLimit(lua_State *L)
|
||||
{
|
||||
const char *limitstr = luaL_checkstring(L, 1);
|
||||
Graphics::SystemLimit limittype;
|
||||
|
||||
if (!Graphics::getConstant(limitstr, limittype))
|
||||
return luaL_error(L, "Invalid system limit type: %s", limitstr);
|
||||
|
||||
lua_pushnumber(L, instance->getSystemLimit(limittype));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_draw(lua_State *L)
|
||||
{
|
||||
Drawable *drawable = nullptr;
|
||||
@@ -1392,8 +1405,6 @@ static const luaL_Reg functions[] =
|
||||
{ "setPointStyle", w_setPointStyle },
|
||||
{ "getPointSize", w_getPointSize },
|
||||
{ "getPointStyle", w_getPointStyle },
|
||||
{ "getMaxPointSize", w_getMaxPointSize },
|
||||
{ "getMaxTextureSize", w_getMaxTextureSize },
|
||||
{ "newScreenshot", w_newScreenshot },
|
||||
{ "setCanvas", w_setCanvas },
|
||||
{ "getCanvas", w_getCanvas },
|
||||
@@ -1404,6 +1415,7 @@ static const luaL_Reg functions[] =
|
||||
|
||||
{ "isSupported", w_isSupported },
|
||||
{ "getRendererInfo", w_getRendererInfo },
|
||||
{ "getSystemLimit", w_getSystemLimit },
|
||||
|
||||
{ "draw", w_draw },
|
||||
|
||||
@@ -1439,6 +1451,7 @@ static const luaL_Reg functions[] =
|
||||
|
||||
// Deprecated since 0.9.1.
|
||||
{ "getMaxImageSize", w_getMaxTextureSize },
|
||||
{ "getMaxPointSize", w_getMaxPointSize },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -93,6 +93,7 @@ int w_getShader(lua_State *L);
|
||||
int w_setDefaultShaderCode(lua_State *L);
|
||||
int w_isSupported(lua_State *L);
|
||||
int w_getRendererInfo(lua_State *L);
|
||||
int w_getSystemLimit(lua_State *L);
|
||||
int w_draw(lua_State *L);
|
||||
int w_print(lua_State *L);
|
||||
int w_printf(lua_State *L);
|
||||
|
||||
@@ -127,7 +127,7 @@ int w_ParticleSystem_getInsertMode(lua_State *L)
|
||||
int w_ParticleSystem_setEmissionRate(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
int arg1 = luaL_checkint(L, 2);
|
||||
float arg1 = (float) luaL_checknumber(L, 2);
|
||||
EXCEPT_GUARD(t->setEmissionRate(arg1);)
|
||||
return 0;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ int w_ParticleSystem_setEmissionRate(lua_State *L)
|
||||
int w_ParticleSystem_getEmissionRate(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
lua_pushinteger(L, t->getEmissionRate());
|
||||
lua_pushnumber(L, t->getEmissionRate());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -191,6 +191,15 @@ int w_ParticleSystem_getPosition(lua_State *L)
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_ParticleSystem_moveTo(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
float arg2 = (float)luaL_checknumber(L, 3);
|
||||
t->moveTo(arg1, arg2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_ParticleSystem_setAreaSpread(lua_State *L)
|
||||
{
|
||||
ParticleSystem *t = luax_checkparticlesystem(L, 1);
|
||||
@@ -649,6 +658,7 @@ static const luaL_Reg functions[] =
|
||||
{ "getParticleLifetime", w_ParticleSystem_getParticleLifetime },
|
||||
{ "setPosition", w_ParticleSystem_setPosition },
|
||||
{ "getPosition", w_ParticleSystem_getPosition },
|
||||
{ "moveTo", w_ParticleSystem_moveTo },
|
||||
{ "setAreaSpread", w_ParticleSystem_setAreaSpread },
|
||||
{ "getAreaSpread", w_ParticleSystem_getAreaSpread },
|
||||
{ "setDirection", w_ParticleSystem_setDirection },
|
||||
|
||||
@@ -48,6 +48,7 @@ int w_ParticleSystem_setParticleLifetime(lua_State *L);
|
||||
int w_ParticleSystem_getParticleLifetime(lua_State *L);
|
||||
int w_ParticleSystem_setPosition(lua_State *L);
|
||||
int w_ParticleSystem_getPosition(lua_State *L);
|
||||
int w_ParticleSystem_moveTo(lua_State *L);
|
||||
int w_ParticleSystem_setAreaSpread(lua_State *L);
|
||||
int w_ParticleSystem_getAreaSpread(lua_State *L);
|
||||
int w_ParticleSystem_setDirection(lua_State *L);
|
||||
|
||||
@@ -182,6 +182,15 @@ const char *love_codename()
|
||||
return love::VERSION_CODENAME;
|
||||
}
|
||||
|
||||
static int w_love_getVersion(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, love::VERSION_MAJOR);
|
||||
lua_pushinteger(L, love::VERSION_MINOR);
|
||||
lua_pushinteger(L, love::VERSION_REV);
|
||||
lua_pushstring(L, love::VERSION_CODENAME);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int luaopen_love(lua_State * L)
|
||||
{
|
||||
love::luax_insistglobal(L, "love");
|
||||
@@ -215,6 +224,9 @@ int luaopen_love(lua_State * L)
|
||||
|
||||
lua_setfield(L, -2, "_version_compat");
|
||||
|
||||
lua_pushcfunction(L, w_love_getVersion);
|
||||
lua_setfield(L, -2, "getVersion");
|
||||
|
||||
#ifdef LOVE_WINDOWS
|
||||
lua_pushstring(L, "Windows");
|
||||
#elif defined(LOVE_MACOSX)
|
||||
|
||||
@@ -257,6 +257,18 @@ bool Window::setContext(int fsaa, bool vsync)
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context)
|
||||
{
|
||||
int flags = 0;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &flags);
|
||||
if (flags & SDL_GL_CONTEXT_DEBUG_FLAG)
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context)
|
||||
{
|
||||
displayError("Could not create OpenGL context", SDL_GetError());
|
||||
@@ -299,6 +311,8 @@ void Window::setWindowGLAttributes(int fsaa) const
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
|
||||
|
||||
int contextprofile = 0;
|
||||
|
||||
bool tryES2 = false;
|
||||
|
||||
const char *driver = SDL_GetCurrentVideoDriver();
|
||||
@@ -314,17 +328,30 @@ void Window::setWindowGLAttributes(int fsaa) const
|
||||
if (tryES2)
|
||||
{
|
||||
// Use OpenGL ES 2+.
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
contextprofile = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use desktop OpenGL.
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
|
||||
contextprofile = 0;
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); // default
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
}
|
||||
|
||||
// Do we want a debug context?
|
||||
const char *debugenv = SDL_GetHint("LOVE_GRAPHICS_DEBUG");
|
||||
if (debugenv && *debugenv == '1')
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
if (!tryES2)
|
||||
contextprofile |= SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
}
|
||||
else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, contextprofile);
|
||||
}
|
||||
|
||||
void Window::updateSettings(const WindowSettings &newsettings)
|
||||
|
||||
@@ -179,6 +179,9 @@ function love.createhandlers()
|
||||
touchmoved = function (id,x,y,p)
|
||||
if love.touchmoved then return love.touchmoved(id,x,y,p) end
|
||||
end,
|
||||
touchgestured = function (x,y,theta,dist,num)
|
||||
if love.touchgestured then return love.touchgestured(x,y,theta,dist,num) end
|
||||
end,
|
||||
joystickpressed = function (j,b)
|
||||
if love.joystickpressed then return love.joystickpressed(j,b) end
|
||||
end,
|
||||
@@ -354,6 +357,11 @@ function love.init()
|
||||
c.console = true
|
||||
end
|
||||
|
||||
-- Console hack
|
||||
if c.console and love._openConsole then
|
||||
love._openConsole()
|
||||
end
|
||||
|
||||
-- Gets desired modules.
|
||||
for k,v in ipairs{
|
||||
"android",
|
||||
@@ -383,11 +391,6 @@ function love.init()
|
||||
love.createhandlers()
|
||||
end
|
||||
|
||||
-- Console hack
|
||||
if c.console and love._openConsole then
|
||||
love._openConsole()
|
||||
end
|
||||
|
||||
-- Setup window here.
|
||||
if c.window and c.modules.window then
|
||||
assert(love.window.setMode(c.window.width, c.window.height,
|
||||
@@ -488,7 +491,7 @@ function love.run()
|
||||
-- Process events.
|
||||
if love.event then
|
||||
love.event.pump()
|
||||
for n,a,b,c,d in love.event.poll() do
|
||||
for n,a,b,c,d,e in love.event.poll() do
|
||||
if n == "quit" then
|
||||
if not love.quit or not love.quit() then
|
||||
if love.audio then
|
||||
@@ -497,7 +500,7 @@ function love.run()
|
||||
return
|
||||
end
|
||||
end
|
||||
love.handlers[n](a,b,c,d)
|
||||
love.handlers[n](a,b,c,d,e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -319,6 +319,15 @@ const unsigned char boot_lua[] =
|
||||
0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x69, 0x64, 0x2c, 0x78,
|
||||
0x2c, 0x79, 0x2c, 0x70, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
|
||||
0x09, 0x09, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20,
|
||||
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x74, 0x68, 0x65, 0x74,
|
||||
0x61, 0x2c, 0x64, 0x69, 0x73, 0x74, 0x2c, 0x6e, 0x75, 0x6d, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x67, 0x65,
|
||||
0x73, 0x74, 0x75, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x65,
|
||||
0x64, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x74, 0x68, 0x65, 0x74, 0x61, 0x2c, 0x64, 0x69, 0x73, 0x74, 0x2c, 0x6e,
|
||||
0x75, 0x6d, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
|
||||
0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20,
|
||||
0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63,
|
||||
@@ -625,6 +634,13 @@ const unsigned char boot_lua[] =
|
||||
0x6e, 0x0a,
|
||||
0x09, 0x09, 0x63, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
|
||||
0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c,
|
||||
0x65, 0x28, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x2d, 0x2d, 0x20, 0x47, 0x65, 0x74, 0x73, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x20, 0x6d,
|
||||
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x0a,
|
||||
0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73,
|
||||
@@ -658,13 +674,6 @@ const unsigned char boot_lua[] =
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x68, 0x61, 0x6e, 0x64, 0x6c,
|
||||
0x65, 0x72, 0x73, 0x28, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
|
||||
0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c,
|
||||
0x65, 0x28, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x2d, 0x2d, 0x20, 0x53, 0x65, 0x74, 0x75, 0x70, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x68,
|
||||
0x65, 0x72, 0x65, 0x2e, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
|
||||
@@ -863,9 +872,9 @@ const unsigned char boot_lua[] =
|
||||
0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70,
|
||||
0x28, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x2c, 0x61, 0x2c, 0x62, 0x2c, 0x63, 0x2c, 0x64, 0x20, 0x69,
|
||||
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28,
|
||||
0x29, 0x20, 0x64, 0x6f, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x2c, 0x61, 0x2c, 0x62, 0x2c, 0x63, 0x2c, 0x64, 0x2c, 0x65,
|
||||
0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c,
|
||||
0x6c, 0x28, 0x29, 0x20, 0x64, 0x6f, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x71, 0x75, 0x69, 0x74, 0x22,
|
||||
0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71,
|
||||
@@ -880,7 +889,7 @@ const unsigned char boot_lua[] =
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b,
|
||||
0x6e, 0x5d, 0x28, 0x61, 0x2c, 0x62, 0x2c, 0x63, 0x2c, 0x64, 0x29, 0x0a,
|
||||
0x6e, 0x5d, 0x28, 0x61, 0x2c, 0x62, 0x2c, 0x63, 0x2c, 0x64, 0x2c, 0x65, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x2d, 0x2d, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x64, 0x74, 0x2c, 0x20, 0x61, 0x73,
|
||||
|
||||
@@ -1310,7 +1310,7 @@ do
|
||||
#define TransformProjectionMatrix gl_ModelViewProjectionMatrix
|
||||
#define NormalMatrix gl_NormalMatrix
|
||||
uniform sampler2D _tex0_;
|
||||
uniform vec2 love_ScreenParams;]]
|
||||
uniform vec4 love_ScreenSize;]]
|
||||
|
||||
GLSLES.UNIFORMS = [[
|
||||
uniform mat4 TransformMatrix;
|
||||
@@ -1319,7 +1319,7 @@ uniform mat4 TransformProjectionMatrix;
|
||||
// uniform mat4 NormalMatrix;
|
||||
uniform float love_PointSize;
|
||||
uniform sampler2D _tex0_;
|
||||
uniform vec2 love_ScreenParams;]]
|
||||
uniform vec4 love_ScreenSize;]]
|
||||
|
||||
GLSL.VERTEX = {
|
||||
HEADER = [[
|
||||
@@ -1390,7 +1390,7 @@ void main() {
|
||||
float dummy = texture2D(_tex0_, vec2(.5)).r;
|
||||
|
||||
// See Shader::checkSetScreenParams in Shader.cpp.
|
||||
vec2 pixelcoord = vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenParams[0]) + love_ScreenParams[1]);
|
||||
vec2 pixelcoord = vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w);
|
||||
|
||||
gl_FragColor = effect(VaryingColor, _tex0_, VaryingTexCoord.st, pixelcoord);
|
||||
}]],
|
||||
@@ -1401,7 +1401,7 @@ void main() {
|
||||
float dummy = texture2D(_tex0_, vec2(.5)).r;
|
||||
|
||||
// See Shader::checkSetScreenParams in Shader.cpp.
|
||||
vec2 pixelcoord = vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenParams[0]) + love_ScreenParams[1]);
|
||||
vec2 pixelcoord = vec2(gl_FragCoord.x, (gl_FragCoord.y * love_ScreenSize.z) + love_ScreenSize.w);
|
||||
|
||||
effects(VaryingColor, _tex0_, VaryingTexCoord.st, pixelcoord);
|
||||
}]],
|
||||
|
||||
@@ -6299,8 +6299,8 @@ const unsigned char graphics_lua[] =
|
||||
0x69, 0x78, 0x20, 0x67, 0x6c, 0x5f, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20,
|
||||
0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x3b, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f,
|
||||
0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3b, 0x5d, 0x5d, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f,
|
||||
0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x3b, 0x5d, 0x5d, 0x0a,
|
||||
0x09, 0x47, 0x4c, 0x53, 0x4c, 0x45, 0x53, 0x2e, 0x55, 0x4e, 0x49, 0x46, 0x4f, 0x52, 0x4d, 0x53, 0x20, 0x3d,
|
||||
0x20, 0x5b, 0x5b, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73,
|
||||
@@ -6316,8 +6316,8 @@ const unsigned char graphics_lua[] =
|
||||
0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x3b, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20,
|
||||
0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x3b, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f,
|
||||
0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3b, 0x5d, 0x5d, 0x0a,
|
||||
0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f,
|
||||
0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x3b, 0x5d, 0x5d, 0x0a,
|
||||
0x09, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
|
||||
0x09, 0x09, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
|
||||
0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x45, 0x52, 0x54, 0x45, 0x58, 0x0a,
|
||||
@@ -6429,9 +6429,9 @@ const unsigned char graphics_lua[] =
|
||||
0x09, 0x76, 0x65, 0x63, 0x32, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d,
|
||||
0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64,
|
||||
0x2e, 0x78, 0x2c, 0x20, 0x28, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e,
|
||||
0x79, 0x20, 0x2a, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x50, 0x61, 0x72,
|
||||
0x61, 0x6d, 0x73, 0x5b, 0x30, 0x5d, 0x29, 0x20, 0x2b, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72,
|
||||
0x65, 0x65, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a,
|
||||
0x79, 0x20, 0x2a, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x2e, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e,
|
||||
0x53, 0x69, 0x7a, 0x65, 0x2e, 0x77, 0x29, 0x3b, 0x0a,
|
||||
0x09, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x66,
|
||||
0x66, 0x65, 0x63, 0x74, 0x28, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c,
|
||||
0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x2c, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65,
|
||||
@@ -6454,9 +6454,9 @@ const unsigned char graphics_lua[] =
|
||||
0x09, 0x76, 0x65, 0x63, 0x32, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d,
|
||||
0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64,
|
||||
0x2e, 0x78, 0x2c, 0x20, 0x28, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e,
|
||||
0x79, 0x20, 0x2a, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x50, 0x61, 0x72,
|
||||
0x61, 0x6d, 0x73, 0x5b, 0x30, 0x5d, 0x29, 0x20, 0x2b, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72,
|
||||
0x65, 0x65, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x5b, 0x31, 0x5d, 0x29, 0x3b, 0x0a,
|
||||
0x79, 0x20, 0x2a, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x2e, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e,
|
||||
0x53, 0x69, 0x7a, 0x65, 0x2e, 0x77, 0x29, 0x3b, 0x0a,
|
||||
0x09, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x73, 0x28, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
||||
0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x2c, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69,
|
||||
0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x73, 0x74, 0x2c, 0x20, 0x70, 0x69, 0x78,
|
||||
|
||||
Reference in New Issue
Block a user