Merged default into minor

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2014-09-28 15:56:04 -03:00
26 changed files with 271 additions and 282 deletions
+5 -7
View File
@@ -34,13 +34,11 @@ std::string getLoveInResources()
@autoreleasepool @autoreleasepool
{ {
// check to see if there are any .love files in Resources - props to stevejohnson/diordna // Check to see if there are any .love files in Resources.
NSArray *lovePaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"love" inDirectory:nil]; NSString *lovepath = [[NSBundle mainBundle] pathForResource:nil ofType:@"love"];
if ([lovePaths count] > 0)
{ if (lovepath != nil)
NSString *firstLovePath = [lovePaths objectAtIndex:0]; path = [lovepath UTF8String];
path = std::string([firstLovePath UTF8String]);
}
} }
return path; return path;
-1
View File
@@ -24,7 +24,6 @@
// STD // STD
#include <queue> #include <queue>
#include <map> #include <map>
#include <iostream>
#include <cmath> #include <cmath>
// LOVE // LOVE
-1
View File
@@ -24,7 +24,6 @@
// STD // STD
#include <queue> #include <queue>
#include <map> #include <map>
#include <iostream>
#include <cmath> #include <cmath>
// LOVE // LOVE
+1 -1
View File
@@ -144,7 +144,7 @@ private:
ALuint source; ALuint source;
bool valid; bool valid;
static const unsigned int MAX_BUFFERS = 32; static const unsigned int MAX_BUFFERS = 8;
ALuint streamBuffers[MAX_BUFFERS]; ALuint streamBuffers[MAX_BUFFERS];
Object::StrongRef<StaticDataBuffer> staticBuffer; Object::StrongRef<StaticDataBuffer> staticBuffer;
+3
View File
@@ -26,6 +26,9 @@
#include "common/runtime.h" #include "common/runtime.h"
// C++
#include <iostream>
namespace love namespace love
{ {
namespace audio namespace audio
+12 -20
View File
@@ -42,17 +42,12 @@ namespace sdl
// we want them in pixel coordinates (may be different with high-DPI enabled.) // we want them in pixel coordinates (may be different with high-DPI enabled.)
static void windowToPixelCoords(int *x, int *y) static void windowToPixelCoords(int *x, int *y)
{ {
double scale = 1.0;
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW); window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window != nullptr)
scale = window->getPixelScale();
if (x != nullptr) if (window && x)
*x = int(double(*x) * scale); *x = (int) window->toPixels(*x);
if (window && y)
if (y != nullptr) *y = (int) window->toPixels(*y);
*y = int(double(*y) * scale);
} }
@@ -74,15 +69,11 @@ Event::~Event()
void Event::pump() void Event::pump()
{ {
SDL_PumpEvents(); SDL_Event e;
static SDL_Event e;
Message *msg;
while (SDL_PollEvent(&e)) while (SDL_PollEvent(&e))
{ {
msg = convert(e); Message *msg = convert(e);
if (msg) if (msg)
{ {
push(msg); push(msg);
@@ -93,16 +84,17 @@ void Event::pump()
Message *Event::wait() Message *Event::wait()
{ {
static SDL_Event e; SDL_Event e;
bool ok = (SDL_WaitEvent(&e) == 1);
if (!ok) if (SDL_WaitEvent(&e) != 1)
return NULL; return nullptr;
return convert(e); return convert(e);
} }
void Event::clear() void Event::clear()
{ {
static SDL_Event e; SDL_Event e;
while (SDL_PollEvent(&e)) while (SDL_PollEvent(&e))
{ {
+1 -1
View File
@@ -27,7 +27,7 @@
#include "common/EnumMap.h" #include "common/EnumMap.h"
// SDL // SDL
#include <SDL.h> #include <SDL_events.h>
// STL // STL
#include <map> #include <map>
@@ -24,7 +24,6 @@
// STD // STD
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
+5 -4
View File
@@ -35,6 +35,7 @@
// C // C
#include <cmath> #include <cmath>
#include <cstdio>
namespace love namespace love
{ {
@@ -223,7 +224,7 @@ bool Graphics::setMode(int width, int height, bool &sRGB)
message += "\nThe program may crash or have graphical issues."; message += "\nThe program may crash or have graphical issues.";
::printf("%s\n%s\n", title.c_str(), message.c_str()); ::printf("%s\n%s\n", title.c_str(), message.c_str());
currentWindow->showMessageBox(type, title, message, true); currentWindow->showMessageBox(title, message, type, true);
// We should only show the message once, instead of after every setMode. // We should only show the message once, instead of after every setMode.
displayedMinReqWarning = true; displayedMinReqWarning = true;
@@ -283,7 +284,7 @@ bool Graphics::setMode(int width, int height, bool &sRGB)
// Reload all volatile objects. // Reload all volatile objects.
if (!Volatile::loadAll()) if (!Volatile::loadAll())
std::cerr << "Could not reload all volatile objects." << std::endl; ::printf("Could not reload all volatile objects.\n");
// Restore the graphics state. // Restore the graphics state.
restoreState(states.back()); restoreState(states.back());
@@ -650,9 +651,9 @@ Canvas *Graphics::newCanvas(int width, int height, Canvas::Format format, int ms
return nullptr; // never reached return nullptr; // never reached
} }
Shader *Graphics::newShader(const Shader::ShaderSources &sources) Shader *Graphics::newShader(const Shader::ShaderSource &source)
{ {
return new Shader(sources); return new Shader(source);
} }
Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode) Mesh *Graphics::newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode)
+1 -2
View File
@@ -22,7 +22,6 @@
#define LOVE_GRAPHICS_OPENGL_GRAPHICS_H #define LOVE_GRAPHICS_OPENGL_GRAPHICS_H
// STD // STD
#include <iostream>
#include <stack> #include <stack>
#include <vector> #include <vector>
@@ -154,7 +153,7 @@ public:
Canvas *newCanvas(int width, int height, Canvas::Format format = Canvas::FORMAT_NORMAL, int msaa = 0); Canvas *newCanvas(int width, int height, Canvas::Format format = Canvas::FORMAT_NORMAL, int msaa = 0);
Shader *newShader(const Shader::ShaderSources &sources); Shader *newShader(const Shader::ShaderSource &source);
Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN); Mesh *newMesh(const std::vector<Vertex> &vertices, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN); Mesh *newMesh(int vertexcount, Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN);
+107 -129
View File
@@ -64,20 +64,20 @@ namespace
Shader *Shader::current = nullptr; Shader *Shader::current = nullptr;
Shader *Shader::defaultShader = nullptr; Shader *Shader::defaultShader = nullptr;
Shader::ShaderSources Shader::defaultCode[1]; // TODO: RENDERER_MAX_ENUM Shader::ShaderSource Shader::defaultCode[1]; // TODO: RENDERER_MAX_ENUM
GLint Shader::maxTexUnits = 0; GLint Shader::maxTexUnits = 0;
std::vector<int> Shader::textureCounters; std::vector<int> Shader::textureCounters;
Shader::Shader(const ShaderSources &sources) Shader::Shader(const ShaderSource &source)
: shaderSources(sources) : shaderSource(source)
, program(0) , program(0)
, builtinUniforms() , builtinUniforms()
, vertexAttributes() , builtinAttributes()
, lastCanvas((Canvas *) -1) , lastCanvas((Canvas *) -1)
, lastViewport() , lastViewport()
{ {
if (shaderSources.empty()) if (source.vertex.empty() && source.pixel.empty())
throw love::Exception("Cannot create shader: no source code!"); throw love::Exception("Cannot create shader: no source code!");
if (maxTexUnits <= 0) if (maxTexUnits <= 0)
@@ -108,21 +108,21 @@ Shader::~Shader()
unloadVolatile(); unloadVolatile();
} }
GLuint Shader::compileCode(ShaderType type, const std::string &code) GLuint Shader::compileCode(ShaderStage stage, const std::string &code)
{ {
GLenum glshadertype; GLenum glstage;
const char *typestr; const char *typestr;
if (!typeNames.find(type, typestr)) if (!stageNames.find(stage, typestr))
typestr = ""; typestr = "";
switch (type) switch (stage)
{ {
case TYPE_VERTEX: case STAGE_VERTEX:
glshadertype = GL_VERTEX_SHADER; glstage = GL_VERTEX_SHADER;
break; break;
case TYPE_PIXEL: case STAGE_PIXEL:
glshadertype = GL_FRAGMENT_SHADER; glstage = GL_FRAGMENT_SHADER;
break; break;
default: default:
throw love::Exception("Cannot create shader object: unknown shader type."); throw love::Exception("Cannot create shader object: unknown shader type.");
@@ -132,128 +132,75 @@ GLuint Shader::compileCode(ShaderType type, const std::string &code)
// clear existing errors // clear existing errors
while (glGetError() != GL_NO_ERROR); while (glGetError() != GL_NO_ERROR);
GLuint shaderid = glCreateShader(glshadertype); GLuint shaderid = glCreateShader(glstage);
if (shaderid == 0) // oh no! if (shaderid == 0)
{ {
GLenum err = glGetError(); if (glGetError() == GL_INVALID_ENUM)
if (err == GL_INVALID_ENUM)
throw love::Exception("Cannot create %s shader object: %s shaders not supported.", typestr, typestr); throw love::Exception("Cannot create %s shader object: %s shaders not supported.", typestr, typestr);
else else
throw love::Exception("Cannot create %s shader object.", typestr); throw love::Exception("Cannot create %s shader object.", typestr);
} }
const char *src = code.c_str(); const char *src = code.c_str();
size_t srclen = code.length(); GLint srclen = (GLint) code.length();
glShaderSource(shaderid, 1, (const GLchar **)&src, (GLint *)&srclen); glShaderSource(shaderid, 1, (const GLchar **)&src, &srclen);
glCompileShader(shaderid); glCompileShader(shaderid);
// Get any warnings the shader compiler may have produced.
GLint infologlen; GLint infologlen;
glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen); glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen);
GLchar *infolog = new GLchar[infologlen + 1]; // Get any warnings the shader compiler may have produced.
glGetShaderInfoLog(shaderid, infologlen, nullptr, infolog);
// Save any warnings for later querying.
if (infologlen > 0) if (infologlen > 0)
shaderWarnings[type] = infolog; {
GLchar *infolog = new GLchar[infologlen];
glGetShaderInfoLog(shaderid, infologlen, nullptr, infolog);
delete[] infolog; // Save any warnings for later querying.
shaderWarnings[stage] = infolog;
delete[] infolog;
}
GLint status; GLint status;
glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status); glGetShaderiv(shaderid, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) if (status == GL_FALSE)
{ {
glDeleteShader(shaderid);
throw love::Exception("Cannot compile %s shader code:\n%s", throw love::Exception("Cannot compile %s shader code:\n%s",
typestr, shaderWarnings[type].c_str()); typestr, shaderWarnings[stage].c_str());
} }
return shaderid; return shaderid;
} }
void Shader::createProgram(const std::vector<GLuint> &shaderids)
{
program = glCreateProgram();
if (program == 0)
throw love::Exception("Cannot create shader program object.");
try
{
for (GLuint id : shaderids)
glAttachShader(program, id);
}
catch (love::Exception &)
{
glDeleteProgram(program);
throw;
}
// Bind love's vertex attribute indices to names in the shader.
for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
{
VertexAttribID attrib = (VertexAttribID) i;
// FIXME: We skip this both because pseudo-instancing is temporarily
// disabled (see graphics.lua), and because binding a non-existant
// attribute name to a location can cause a shader linker warning.
if (attrib == ATTRIB_PSEUDO_INSTANCE_ID)
continue;
const char *name = nullptr;
if (attribNames.find(attrib, name))
glBindAttribLocation(program, i, (const GLchar *) name);
}
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
std::string warnings = getProgramWarnings();
glDeleteProgram(program);
program = 0;
throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str());
}
// flag shaders for auto-deletion when the program object is deleted.
for (GLuint id : shaderids)
glDeleteShader(id);
}
void Shader::mapActiveUniforms() void Shader::mapActiveUniforms()
{ {
// Built-in uniform locations default to -1 (nonexistant.)
for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
builtinUniforms[i] = -1;
uniforms.clear(); uniforms.clear();
GLint numuniforms; GLint numuniforms;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numuniforms); glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numuniforms);
GLsizei bufsize; GLchar cname[256];
glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, (GLint *) &bufsize); const GLint bufsize = (GLint) (sizeof(cname) / sizeof(GLchar));
if (bufsize <= 0)
return;
for (int i = 0; i < numuniforms; i++) for (int i = 0; i < numuniforms; i++)
{ {
GLchar *cname = new GLchar[bufsize]; GLsizei namelen = 0;
GLsizei namelength; Uniform u = {};
Uniform u; glGetActiveUniform(program, (GLuint) i, bufsize, &namelen, &u.count, &u.type, cname);
glGetActiveUniform(program, (GLuint) i, bufsize, &namelength, &u.count, &u.type, cname); u.name = std::string(cname, (size_t) namelen);
u.name = std::string(cname, (size_t) namelength);
u.location = glGetUniformLocation(program, u.name.c_str()); u.location = glGetUniformLocation(program, u.name.c_str());
u.baseType = getUniformBaseType(u.type); u.baseType = getUniformBaseType(u.type);
delete[] cname;
// glGetActiveUniform appends "[0]" to the end of array uniform names... // glGetActiveUniform appends "[0]" to the end of array uniform names...
if (u.name.length() > 3) if (u.name.length() > 3)
{ {
@@ -278,35 +225,18 @@ bool Shader::loadVolatile()
activeTexUnits.clear(); activeTexUnits.clear();
activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0); activeTexUnits.insert(activeTexUnits.begin(), maxTexUnits, 0);
// Built-in uniform locations default to -1 (nonexistant.)
for (int i = 0; i < int(BUILTIN_MAX_ENUM); i++)
builtinUniforms[i] = -1;
std::vector<GLuint> shaderids; std::vector<GLuint> shaderids;
for (const auto &source : shaderSources)
{
GLuint shaderid = compileCode(source.first, source.second);
shaderids.push_back(shaderid);
}
// The shader program must have both vertex and pixel shader stages. // The shader program must have both vertex and pixel shader stages.
ShaderSources &defaults = defaultCode[0]; const ShaderSource &defaults = defaultCode[0];
ShaderSources::const_iterator source = shaderSources.find(TYPE_VERTEX); const std::string &vertexcode = shaderSource.vertex.empty() ? defaults.vertex : shaderSource.vertex;
if (source == shaderSources.end()) const std::string &pixelcode = shaderSource.pixel.empty() ? defaults.pixel : shaderSource.pixel;
shaderids.push_back(compileCode(TYPE_VERTEX, defaults[TYPE_VERTEX]));
source = shaderSources.find(TYPE_PIXEL);
if (source == shaderSources.end())
shaderids.push_back(compileCode(TYPE_PIXEL, defaults[TYPE_PIXEL]));
if (shaderids.empty())
throw love::Exception("Cannot create shader: no valid source code!");
try try
{ {
createProgram(shaderids); shaderids.push_back(compileCode(STAGE_VERTEX, vertexcode));
shaderids.push_back(compileCode(STAGE_PIXEL, pixelcode));
} }
catch (love::Exception &) catch (love::Exception &)
{ {
@@ -315,6 +245,51 @@ bool Shader::loadVolatile()
throw; throw;
} }
program = glCreateProgram();
if (program == 0)
{
for (GLuint id : shaderids)
glDeleteShader(id);
throw love::Exception("Cannot create shader program object.");
}
for (GLuint id : shaderids)
glAttachShader(program, id);
// Bind generic vertex attribute indices to names in the shader.
for (int i = 0; i < int(ATTRIB_MAX_ENUM); i++)
{
VertexAttribID attrib = (VertexAttribID) i;
// FIXME: We skip this both because pseudo-instancing is temporarily
// disabled (see graphics.lua), and because binding a non-existant
// attribute name to a location causes a shader linker warning.
if (attrib == ATTRIB_PSEUDO_INSTANCE_ID)
continue;
const char *name = nullptr;
if (attribNames.find(attrib, name))
glBindAttribLocation(program, i, (const GLchar *) name);
}
glLinkProgram(program);
// Flag shaders for auto-deletion when the program object is deleted.
for (GLuint id : shaderids)
glDeleteShader(id);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
std::string warnings = getProgramWarnings();
glDeleteProgram(program);
program = 0;
throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str());
}
// Retreive all active uniform variables in this shader from OpenGL. // Retreive all active uniform variables in this shader from OpenGL.
mapActiveUniforms(); mapActiveUniforms();
@@ -322,9 +297,9 @@ bool Shader::loadVolatile()
{ {
const char *name = nullptr; const char *name = nullptr;
if (attribNames.find(VertexAttribID(i), name)) if (attribNames.find(VertexAttribID(i), name))
vertexAttributes[i] = glGetAttribLocation(program, name); builtinAttributes[i] = glGetAttribLocation(program, name);
else else
vertexAttributes[i] = -1; builtinAttributes[i] = -1;
} }
if (current == this) if (current == this)
@@ -371,13 +346,16 @@ void Shader::unloadVolatile()
std::string Shader::getProgramWarnings() const std::string Shader::getProgramWarnings() const
{ {
GLint strlen, nullpos; GLint strsize, nullpos;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strlen); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &strsize);
char *tempstr = new char[strlen+1]; if (strsize == 0)
return "";
char *tempstr = new char[strsize];
// be extra sure that the error string will be 0-terminated // be extra sure that the error string will be 0-terminated
memset(tempstr, '\0', strlen+1); memset(tempstr, '\0', strsize);
glGetProgramInfoLog(program, strlen, &nullpos, tempstr); glGetProgramInfoLog(program, strsize, &nullpos, tempstr);
tempstr[nullpos] = '\0'; tempstr[nullpos] = '\0';
std::string warnings(tempstr); std::string warnings(tempstr);
@@ -389,13 +367,13 @@ std::string Shader::getProgramWarnings() const
std::string Shader::getWarnings() const std::string Shader::getWarnings() const
{ {
std::string warnings; std::string warnings;
const char *typestr; const char *stagestr;
// Get the individual shader stage warnings // Get the individual shader stage warnings
for (const auto &warning : shaderWarnings) for (const auto &warning : shaderWarnings)
{ {
if (typeNames.find(warning.first, typestr)) if (stageNames.find(warning.first, stagestr))
warnings += std::string(typestr) + std::string(" shader:\n") + warning.second; warnings += std::string(stagestr) + std::string(" shader:\n") + warning.second;
} }
warnings += getProgramWarnings(); warnings += getProgramWarnings();
@@ -644,7 +622,7 @@ Shader::UniformType Shader::getExternVariable(const std::string &name, int &comp
bool Shader::hasVertexAttrib(VertexAttribID attrib) const bool Shader::hasVertexAttrib(VertexAttribID attrib) const
{ {
return vertexAttributes[int(attrib)] != -1; return builtinAttributes[int(attrib)] != -1;
} }
bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const bool Shader::hasBuiltinUniform(BuiltinUniform builtin) const
@@ -816,13 +794,13 @@ bool Shader::getConstant(UniformType in, const char *&out)
return uniformTypes.find(in, out); return uniformTypes.find(in, out);
} }
StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM>::Entry Shader::typeNameEntries[] = StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM>::Entry Shader::stageNameEntries[] =
{ {
{"vertex", Shader::TYPE_VERTEX}, {"vertex", Shader::STAGE_VERTEX},
{"pixel", Shader::TYPE_PIXEL}, {"pixel", Shader::STAGE_PIXEL},
}; };
StringMap<Shader::ShaderType, Shader::TYPE_MAX_ENUM> Shader::typeNames(Shader::typeNameEntries, sizeof(Shader::typeNameEntries)); StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM> Shader::stageNames(Shader::stageNameEntries, sizeof(Shader::stageNameEntries));
StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM>::Entry Shader::uniformTypeEntries[] = StringMap<Shader::UniformType, Shader::UNIFORM_MAX_ENUM>::Entry Shader::uniformTypeEntries[] =
{ {
+19 -17
View File
@@ -46,11 +46,11 @@ class Shader : public Object, public Volatile
{ {
public: public:
enum ShaderType enum ShaderStage
{ {
TYPE_VERTEX, STAGE_VERTEX,
TYPE_PIXEL, STAGE_PIXEL,
TYPE_MAX_ENUM STAGE_MAX_ENUM
}; };
// Built-in uniform (extern) variables. // Built-in uniform (extern) variables.
@@ -71,8 +71,11 @@ public:
UNIFORM_MAX_ENUM UNIFORM_MAX_ENUM
}; };
// Type for a list of shader source codes in the form of sources[shadertype] = code struct ShaderSource
typedef std::map<ShaderType, std::string> ShaderSources; {
std::string vertex;
std::string pixel;
};
// Pointer to currently active Shader. // Pointer to currently active Shader.
static Shader *current; static Shader *current;
@@ -81,13 +84,13 @@ public:
static Shader *defaultShader; static Shader *defaultShader;
// Default shader code (a shader is always required internally.) // Default shader code (a shader is always required internally.)
static ShaderSources defaultCode[1]; // TODO: RENDERER_MAX_ENUM static ShaderSource defaultCode[1]; // TODO: RENDERER_MAX_ENUM
/** /**
* Creates a new Shader using a list of source codes. * Creates a new Shader using a list of source codes.
* Sources must contain either vertex or pixel shader code, or both. * Source must contain either vertex or pixel shader code, or both.
**/ **/
Shader(const ShaderSources &sources); Shader(const ShaderSource &source);
virtual ~Shader(); virtual ~Shader();
@@ -202,8 +205,7 @@ private:
UniformType getUniformBaseType(GLenum type) const; UniformType getUniformBaseType(GLenum type) const;
void checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const; void checkSetUniformError(const Uniform &u, int size, int count, UniformType sendtype) const;
GLuint compileCode(ShaderType type, const std::string &code); GLuint compileCode(ShaderStage stage, const std::string &code);
void createProgram(const std::vector<GLuint> &shaderids);
int getTextureUnit(const std::string &name); int getTextureUnit(const std::string &name);
@@ -212,11 +214,11 @@ private:
// Get any warnings or errors generated only by the shader program object. // Get any warnings or errors generated only by the shader program object.
std::string getProgramWarnings() const; std::string getProgramWarnings() const;
// List of all shader code attached to this Shader // Source code used for this Shader.
ShaderSources shaderSources; ShaderSource shaderSource;
// Shader compiler warning strings for individual shader stages. // Shader compiler warning strings for individual shader stages.
std::map<ShaderType, std::string> shaderWarnings; std::map<ShaderStage, std::string> shaderWarnings;
// volatile // volatile
GLuint program; GLuint program;
@@ -225,7 +227,7 @@ private:
GLint builtinUniforms[BUILTIN_MAX_ENUM]; GLint builtinUniforms[BUILTIN_MAX_ENUM];
// Location values for any generic vertex attribute variables. // Location values for any generic vertex attribute variables.
GLint vertexAttributes[ATTRIB_MAX_ENUM]; GLint builtinAttributes[ATTRIB_MAX_ENUM];
// Uniform location buffer map // Uniform location buffer map
std::map<std::string, Uniform> uniforms; std::map<std::string, Uniform> uniforms;
@@ -247,8 +249,8 @@ private:
// Counts total number of textures bound to each texture unit in all shaders // Counts total number of textures bound to each texture unit in all shaders
static std::vector<int> textureCounters; static std::vector<int> textureCounters;
static StringMap<ShaderType, TYPE_MAX_ENUM>::Entry typeNameEntries[]; static StringMap<ShaderStage, STAGE_MAX_ENUM>::Entry stageNameEntries[];
static StringMap<ShaderType, TYPE_MAX_ENUM> typeNames; static StringMap<ShaderStage, STAGE_MAX_ENUM> stageNames;
static StringMap<UniformType, UNIFORM_MAX_ENUM>::Entry uniformTypeEntries[]; static StringMap<UniformType, UNIFORM_MAX_ENUM>::Entry uniformTypeEntries[];
static StringMap<UniformType, UNIFORM_MAX_ENUM> uniformTypes; static StringMap<UniformType, UNIFORM_MAX_ENUM> uniformTypes;
+8 -14
View File
@@ -445,27 +445,21 @@ int w_newShader(lua_State *L)
if (lua_pcall(L, 2, 2, 0) != 0) if (lua_pcall(L, 2, 2, 0) != 0)
return luaL_error(L, "%s", lua_tostring(L, -1)); return luaL_error(L, "%s", lua_tostring(L, -1));
Shader::ShaderSources sources; Shader::ShaderSource source;
// vertex shader code // vertex shader code
if (lua_isstring(L, -2)) if (lua_isstring(L, -2))
{ source.vertex = luax_checkstring(L, -2);
std::string vertexcode(luaL_checkstring(L, -2));
sources[Shader::TYPE_VERTEX] = vertexcode;
}
else if (has_arg1 && has_arg2) else if (has_arg1 && has_arg2)
return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)"); return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
// pixel shader code // pixel shader code
if (lua_isstring(L, -1)) if (lua_isstring(L, -1))
{ source.pixel = luax_checkstring(L, -1);
std::string pixelcode(luaL_checkstring(L, -1));
sources[Shader::TYPE_PIXEL] = pixelcode;
}
else if (has_arg1 && has_arg2) else if (has_arg1 && has_arg2)
return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)"); return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
if (sources.empty()) if (source.vertex.empty() && source.pixel.empty())
{ {
// Original args had source code, but effectCodeToGLSL couldn't translate it // Original args had source code, but effectCodeToGLSL couldn't translate it
for (int i = 1; i <= 2; i++) for (int i = 1; i <= 2; i++)
@@ -478,7 +472,7 @@ int w_newShader(lua_State *L)
bool should_error = false; bool should_error = false;
try try
{ {
Shader *shader = instance()->newShader(sources); Shader *shader = instance()->newShader(source);
luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader); luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
shader->release(); shader->release();
} }
@@ -982,9 +976,9 @@ int w_setDefaultShaderCode(lua_State *L)
lua_rawgeti(L, -1, 1); lua_rawgeti(L, -1, 1);
lua_rawgeti(L, -2, 2); lua_rawgeti(L, -2, 2);
Shader::ShaderSources openglcode; Shader::ShaderSource openglcode;
openglcode[Shader::TYPE_VERTEX] = luax_checkstring(L, -2); openglcode.vertex = luax_checkstring(L, -2);
openglcode[Shader::TYPE_PIXEL] = luax_checkstring(L, -1); openglcode.pixel = luax_checkstring(L, -1);
lua_pop(L, 3); lua_pop(L, 3);
+1 -1
View File
@@ -241,7 +241,7 @@ public:
KEY_EJECT, KEY_EJECT,
KEY_SLEEP, KEY_SLEEP,
KEY_MAX_ENUM = 512 KEY_MAX_ENUM
}; };
virtual ~Keyboard() {} virtual ~Keyboard() {}
+6 -7
View File
@@ -18,8 +18,6 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#include "common/config.h"
#include "Keyboard.h" #include "Keyboard.h"
namespace love namespace love
@@ -55,8 +53,8 @@ bool Keyboard::isDown(Key *keylist) const
for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist)) for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist))
{ {
auto it = keys.find(key); SDL_Scancode scancode = SDL_GetScancodeFromKey(keymap[key]);
if (it != keys.end() && keystate[SDL_GetScancodeFromKey(it->second)]) if (keystate[scancode])
return true; return true;
} }
@@ -76,9 +74,10 @@ bool Keyboard::hasTextInput() const
return SDL_IsTextInputActive(); return SDL_IsTextInputActive();
} }
std::map<Keyboard::Key, SDL_Keycode> Keyboard::createKeyMap() const SDL_Keycode *Keyboard::createKeyMap()
{ {
std::map<Keyboard::Key, SDL_Keycode> k; // Array must be static so its lifetime continues once the function returns.
static SDL_Keycode k[Keyboard::KEY_MAX_ENUM] = {SDLK_UNKNOWN};
k[Keyboard::KEY_UNKNOWN] = SDLK_UNKNOWN; k[Keyboard::KEY_UNKNOWN] = SDLK_UNKNOWN;
@@ -287,7 +286,7 @@ std::map<Keyboard::Key, SDL_Keycode> Keyboard::createKeyMap()
return k; return k;
} }
std::map<Keyboard::Key, SDL_Keycode> Keyboard::keys = Keyboard::createKeyMap(); const SDL_Keycode *Keyboard::keymap = Keyboard::createKeyMap();
} // sdl } // sdl
} // keyboard } // keyboard
+3 -6
View File
@@ -26,10 +26,7 @@
#include "common/EnumMap.h" #include "common/EnumMap.h"
// SDL // SDL
#include <SDL.h> #include <SDL_keyboard.h>
// STL
#include <map>
namespace love namespace love
{ {
@@ -60,8 +57,8 @@ private:
// The real implementation is in love::event::sdl::Event::Convert. // The real implementation is in love::event::sdl::Event::Convert.
bool key_repeat; bool key_repeat;
static std::map<Key, SDL_Keycode> createKeyMap(); static const SDL_Keycode *createKeyMap();
static std::map<Key, SDL_Keycode> keys; static const SDL_Keycode *keymap;
}; // Keyboard }; // Keyboard
-5
View File
@@ -81,11 +81,6 @@ void RandomGenerator::setSeed(RandomGenerator::Seed newseed)
seed = newseed; seed = newseed;
rng_state = seed; rng_state = seed;
// Xorshift's first couple results after seeding will be similar to results
// from very similar seeds, so we immediately discard them here.
for (int i = 0; i < 2; i++)
rand();
} }
RandomGenerator::Seed RandomGenerator::getSeed() const RandomGenerator::Seed RandomGenerator::getSeed() const
+10 -20
View File
@@ -36,33 +36,23 @@ namespace sdl
// we want them in pixel coordinates (may be different with high-DPI enabled.) // we want them in pixel coordinates (may be different with high-DPI enabled.)
static void windowToPixelCoords(int *x, int *y) static void windowToPixelCoords(int *x, int *y)
{ {
double scale = 1.0; window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
love::window::Window *window = love::window::sdl::Window::getSingleton(); if (window && x)
if (window != nullptr) *x = (int) window->toPixels(*x);
scale = window->getPixelScale(); if (window && y)
*y = (int) window->toPixels(*y);
if (x != nullptr)
*x = int(double(*x) * scale);
if (y != nullptr)
*y = int(double(*y) * scale);
} }
// And vice versa for setting mouse coordinates. // And vice versa for setting mouse coordinates.
static void pixelToWindowCoords(int *x, int *y) static void pixelToWindowCoords(int *x, int *y)
{ {
double scale = 1.0; window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
love::window::Window *window = love::window::sdl::Window::getSingleton(); if (window && x)
if (window != nullptr) *x = (int) window->fromPixels(*x);
scale = window->getPixelScale(); if (window && y)
*y = (int) window->fromPixels(*y);
if (x != nullptr)
*x = int(double(*x) / scale);
if (y != nullptr)
*y = int(double(*y) / scale);
} }
const char *Mouse::getName() const const char *Mouse::getName() const
+55 -13
View File
@@ -93,6 +93,12 @@ EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2)
int Physics::newPolygonShape(lua_State *L) int Physics::newPolygonShape(lua_State *L)
{ {
int argc = lua_gettop(L); int argc = lua_gettop(L);
bool istable = lua_istable(L, 1);
if (istable)
argc = lua_objlen(L, 1);
if (argc % 2 != 0) if (argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two."); return luaL_error(L, "Number of vertex components must be a multiple of two.");
@@ -103,16 +109,31 @@ int Physics::newPolygonShape(lua_State *L)
else if (vcount > b2_maxPolygonVertices) else if (vcount > b2_maxPolygonVertices)
return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount); return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount);
b2PolygonShape *s = new b2PolygonShape();
b2Vec2 vecs[b2_maxPolygonVertices]; b2Vec2 vecs[b2_maxPolygonVertices];
for (int i = 0; i < vcount; i++) if (istable)
{ {
float x = (float)luaL_checknumber(L, 1 + i * 2); for (int i = 0; i < vcount; i++)
float y = (float)luaL_checknumber(L, 2 + i * 2); {
vecs[i] = Physics::scaleDown(b2Vec2(x, y)); lua_rawgeti(L, 1, 1 + i * 2);
lua_rawgeti(L, 1, 2 + i * 2);
float x = (float)luaL_checknumber(L, -2);
float y = (float)luaL_checknumber(L, -1);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
lua_pop(L, 2);
}
} }
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 1 + i * 2);
float y = (float)luaL_checknumber(L, 2 + i * 2);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
}
}
b2PolygonShape *s = new b2PolygonShape();
try try
{ {
@@ -133,22 +154,42 @@ int Physics::newPolygonShape(lua_State *L)
int Physics::newChainShape(lua_State *L) int Physics::newChainShape(lua_State *L)
{ {
int argc = lua_gettop(L)-1; // first argument is looping int argc = lua_gettop(L)-1; // first argument is looping
bool istable = lua_istable(L, 2);
if (istable)
argc = lua_objlen(L, 2);
if (argc % 2 != 0) if (argc % 2 != 0)
return luaL_error(L, "Number of vertex components must be a multiple of two."); return luaL_error(L, "Number of vertex components must be a multiple of two.");
int vcount = (int)argc/2; int vcount = (int)argc/2;
b2ChainShape *s = new b2ChainShape();
bool loop = luax_toboolean(L, 1); bool loop = luax_toboolean(L, 1);
b2Vec2 *vecs = new b2Vec2[vcount]; b2Vec2 *vecs = new b2Vec2[vcount];
for (int i = 0; i<vcount; i++) if (istable)
{ {
float x = (float)lua_tonumber(L, -2); for (int i = 0; i < vcount; i++)
float y = (float)lua_tonumber(L, -1); {
vecs[i].Set(x, y); lua_rawgeti(L, 2, 1 + i * 2);
vecs[i] = Physics::scaleDown(vecs[i]); lua_rawgeti(L, 2, 2 + i * 2);
lua_pop(L, 2); float x = (float)lua_tonumber(L, -2);
float y = (float)lua_tonumber(L, -1);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
lua_pop(L, 2);
}
} }
else
{
for (int i = 0; i < vcount; i++)
{
float x = (float)luaL_checknumber(L, 2 + i * 2);
float y = (float)luaL_checknumber(L, 3 + i * 2);
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
}
}
b2ChainShape *s = new b2ChainShape();
try try
{ {
@@ -160,6 +201,7 @@ int Physics::newChainShape(lua_State *L)
catch (love::Exception &) catch (love::Exception &)
{ {
delete[] vecs; delete[] vecs;
delete s;
throw; throw;
} }
+1 -1
View File
@@ -40,7 +40,7 @@ public:
* Indicates how many bytes of raw data should be generated at each * Indicates how many bytes of raw data should be generated at each
* call to Decode. * call to Decode.
**/ **/
static const int DEFAULT_BUFFER_SIZE = 2048; static const int DEFAULT_BUFFER_SIZE = 16384;
/** /**
* Indicates the quality of the sound. * Indicates the quality of the sound.
+6 -1
View File
@@ -83,6 +83,11 @@ public:
{ {
int width; int width;
int height; int height;
bool operator == (const WindowSize &w) const
{
return w.width == width && w.height == height;
}
}; };
struct MessageBoxData struct MessageBoxData
@@ -156,7 +161,7 @@ public:
virtual const void *getHandle() const = 0; virtual const void *getHandle() const = 0;
virtual bool showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow) = 0; virtual bool showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow) = 0;
virtual int showMessageBox(const MessageBoxData &data) = 0; virtual int showMessageBox(const MessageBoxData &data) = 0;
//virtual static Window *createSingleton() = 0; //virtual static Window *createSingleton() = 0;
+5 -17
View File
@@ -497,29 +497,17 @@ std::vector<WindowSize> Window::getFullscreenSizes(int displayindex) const
{ {
std::vector<WindowSize> sizes; std::vector<WindowSize> sizes;
SDL_DisplayMode mode = {};
std::vector<WindowSize>::const_iterator it;
for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++) for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++)
{ {
SDL_DisplayMode mode = {};
SDL_GetDisplayMode(displayindex, i, &mode); SDL_GetDisplayMode(displayindex, i, &mode);
WindowSize w = {mode.w, mode.h};
// SDL2's display mode list has multiple entries for modes of the same // SDL2's display mode list has multiple entries for modes of the same
// size with different bits per pixel, so we need to filter those out. // size with different bits per pixel, so we need to filter those out.
bool alreadyhassize = false; if (std::find(sizes.begin(), sizes.end(), w) == sizes.end())
for (it = sizes.begin(); it != sizes.end(); ++it)
{
if (it->width == mode.w && it->height == mode.h)
{
alreadyhassize = true;
break;
}
}
if (!alreadyhassize)
{
WindowSize w = {mode.w, mode.h};
sizes.push_back(w); sizes.push_back(w);
}
} }
return sizes; return sizes;
@@ -767,7 +755,7 @@ SDL_MessageBoxFlags Window::convertMessageBoxType(MessageBoxType type) const
} }
} }
bool Window::showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow) bool Window::showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow)
{ {
SDL_MessageBoxFlags flags = convertMessageBoxType(type); SDL_MessageBoxFlags flags = convertMessageBoxType(type);
SDL_Window *sdlwindow = attachtowindow ? window : nullptr; SDL_Window *sdlwindow = attachtowindow ? window : nullptr;
+1 -1
View File
@@ -92,7 +92,7 @@ public:
const void *getHandle() const; const void *getHandle() const;
bool showMessageBox(MessageBoxType type, const std::string &title, const std::string &message, bool attachtowindow); bool showMessageBox(const std::string &title, const std::string &message, MessageBoxType type, bool attachtowindow);
int showMessageBox(const MessageBoxData &data); int showMessageBox(const MessageBoxData &data);
static love::window::Window *createSingleton(); static love::window::Window *createSingleton();
+17 -12
View File
@@ -395,32 +395,29 @@ int w_minimize(lua_State* /*L*/)
int w_showMessageBox(lua_State *L) int w_showMessageBox(lua_State *L)
{ {
Window::MessageBoxData data = {}; Window::MessageBoxData data = {};
data.type = Window::MESSAGEBOX_INFO;
const char *typestr = luaL_checkstring(L, 1); data.title = luaL_checkstring(L, 1);
if (!Window::getConstant(typestr, data.type)) data.message = luaL_checkstring(L, 2);
return luaL_error(L, "Invalid messagebox type: %s", typestr);
data.title = luaL_checkstring(L, 2);
data.message = luaL_checkstring(L, 3);
// If we have a table argument, we assume a list of button names, which // If we have a table argument, we assume a list of button names, which
// means we should use the more complex message box API. // means we should use the more complex message box API.
if (lua_istable(L, 4)) if (lua_istable(L, 3))
{ {
size_t numbuttons = lua_objlen(L, 4); size_t numbuttons = lua_objlen(L, 3);
if (numbuttons == 0) if (numbuttons == 0)
return luaL_error(L, "Must have at least one messagebox button."); return luaL_error(L, "Must have at least one messagebox button.");
// Array of button names. // Array of button names.
for (size_t i = 0; i < numbuttons; i++) for (size_t i = 0; i < numbuttons; i++)
{ {
lua_rawgeti(L, 4, i + 1); lua_rawgeti(L, 3, i + 1);
data.buttons.push_back(luax_checkstring(L, -1)); data.buttons.push_back(luax_checkstring(L, -1));
lua_pop(L, 1); lua_pop(L, 1);
} }
// Optional table entry specifying the button to use when enter is pressed. // Optional table entry specifying the button to use when enter is pressed.
lua_getfield(L, 4, "enterbutton"); lua_getfield(L, 3, "enterbutton");
if (!lua_isnoneornil(L, -1)) if (!lua_isnoneornil(L, -1))
data.enterButtonIndex = luaL_checkint(L, -1) - 1; data.enterButtonIndex = luaL_checkint(L, -1) - 1;
else else
@@ -428,13 +425,17 @@ int w_showMessageBox(lua_State *L)
lua_pop(L, 1); lua_pop(L, 1);
// Optional table entry specifying the button to use when esc is pressed. // Optional table entry specifying the button to use when esc is pressed.
lua_getfield(L, 4, "escapebutton"); lua_getfield(L, 3, "escapebutton");
if (!lua_isnoneornil(L, -1)) if (!lua_isnoneornil(L, -1))
data.escapeButtonIndex = luaL_checkint(L, -1) - 1; data.escapeButtonIndex = luaL_checkint(L, -1) - 1;
else else
data.escapeButtonIndex = (int) data.buttons.size() - 1; data.escapeButtonIndex = (int) data.buttons.size() - 1;
lua_pop(L, 1); lua_pop(L, 1);
const char *typestr = lua_isnoneornil(L, 4) ? nullptr : luaL_checkstring(L, 4);
if (typestr && !Window::getConstant(typestr, data.type))
return luaL_error(L, "Invalid messagebox type: %s", typestr);
data.attachToWindow = luax_optboolean(L, 5, true); data.attachToWindow = luax_optboolean(L, 5, true);
int pressedbutton = instance()->showMessageBox(data); int pressedbutton = instance()->showMessageBox(data);
@@ -442,10 +443,14 @@ int w_showMessageBox(lua_State *L)
} }
else else
{ {
const char *typestr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3);
if (typestr && !Window::getConstant(typestr, data.type))
return luaL_error(L, "Invalid messagebox type: %s", typestr);
data.attachToWindow = luax_optboolean(L, 4, true); data.attachToWindow = luax_optboolean(L, 4, true);
// Display a simple message box. // Display a simple message box.
bool success = instance()->showMessageBox(data.type, data.title, data.message, data.attachToWindow); bool success = instance()->showMessageBox(data.title, data.message, data.type, data.attachToWindow);
luax_pushboolean(L, success); luax_pushboolean(L, success);
} }
+1
View File
@@ -479,6 +479,7 @@ function love.run()
if love.math then if love.math then
love.math.setRandomSeed(os.time()) love.math.setRandomSeed(os.time())
for i=1,3 do love.math.random() end
end end
if love.event then if love.event then
+3
View File
@@ -858,6 +858,9 @@ const unsigned char boot_lua[] =
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x61, 0x6e, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x74, 0x52, 0x61, 0x6e,
0x64, 0x6f, 0x6d, 0x53, 0x65, 0x65, 0x64, 0x28, 0x6f, 0x73, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0x29, 0x0a, 0x64, 0x6f, 0x6d, 0x53, 0x65, 0x65, 0x64, 0x28, 0x6f, 0x73, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0x29, 0x0a,
0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x3d, 0x31, 0x2c, 0x33, 0x20, 0x64, 0x6f, 0x20, 0x6c, 0x6f, 0x76,
0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x29, 0x20, 0x65, 0x6e,
0x64, 0x0a,
0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0a, 0x6e, 0x0a,