mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Merge remote-tracking branch 'origin/12.0-development' into vulkan
This commit is contained in:
+10
@@ -1,3 +1,13 @@
|
|||||||
|
# automake products
|
||||||
|
/config.h
|
||||||
|
/config.h.in
|
||||||
|
/config.log
|
||||||
|
/config.status
|
||||||
|
/configure
|
||||||
|
/configure-modules-post.ac
|
||||||
|
/configure-modules-pre.ac
|
||||||
|
/configure.ac
|
||||||
|
|
||||||
/extra/reshax/Release/
|
/extra/reshax/Release/
|
||||||
/extra/reshax/Debug/
|
/extra/reshax/Debug/
|
||||||
/extra/reshax/resources.h
|
/extra/reshax/resources.h
|
||||||
|
|||||||
@@ -1841,6 +1841,7 @@ if(MSVC)
|
|||||||
set(LOVE_LINK_LIBRARIES ${LOVE_LINK_LIBRARIES}
|
set(LOVE_LINK_LIBRARIES ${LOVE_LINK_LIBRARIES}
|
||||||
ws2_32.lib
|
ws2_32.lib
|
||||||
winmm.lib
|
winmm.lib
|
||||||
|
dwmapi.lib
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LOVE_RC
|
set(LOVE_RC
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ bool Stream::write(Data *src)
|
|||||||
|
|
||||||
bool Stream::write(Data *src, int64 offset, int64 size)
|
bool Stream::write(Data *src, int64 offset, int64 size)
|
||||||
{
|
{
|
||||||
if (offset < 0 || size < 0 || offset + size > src->getSize())
|
if (offset < 0 || size < 0 || offset + size > (int64) src->getSize())
|
||||||
throw love::Exception("Offset and size parameters do not fit within the given Data's size.");
|
throw love::Exception("Offset and size parameters do not fit within the given Data's size.");
|
||||||
|
|
||||||
return write((const uint8 *) src->getData() + offset, size);
|
return write((const uint8 *) src->getData() + offset, size);
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ HTTPSClient::Reply AndroidClient::request(const HTTPSClient::Request &req)
|
|||||||
|
|
||||||
jmethodID constructor = env->GetMethodID(httpsClass, "<init>", "()V");
|
jmethodID constructor = env->GetMethodID(httpsClass, "<init>", "()V");
|
||||||
jmethodID setURL = env->GetMethodID(httpsClass, "setUrl", "(Ljava/lang/String;)V");
|
jmethodID setURL = env->GetMethodID(httpsClass, "setUrl", "(Ljava/lang/String;)V");
|
||||||
|
jmethodID setMethod = env->GetMethodID(httpsClass, "setMethod", "(Ljava/lang/String;)V");
|
||||||
jmethodID request = env->GetMethodID(httpsClass, "request", "()Z");
|
jmethodID request = env->GetMethodID(httpsClass, "request", "()Z");
|
||||||
jmethodID getInterleavedHeaders = env->GetMethodID(httpsClass, "getInterleavedHeaders", "()[Ljava/lang/String;");
|
jmethodID getInterleavedHeaders = env->GetMethodID(httpsClass, "getInterleavedHeaders", "()[Ljava/lang/String;");
|
||||||
jmethodID getResponse = env->GetMethodID(httpsClass, "getResponse", "()[B");
|
jmethodID getResponse = env->GetMethodID(httpsClass, "getResponse", "()[B");
|
||||||
@@ -109,8 +110,13 @@ HTTPSClient::Reply AndroidClient::request(const HTTPSClient::Request &req)
|
|||||||
env->CallVoidMethod(httpsObject, setURL, url);
|
env->CallVoidMethod(httpsObject, setURL, url);
|
||||||
env->DeleteLocalRef(url);
|
env->DeleteLocalRef(url);
|
||||||
|
|
||||||
|
// Set method
|
||||||
|
jstring method = env->NewStringUTF(req.method.c_str());
|
||||||
|
env->CallVoidMethod(httpsObject, setMethod, method);
|
||||||
|
env->DeleteLocalRef(method);
|
||||||
|
|
||||||
// Set post data
|
// Set post data
|
||||||
if (req.method == Request::POST)
|
if (req.postdata.size() > 0)
|
||||||
{
|
{
|
||||||
jmethodID setPostData = env->GetMethodID(httpsClass, "setPostData", "([B)V");
|
jmethodID setPostData = env->GetMethodID(httpsClass, "setPostData", "([B)V");
|
||||||
jbyteArray byteArray = env->NewByteArray((jsize) req.postdata.length());
|
jbyteArray byteArray = env->NewByteArray((jsize) req.postdata.length());
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.ProtocolException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -22,6 +23,7 @@ class LuaHTTPS {
|
|||||||
static private String TAG = "LuaHTTPS";
|
static private String TAG = "LuaHTTPS";
|
||||||
|
|
||||||
private String urlString;
|
private String urlString;
|
||||||
|
private String method;
|
||||||
private byte[] postData;
|
private byte[] postData;
|
||||||
private byte[] response;
|
private byte[] response;
|
||||||
private int responseCode;
|
private int responseCode;
|
||||||
@@ -34,6 +36,7 @@ class LuaHTTPS {
|
|||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
urlString = null;
|
urlString = null;
|
||||||
|
method = "GET";
|
||||||
postData = null;
|
postData = null;
|
||||||
response = null;
|
response = null;
|
||||||
responseCode = 0;
|
responseCode = 0;
|
||||||
@@ -50,6 +53,11 @@ class LuaHTTPS {
|
|||||||
this.postData = postData;
|
this.postData = postData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
public void setMethod(String method) {
|
||||||
|
this.method = method.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
public void addHeader(String key, String value) {
|
public void addHeader(String key, String value) {
|
||||||
headers.put(key, value);
|
headers.put(key, value);
|
||||||
@@ -110,15 +118,22 @@ class LuaHTTPS {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set request method
|
||||||
|
try {
|
||||||
|
connection.setRequestMethod(method);
|
||||||
|
} catch (ProtocolException e) {
|
||||||
|
Log.e(TAG, "Error", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set header
|
// Set header
|
||||||
for (Map.Entry<String, String> headerData: headers.entrySet()) {
|
for (Map.Entry<String, String> headerData: headers.entrySet()) {
|
||||||
connection.setRequestProperty(headerData.getKey(), headerData.getValue());
|
connection.setRequestProperty(headerData.getKey(), headerData.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set post data
|
// Set post data
|
||||||
if (postData != null) {
|
if (postData != null && canSendData()) {
|
||||||
connection.setDoOutput(true);
|
connection.setDoOutput(true);
|
||||||
connection.setChunkedStreamingMode(0);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OutputStream out = connection.getOutputStream();
|
OutputStream out = connection.getOutputStream();
|
||||||
@@ -168,4 +183,8 @@ class LuaHTTPS {
|
|||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean canSendData() {
|
||||||
|
return !method.equals("GET") && !method.equals("HEAD");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,16 +29,12 @@ HTTPSClient::Reply NSURLClient::request(const HTTPSClient::Request &req)
|
|||||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
||||||
|
|
||||||
NSData *bodydata = nil;
|
NSData *bodydata = nil;
|
||||||
switch(req.method)
|
[request setHTTPMethod:@(req.method.c_str())];
|
||||||
|
|
||||||
|
if (req.postdata.size() > 0 && (req.method != "GET" && req.method != "HEAD"))
|
||||||
{
|
{
|
||||||
case Request::GET:
|
|
||||||
[request setHTTPMethod:@"GET"];
|
|
||||||
break;
|
|
||||||
case Request::POST:
|
|
||||||
bodydata = [NSData dataWithBytesNoCopy:(void*) req.postdata.data() length:req.postdata.size() freeWhenDone:NO];
|
bodydata = [NSData dataWithBytesNoCopy:(void*) req.postdata.data() length:req.postdata.size() freeWhenDone:NO];
|
||||||
[request setHTTPMethod:@"POST"];
|
|
||||||
[request setHTTPBody:bodydata];
|
[request setHTTPBody:bodydata];
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &header : req.headers)
|
for (auto &header : req.headers)
|
||||||
@@ -63,7 +59,7 @@ HTTPSClient::Reply NSURLClient::request(const HTTPSClient::Request &req)
|
|||||||
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
HTTPSClient::Reply reply;
|
HTTPSClient::Reply reply;
|
||||||
reply.responseCode = 400;
|
reply.responseCode = 0;
|
||||||
|
|
||||||
if (body)
|
if (body)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,13 @@ HTTPSClient::Reply HTTPRequest::request(const HTTPSClient::Request &req)
|
|||||||
// Build the request
|
// Build the request
|
||||||
{
|
{
|
||||||
std::stringstream request;
|
std::stringstream request;
|
||||||
request << (req.method == HTTPSClient::Request::GET ? "GET " : "POST ") << info.query << " HTTP/1.1\r\n";
|
std::string method = req.method;
|
||||||
|
bool hasData = req.postdata.length() > 0;
|
||||||
|
|
||||||
|
if (method.length() == 0)
|
||||||
|
method = hasData ? "POST" : "GET";
|
||||||
|
|
||||||
|
request << method << " " << info.query << " HTTP/1.1\r\n";
|
||||||
|
|
||||||
for (auto &header : req.headers)
|
for (auto &header : req.headers)
|
||||||
request << header.first << ": " << header.second << "\r\n";
|
request << header.first << ": " << header.second << "\r\n";
|
||||||
@@ -44,15 +50,15 @@ HTTPSClient::Reply HTTPRequest::request(const HTTPSClient::Request &req)
|
|||||||
|
|
||||||
request << "Host: " << info.hostname << "\r\n";
|
request << "Host: " << info.hostname << "\r\n";
|
||||||
|
|
||||||
if (req.method == HTTPSClient::Request::POST && req.headers.count("Content-Type") == 0)
|
if (hasData && req.headers.count("Content-Type") == 0)
|
||||||
request << "Content-Type: application/x-www-form-urlencoded\r\n";
|
request << "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||||
|
|
||||||
if (req.method == HTTPSClient::Request::POST)
|
if (hasData)
|
||||||
request << "Content-Length: " << req.postdata.size() << "\r\n";
|
request << "Content-Length: " << req.postdata.size() << "\r\n";
|
||||||
|
|
||||||
request << "\r\n";
|
request << "\r\n";
|
||||||
|
|
||||||
if (req.method == HTTPSClient::Request::POST)
|
if (hasData)
|
||||||
request << req.postdata;
|
request << req.postdata;
|
||||||
|
|
||||||
// Send it
|
// Send it
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ bool HTTPSClient::ci_string_less::operator()(const std::string &lhs, const std::
|
|||||||
|
|
||||||
HTTPSClient::Request::Request(const std::string &url)
|
HTTPSClient::Request::Request(const std::string &url)
|
||||||
: url(url)
|
: url(url)
|
||||||
, method(GET)
|
, method("")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ public:
|
|||||||
header_map headers;
|
header_map headers;
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string postdata;
|
std::string postdata;
|
||||||
|
std::string method;
|
||||||
enum Method
|
|
||||||
{
|
|
||||||
GET,
|
|
||||||
POST,
|
|
||||||
} method;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Reply
|
struct Reply
|
||||||
|
|||||||
@@ -73,9 +73,15 @@ HTTPSClient::Reply CurlClient::request(const HTTPSClient::Request &req)
|
|||||||
curl.easy_setopt(handle, CURLOPT_URL, req.url.c_str());
|
curl.easy_setopt(handle, CURLOPT_URL, req.url.c_str());
|
||||||
curl.easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
|
curl.easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
|
||||||
if (req.method == Request::POST)
|
if (req.method == "PUT")
|
||||||
{
|
curl.easy_setopt(handle, CURLOPT_PUT, 1L);
|
||||||
|
else if (req.method == "POST")
|
||||||
curl.easy_setopt(handle, CURLOPT_POST, 1L);
|
curl.easy_setopt(handle, CURLOPT_POST, 1L);
|
||||||
|
else
|
||||||
|
curl.easy_setopt(handle, CURLOPT_CUSTOMREQUEST, req.method.c_str());
|
||||||
|
|
||||||
|
if (req.postdata.size() > 0 && (req.method != "GET" && req.method != "HEAD"))
|
||||||
|
{
|
||||||
curl.easy_setopt(handle, CURLOPT_POSTFIELDS, req.postdata.c_str());
|
curl.easy_setopt(handle, CURLOPT_POSTFIELDS, req.postdata.c_str());
|
||||||
curl.easy_setopt(handle, CURLOPT_POSTFIELDSIZE, req.postdata.size());
|
curl.easy_setopt(handle, CURLOPT_POSTFIELDSIZE, req.postdata.size());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
@@ -7,6 +10,14 @@ extern "C"
|
|||||||
#include "../common/HTTPS.h"
|
#include "../common/HTTPS.h"
|
||||||
#include "../common/config.h"
|
#include "../common/config.h"
|
||||||
|
|
||||||
|
static std::string validMethod[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"};
|
||||||
|
|
||||||
|
static int str_toupper(char c)
|
||||||
|
{
|
||||||
|
unsigned char uc = (unsigned char) c;
|
||||||
|
return toupper(uc);
|
||||||
|
}
|
||||||
|
|
||||||
static std::string w_checkstring(lua_State *L, int idx)
|
static std::string w_checkstring(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -34,20 +45,20 @@ static void w_readheaders(lua_State *L, int idx, HTTPSClient::header_map &header
|
|||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HTTPSClient::Request::Method w_optmethod(lua_State *L, int idx, HTTPSClient::Request::Method defaultMethod)
|
static std::string w_optmethod(lua_State *L, int idx, const std::string &defaultMethod)
|
||||||
{
|
{
|
||||||
|
std::string *const validMethodEnd = validMethod + sizeof(validMethod) / sizeof(std::string);
|
||||||
|
|
||||||
if (lua_isnoneornil(L, idx))
|
if (lua_isnoneornil(L, idx))
|
||||||
return defaultMethod;
|
return defaultMethod;
|
||||||
|
|
||||||
auto str = w_checkstring(L, idx);
|
std::string str = w_checkstring(L, idx);
|
||||||
if (str == "get")
|
std::transform(str.begin(), str.end(), str.begin(), str_toupper);
|
||||||
return HTTPSClient::Request::GET;
|
|
||||||
else if (str == "post")
|
|
||||||
return HTTPSClient::Request::POST;
|
|
||||||
else
|
|
||||||
luaL_argerror(L, idx, "expected one of \"get\" or \"set\"");
|
|
||||||
|
|
||||||
return defaultMethod;
|
if (std::find(validMethod, validMethodEnd, str) == validMethodEnd)
|
||||||
|
luaL_argerror(L, idx, "expected one of \"get\", \"head\", \"post\", \"put\", \"delete\", or \"patch\"");
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int w_request(lua_State *L)
|
static int w_request(lua_State *L)
|
||||||
@@ -61,13 +72,13 @@ static int w_request(lua_State *L)
|
|||||||
{
|
{
|
||||||
advanced = true;
|
advanced = true;
|
||||||
|
|
||||||
HTTPSClient::Request::Method defaultMethod = HTTPSClient::Request::GET;
|
std::string defaultMethod = "GET";
|
||||||
|
|
||||||
lua_getfield(L, 2, "data");
|
lua_getfield(L, 2, "data");
|
||||||
if (!lua_isnoneornil(L, -1))
|
if (!lua_isnoneornil(L, -1))
|
||||||
{
|
{
|
||||||
req.postdata = w_checkstring(L, -1);
|
req.postdata = w_checkstring(L, -1);
|
||||||
defaultMethod = HTTPSClient::Request::POST;
|
defaultMethod = "POST";
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,12 @@ static size_t dequeue(std::vector<char> &buffer, char *data, size_t size)
|
|||||||
size_t remaining = buffer.size() - size;
|
size_t remaining = buffer.size() - size;
|
||||||
|
|
||||||
memcpy(data, &buffer[0], size);
|
memcpy(data, &buffer[0], size);
|
||||||
memmove(&buffer[0], &buffer[size], remaining);
|
|
||||||
buffer.resize(remaining);
|
if (remaining > 0)
|
||||||
|
{
|
||||||
|
memmove(&buffer[0], &buffer[size], remaining);
|
||||||
|
buffer.resize(remaining);
|
||||||
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ static Variant::SharedTable *putSourcesAsSharedTable(std::vector<audio::Source *
|
|||||||
{
|
{
|
||||||
Variant::SharedTable *table = new Variant::SharedTable();
|
Variant::SharedTable *table = new Variant::SharedTable();
|
||||||
|
|
||||||
for (int i = 0; i < sources.size(); i++)
|
for (int i = 0; i < (int) sources.size(); i++)
|
||||||
table->pairs.emplace_back((double) (i + 1), Variant(&Source::type, sources[i]));
|
table->pairs.emplace_back((double) (i + 1), Variant(&Source::type, sources[i]));
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
|
|||||||
@@ -34,19 +34,19 @@ love::Type DataStream::type("DataStream", &Stream::type);
|
|||||||
|
|
||||||
DataStream::DataStream(Data *data)
|
DataStream::DataStream(Data *data)
|
||||||
: data(data)
|
: data(data)
|
||||||
, offset(0)
|
|
||||||
, size(data->getSize())
|
|
||||||
, memory((const uint8 *) data->getData())
|
, memory((const uint8 *) data->getData())
|
||||||
, writableMemory((uint8 *) data->getData()) // TODO: disallow writing sometimes?
|
, writableMemory((uint8 *) data->getData()) // TODO: disallow writing sometimes?
|
||||||
|
, offset(0)
|
||||||
|
, size(data->getSize())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DataStream::DataStream(const DataStream &other)
|
DataStream::DataStream(const DataStream &other)
|
||||||
: data(other.data)
|
: data(other.data)
|
||||||
, offset(0)
|
|
||||||
, size(other.size)
|
|
||||||
, memory(other.memory)
|
, memory(other.memory)
|
||||||
, writableMemory(other.writableMemory)
|
, writableMemory(other.writableMemory)
|
||||||
|
, offset(0)
|
||||||
|
, size(other.size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ int64 DataStream::read(void* data, int64 size)
|
|||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (offset >= getSize())
|
if ((int64) offset >= getSize())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int64 readsize = std::min<int64>(size, getSize() - offset);
|
int64 readsize = std::min<int64>(size, getSize() - offset);
|
||||||
@@ -95,7 +95,7 @@ bool DataStream::write(const void* data, int64 size)
|
|||||||
if (size <= 0 || writableMemory == nullptr)
|
if (size <= 0 || writableMemory == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (offset >= getSize())
|
if ((int64) offset >= getSize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int64 writesize = std::min<int64>(size, getSize() - offset);
|
int64 writesize = std::min<int64>(size, getSize() - offset);
|
||||||
@@ -123,7 +123,7 @@ bool DataStream::seek(int64 pos, SeekOrigin origin)
|
|||||||
else if (origin == SEEKORIGIN_END)
|
else if (origin == SEEKORIGIN_END)
|
||||||
pos += size;
|
pos += size;
|
||||||
|
|
||||||
if (pos < 0 || pos > size)
|
if (pos < 0 || pos > (int64) size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
offset = pos;
|
offset = pos;
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ void Text::addTextData(const TextData &t)
|
|||||||
|
|
||||||
size_t voffset = vertOffset;
|
size_t voffset = vertOffset;
|
||||||
|
|
||||||
// Must be before the early exit below.
|
|
||||||
if (!t.appendVertices)
|
if (!t.appendVertices)
|
||||||
{
|
{
|
||||||
voffset = 0;
|
voffset = 0;
|
||||||
@@ -133,8 +132,8 @@ void Text::addTextData(const TextData &t)
|
|||||||
textData.clear();
|
textData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.useMatrix)
|
if (t.useMatrix && !vertices.empty())
|
||||||
t.matrix.transformXY(&vertices[0], &vertices[0], (int) vertices.size());
|
t.matrix.transformXY(vertices.data(), vertices.data(), (int) vertices.size());
|
||||||
|
|
||||||
uploadVertices(vertices, voffset);
|
uploadVertices(vertices, voffset);
|
||||||
|
|
||||||
|
|||||||
@@ -527,7 +527,7 @@ void Graphics::setActive(bool enable)
|
|||||||
|
|
||||||
void Graphics::setShaderChanged()
|
void Graphics::setShaderChanged()
|
||||||
{
|
{
|
||||||
dirtyRenderState |= STATE_SHADER;
|
dirtyRenderState |= STATEBIT_SHADER;
|
||||||
++shaderSwitches;
|
++shaderSwitches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1414,12 +1414,17 @@ void Graphics::setStencilMode(StencilAction action, CompareMode compare, int val
|
|||||||
if (enablestencil != gl.isStateEnabled(OpenGL::ENABLE_STENCIL_TEST))
|
if (enablestencil != gl.isStateEnabled(OpenGL::ENABLE_STENCIL_TEST))
|
||||||
gl.setEnableState(OpenGL::ENABLE_STENCIL_TEST, enablestencil);
|
gl.setEnableState(OpenGL::ENABLE_STENCIL_TEST, enablestencil);
|
||||||
|
|
||||||
GLenum glaction = GL_REPLACE;
|
GLenum glaction = GL_KEEP;
|
||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
|
case STENCIL_KEEP:
|
||||||
|
glaction = GL_KEEP;
|
||||||
|
break;
|
||||||
|
case STENCIL_ZERO:
|
||||||
|
glaction = GL_ZERO;
|
||||||
|
break;
|
||||||
case STENCIL_REPLACE:
|
case STENCIL_REPLACE:
|
||||||
default:
|
|
||||||
glaction = GL_REPLACE;
|
glaction = GL_REPLACE;
|
||||||
break;
|
break;
|
||||||
case STENCIL_INCREMENT:
|
case STENCIL_INCREMENT:
|
||||||
@@ -1437,6 +1442,9 @@ void Graphics::setStencilMode(StencilAction action, CompareMode compare, int val
|
|||||||
case STENCIL_INVERT:
|
case STENCIL_INVERT:
|
||||||
glaction = GL_INVERT;
|
glaction = GL_INVERT;
|
||||||
break;
|
break;
|
||||||
|
case STENCIL_MAX_ENUM:
|
||||||
|
glaction = GL_KEEP;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -298,20 +298,18 @@ void Texture::createTexture()
|
|||||||
{
|
{
|
||||||
if (isCompressed() && (texType == TEXTURE_2D_ARRAY || texType == TEXTURE_VOLUME))
|
if (isCompressed() && (texType == TEXTURE_2D_ARRAY || texType == TEXTURE_VOLUME))
|
||||||
{
|
{
|
||||||
|
int slicecount = slices.getSliceCount(mip);
|
||||||
size_t mipsize = 0;
|
size_t mipsize = 0;
|
||||||
|
|
||||||
if (texType == TEXTURE_2D_ARRAY || texType == TEXTURE_VOLUME)
|
for (int slice = 0; slice < slicecount; slice++)
|
||||||
{
|
{
|
||||||
for (int slice = 0; slice < slices.getSliceCount(mip); slice++)
|
auto id = slices.get(slice, mip);
|
||||||
{
|
if (id != nullptr)
|
||||||
auto id = slices.get(slice, mip);
|
mipsize += id->getSize();
|
||||||
if (id != nullptr)
|
|
||||||
mipsize += id->getSize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mipsize > 0)
|
if (mipsize > 0)
|
||||||
glCompressedTexImage3D(gltype, mip, fmt.internalformat, w, h, d, 0, mipsize, nullptr);
|
glCompressedTexImage3D(gltype, mip, fmt.internalformat, w, h, slicecount, 0, mipsize, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int slice = 0; slice < slicecount; slice++)
|
for (int slice = 0; slice < slicecount; slice++)
|
||||||
|
|||||||
@@ -25,9 +25,12 @@
|
|||||||
// SDL
|
// SDL
|
||||||
#include <SDL_clipboard.h>
|
#include <SDL_clipboard.h>
|
||||||
#include <SDL_cpuinfo.h>
|
#include <SDL_cpuinfo.h>
|
||||||
#include <SDL_locale.h>
|
|
||||||
#include <SDL_version.h>
|
#include <SDL_version.h>
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||||
|
#include <SDL_locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace system
|
namespace system
|
||||||
|
|||||||
@@ -43,14 +43,14 @@ public:
|
|||||||
virtual ~System() {}
|
virtual ~System() {}
|
||||||
|
|
||||||
// Implements Module.
|
// Implements Module.
|
||||||
const char *getName() const;
|
const char *getName() const override;
|
||||||
|
|
||||||
int getProcessorCount() const;
|
int getProcessorCount() const override;
|
||||||
|
|
||||||
void setClipboardText(const std::string &text) const;
|
void setClipboardText(const std::string &text) const override;
|
||||||
std::string getClipboardText() const;
|
std::string getClipboardText() const override;
|
||||||
|
|
||||||
PowerState getPowerInfo(int &seconds, int &percent) const;
|
PowerState getPowerInfo(int &seconds, int &percent) const override;
|
||||||
std::vector<std::string> getPreferredLocales() const override;
|
std::vector<std::string> getPreferredLocales() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -28,8 +28,13 @@ namespace window
|
|||||||
|
|
||||||
static bool highDPIAllowed = false;
|
static bool highDPIAllowed = false;
|
||||||
|
|
||||||
|
// TODO: find a cleaner way to do this...
|
||||||
|
// The window backend (e.g. love.window.sdl) is expected to implement this.
|
||||||
|
void setHighDPIAllowedImplementation(bool enable);
|
||||||
|
|
||||||
void setHighDPIAllowed(bool enable)
|
void setHighDPIAllowed(bool enable)
|
||||||
{
|
{
|
||||||
|
setHighDPIAllowedImplementation(enable);
|
||||||
highDPIAllowed = enable;
|
highDPIAllowed = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@
|
|||||||
|
|
||||||
#if defined(LOVE_WINDOWS)
|
#if defined(LOVE_WINDOWS)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <dwmapi.h>
|
||||||
|
#include <VersionHelpers.h>
|
||||||
#elif defined(LOVE_MACOS)
|
#elif defined(LOVE_MACOS)
|
||||||
#include "common/macos.h"
|
#include "common/macos.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -53,10 +55,27 @@
|
|||||||
#define APIENTRY
|
#define APIENTRY
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_HINT_WINDOWS_DPI_SCALING
|
||||||
|
#define SDL_HINT_WINDOWS_DPI_SCALING "SDL_WINDOWS_DPI_SCALING"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace window
|
namespace window
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// See src/modules/window/Window.cpp.
|
||||||
|
void setHighDPIAllowedImplementation(bool enable)
|
||||||
|
{
|
||||||
|
#if defined(LOVE_WINDOWS)
|
||||||
|
// Windows uses a different API than SDL_WINDOW_ALLOW_HIGHDPI.
|
||||||
|
// This must be set before the video subsystem is initialized.
|
||||||
|
SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, enable ? "1" : "0");
|
||||||
|
#else
|
||||||
|
LOVE_UNUSED(enable);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
namespace sdl
|
namespace sdl
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -72,12 +91,6 @@ Window::Window()
|
|||||||
, hasSDL203orEarlier(false)
|
, hasSDL203orEarlier(false)
|
||||||
, contextAttribs()
|
, contextAttribs()
|
||||||
{
|
{
|
||||||
// Windows uses a different API than SDL_WINDOW_ALLOW_HIGHDPI.
|
|
||||||
#if defined(LOVE_WINDOWS) && defined(SDL_HINT_WINDOWS_DPI_SCALING)
|
|
||||||
// This must be set before the video subsystem is initialized.
|
|
||||||
SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, isHighDPIAllowed() ? "1" : "0");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
|
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
|
||||||
throw love::Exception("Could not initialize SDL video subsystem (%s)", SDL_GetError());
|
throw love::Exception("Could not initialize SDL video subsystem (%s)", SDL_GetError());
|
||||||
|
|
||||||
@@ -1183,7 +1196,59 @@ bool Window::isMinimized() const
|
|||||||
void Window::swapBuffers()
|
void Window::swapBuffers()
|
||||||
{
|
{
|
||||||
if (glcontext)
|
if (glcontext)
|
||||||
|
{
|
||||||
|
#ifdef LOVE_WINDOWS
|
||||||
|
bool useDwmFlush = false;
|
||||||
|
int swapInterval = getVSync();
|
||||||
|
|
||||||
|
// https://github.com/love2d/love/issues/1628
|
||||||
|
// VSync can interact badly with Windows desktop composition (DWM) in windowed mode. DwmFlush can be used instead
|
||||||
|
// of vsync, but it's much less flexible so we're very conservative here with where it's used:
|
||||||
|
// - It won't work with exclusive or desktop fullscreen.
|
||||||
|
// - DWM refreshes don't always match the refresh rate of the monitor the window is in (or the requested swap
|
||||||
|
// interval), so we only use it when they do match.
|
||||||
|
// - The user may force GL vsync, and DwmFlush shouldn't be used together with GL vsync.
|
||||||
|
if (!settings.fullscreen && swapInterval == 1)
|
||||||
|
{
|
||||||
|
// Desktop composition is always enabled in Windows 8+. But DwmIsCompositionEnabled won't always return true...
|
||||||
|
// (see DwmIsCompositionEnabled docs).
|
||||||
|
BOOL compositionEnabled = IsWindows8OrGreater();
|
||||||
|
if (compositionEnabled || (SUCCEEDED(DwmIsCompositionEnabled(&compositionEnabled)) && compositionEnabled))
|
||||||
|
{
|
||||||
|
DWM_TIMING_INFO info = {};
|
||||||
|
info.cbSize = sizeof(DWM_TIMING_INFO);
|
||||||
|
double dwmRefreshRate = 0;
|
||||||
|
if (SUCCEEDED(DwmGetCompositionTimingInfo(nullptr, &info)))
|
||||||
|
dwmRefreshRate = (double)info.rateRefresh.uiNumerator / (double)info.rateRefresh.uiDenominator;
|
||||||
|
|
||||||
|
SDL_DisplayMode dmode = {};
|
||||||
|
int displayindex = SDL_GetWindowDisplayIndex(window);
|
||||||
|
|
||||||
|
if (displayindex >= 0)
|
||||||
|
SDL_GetCurrentDisplayMode(displayindex, &dmode);
|
||||||
|
|
||||||
|
if (dmode.refresh_rate > 0 && dwmRefreshRate > 0 && (fabs(dmode.refresh_rate - dwmRefreshRate) < 2))
|
||||||
|
{
|
||||||
|
SDL_GL_SetSwapInterval(0);
|
||||||
|
if (SDL_GL_GetSwapInterval() == 0)
|
||||||
|
useDwmFlush = true;
|
||||||
|
else
|
||||||
|
SDL_GL_SetSwapInterval(swapInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
|
|
||||||
|
#ifdef LOVE_WINDOWS
|
||||||
|
if (useDwmFlush)
|
||||||
|
{
|
||||||
|
DwmFlush();
|
||||||
|
SDL_GL_SetSwapInterval(swapInterval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::hasFocus() const
|
bool Window::hasFocus() const
|
||||||
|
|||||||
Reference in New Issue
Block a user