mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Update metal backend for Image+Canvas->Texture changes
This commit is contained in:
@@ -781,8 +781,6 @@
|
||||
FA18CED723DBC6E000263725 /* Shader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA18CECD23DBC6E000263725 /* Shader.h */; };
|
||||
FA18CED823DBC6E000263725 /* StreamBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CECE23DBC6E000263725 /* StreamBuffer.mm */; };
|
||||
FA18CED923DBC6E000263725 /* StreamBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CECE23DBC6E000263725 /* StreamBuffer.mm */; };
|
||||
FA18CEDA23DBC6E000263725 /* Canvas.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CECF23DBC6E000263725 /* Canvas.mm */; };
|
||||
FA18CEDB23DBC6E000263725 /* Canvas.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CECF23DBC6E000263725 /* Canvas.mm */; };
|
||||
FA18CEDC23DBC6E000263725 /* Metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CED023DBC6E000263725 /* Metal.mm */; };
|
||||
FA18CEDD23DBC6E000263725 /* Metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CED023DBC6E000263725 /* Metal.mm */; };
|
||||
FA18CEDE23DBC6E000263725 /* Shader.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CED123DBC6E000263725 /* Shader.mm */; };
|
||||
@@ -792,13 +790,11 @@
|
||||
FA18CEE223DBC6E000263725 /* Graphics.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CED323DBC6E000263725 /* Graphics.mm */; };
|
||||
FA18CEE323DBC6E000263725 /* Metal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA18CED423DBC6E000263725 /* Metal.h */; };
|
||||
FA18CEE423DBC6E000263725 /* Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FA18CED523DBC6E000263725 /* Graphics.h */; };
|
||||
FA18CEE523DBC6E000263725 /* Canvas.h in Headers */ = {isa = PBXBuildFile; fileRef = FA18CED623DBC6E000263725 /* Canvas.h */; };
|
||||
FA18CEE723DBC6F700263725 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA18CEE623DBC6F700263725 /* Metal.framework */; };
|
||||
FA18CEE923DBC8D400263725 /* Buffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEE823DBC8D400263725 /* Buffer.mm */; };
|
||||
FA18CEEA23DBC8D400263725 /* Buffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEE823DBC8D400263725 /* Buffer.mm */; };
|
||||
FA18CEEE23DC9B3E00263725 /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = FA18CEEC23DC9B3E00263725 /* Image.h */; };
|
||||
FA18CEEF23DC9B3E00263725 /* Image.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEED23DC9B3E00263725 /* Image.mm */; };
|
||||
FA18CEF023DC9B3E00263725 /* Image.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEED23DC9B3E00263725 /* Image.mm */; };
|
||||
FA18CEEF23DC9B3E00263725 /* Texture.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEED23DC9B3E00263725 /* Texture.mm */; };
|
||||
FA18CEF023DC9B3E00263725 /* Texture.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEED23DC9B3E00263725 /* Texture.mm */; };
|
||||
FA18CF1623DCF67900263725 /* spirv_parser.hpp in Headers */ = {isa = PBXBuildFile; fileRef = FA18CEF223DCF67800263725 /* spirv_parser.hpp */; };
|
||||
FA18CF1723DCF67900263725 /* spirv_glsl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEF323DCF67800263725 /* spirv_glsl.cpp */; };
|
||||
FA18CF1823DCF67900263725 /* spirv_glsl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA18CEF323DCF67800263725 /* spirv_glsl.cpp */; };
|
||||
@@ -1855,19 +1851,17 @@
|
||||
FA15DFAB1F9B8C850042AB22 /* StringMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringMap.cpp; sourceTree = "<group>"; };
|
||||
FA18CECD23DBC6E000263725 /* Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shader.h; sourceTree = "<group>"; };
|
||||
FA18CECE23DBC6E000263725 /* StreamBuffer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StreamBuffer.mm; sourceTree = "<group>"; };
|
||||
FA18CECF23DBC6E000263725 /* Canvas.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Canvas.mm; sourceTree = "<group>"; };
|
||||
FA18CED023DBC6E000263725 /* Metal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Metal.mm; sourceTree = "<group>"; };
|
||||
FA18CED123DBC6E000263725 /* Shader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Shader.mm; sourceTree = "<group>"; };
|
||||
FA18CED223DBC6E000263725 /* StreamBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamBuffer.h; sourceTree = "<group>"; };
|
||||
FA18CED323DBC6E000263725 /* Graphics.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Graphics.mm; sourceTree = "<group>"; };
|
||||
FA18CED423DBC6E000263725 /* Metal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metal.h; sourceTree = "<group>"; };
|
||||
FA18CED523DBC6E000263725 /* Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Graphics.h; sourceTree = "<group>"; };
|
||||
FA18CED623DBC6E000263725 /* Canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Canvas.h; sourceTree = "<group>"; };
|
||||
FA18CEE623DBC6F700263725 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
|
||||
FA18CEE823DBC8D400263725 /* Buffer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Buffer.mm; sourceTree = "<group>"; };
|
||||
FA18CEEB23DBC8EB00263725 /* Buffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Buffer.h; sourceTree = "<group>"; };
|
||||
FA18CEEC23DC9B3E00263725 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = "<group>"; };
|
||||
FA18CEED23DC9B3E00263725 /* Image.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Image.mm; sourceTree = "<group>"; };
|
||||
FA18CEEC23DC9B3E00263725 /* Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Texture.h; sourceTree = "<group>"; };
|
||||
FA18CEED23DC9B3E00263725 /* Texture.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Texture.mm; sourceTree = "<group>"; };
|
||||
FA18CEF223DCF67800263725 /* spirv_parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = spirv_parser.hpp; sourceTree = "<group>"; };
|
||||
FA18CEF323DCF67800263725 /* spirv_glsl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spirv_glsl.cpp; sourceTree = "<group>"; };
|
||||
FA18CEF423DCF67800263725 /* spirv_cross_error_handling.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = spirv_cross_error_handling.hpp; sourceTree = "<group>"; };
|
||||
@@ -3473,12 +3467,8 @@
|
||||
children = (
|
||||
FA18CEEB23DBC8EB00263725 /* Buffer.h */,
|
||||
FA18CEE823DBC8D400263725 /* Buffer.mm */,
|
||||
FA18CED623DBC6E000263725 /* Canvas.h */,
|
||||
FA18CECF23DBC6E000263725 /* Canvas.mm */,
|
||||
FA18CED523DBC6E000263725 /* Graphics.h */,
|
||||
FA18CED323DBC6E000263725 /* Graphics.mm */,
|
||||
FA18CEEC23DC9B3E00263725 /* Image.h */,
|
||||
FA18CEED23DC9B3E00263725 /* Image.mm */,
|
||||
FA18CED423DBC6E000263725 /* Metal.h */,
|
||||
FA18CED023DBC6E000263725 /* Metal.mm */,
|
||||
FA18CECD23DBC6E000263725 /* Shader.h */,
|
||||
@@ -3487,6 +3477,8 @@
|
||||
FA18CF4423DD1A8000263725 /* ShaderStage.mm */,
|
||||
FA18CED223DBC6E000263725 /* StreamBuffer.h */,
|
||||
FA18CECE23DBC6E000263725 /* StreamBuffer.mm */,
|
||||
FA18CEEC23DC9B3E00263725 /* Texture.h */,
|
||||
FA18CEED23DC9B3E00263725 /* Texture.mm */,
|
||||
);
|
||||
path = metal;
|
||||
sourceTree = "<group>";
|
||||
@@ -4141,7 +4133,6 @@
|
||||
FA0B7E2F1A95902C000E1D17 /* RopeJoint.h in Headers */,
|
||||
FA0B7D141A95902C000E1D17 /* Font.h in Headers */,
|
||||
FA0B7E591A95902C000E1D17 /* wrap_Joint.h in Headers */,
|
||||
FA18CEE523DBC6E000263725 /* Canvas.h in Headers */,
|
||||
FA0B7A631A958EA3000E1D17 /* b2ContactManager.h in Headers */,
|
||||
FA0B7E771A95902C000E1D17 /* wrap_WeldJoint.h in Headers */,
|
||||
FA0B7A911A958EA3000E1D17 /* b2FrictionJoint.h in Headers */,
|
||||
@@ -4600,7 +4591,6 @@
|
||||
FA0B7A3F1A958EA3000E1D17 /* b2ChainShape.cpp in Sources */,
|
||||
FA0B7E921A95902C000E1D17 /* ModPlugDecoder.cpp in Sources */,
|
||||
FA0B7E521A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */,
|
||||
FA18CEDB23DBC6E000263725 /* Canvas.mm in Sources */,
|
||||
FADF54351E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */,
|
||||
FA4F2BB51DE1E4C300CA37D7 /* wrap_RecordingDevice.cpp in Sources */,
|
||||
FA0B7A311A958EA3000E1D17 /* b2CollidePolygon.cpp in Sources */,
|
||||
@@ -4700,7 +4690,7 @@
|
||||
FA0B7CD41A95902C000E1D17 /* Source.cpp in Sources */,
|
||||
FAA3A9AF1B7D465A00CED060 /* android.cpp in Sources */,
|
||||
FAE64A812071363100BC7981 /* physfs_archiver_dir.c in Sources */,
|
||||
FA18CEF023DC9B3E00263725 /* Image.mm in Sources */,
|
||||
FA18CEF023DC9B3E00263725 /* Texture.mm in Sources */,
|
||||
FA0B7CD11A95902C000E1D17 /* Audio.cpp in Sources */,
|
||||
FA4F2B7B1DE0181B00CA37D7 /* xxhash.c in Sources */,
|
||||
FA0B7D131A95902C000E1D17 /* Font.cpp in Sources */,
|
||||
@@ -4984,7 +4974,6 @@
|
||||
FA0B7E0F1A95902C000E1D17 /* FrictionJoint.cpp in Sources */,
|
||||
FA620A351AA2F8DB005DB4C2 /* wrap_Texture.cpp in Sources */,
|
||||
FAF140771E20934C00F898D2 /* iomapper.cpp in Sources */,
|
||||
FA18CEDA23DBC6E000263725 /* Canvas.mm in Sources */,
|
||||
FA0B7D091A95902C000E1D17 /* wrap_FileData.cpp in Sources */,
|
||||
FA18CEDC23DBC6E000263725 /* Metal.mm in Sources */,
|
||||
FA0B7B341A958EA3000E1D17 /* wuff_convert.c in Sources */,
|
||||
@@ -5310,7 +5299,7 @@
|
||||
FA0B7D281A95902C000E1D17 /* wrap_GlyphData.cpp in Sources */,
|
||||
FA0B7DE21A95902C000E1D17 /* wrap_RandomGenerator.cpp in Sources */,
|
||||
FAF6C9F223C2DE2900D7B5BC /* SPVRemapper.cpp in Sources */,
|
||||
FA18CEEF23DC9B3E00263725 /* Image.mm in Sources */,
|
||||
FA18CEEF23DC9B3E00263725 /* Texture.mm in Sources */,
|
||||
FACA02F61F5E396B0084B28F /* wrap_DataModule.cpp in Sources */,
|
||||
FA0B79401A958E3B000E1D17 /* utf8.cpp in Sources */,
|
||||
FA0B79241A958E3B000E1D17 /* Exception.cpp in Sources */,
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2020 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace metal
|
||||
{
|
||||
|
||||
Canvas::Canvas(id<MTLDevice> device, const Settings &settings)
|
||||
: love::graphics::Canvas(settings)
|
||||
{ @autoreleasepool {
|
||||
MTLTextureDescriptor *desc = [MTLTextureDescriptor new];
|
||||
|
||||
// TODO: sampleCount validation
|
||||
desc.sampleCount = getRequestedMSAA();
|
||||
|
||||
desc.width = pixelWidth;
|
||||
desc.height = pixelHeight;
|
||||
desc.depth = depth;
|
||||
desc.arrayLength = layers;
|
||||
desc.mipmapLevelCount = mipmapCount;
|
||||
desc.textureType = Metal::getTextureType(texType, getRequestedMSAA());
|
||||
|
||||
bool sRGB = false;
|
||||
desc.pixelFormat = Metal::convertPixelFormat(format, sRGB);
|
||||
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
desc.usage = MTLTextureUsageRenderTarget;
|
||||
|
||||
if (isReadable())
|
||||
desc.usage |= MTLTextureUsageShaderRead;
|
||||
|
||||
texture = [device newTextureWithDescriptor:desc];
|
||||
|
||||
if (texture == nil)
|
||||
throw love::Exception("Out of graphics memory.");
|
||||
|
||||
// TODO: initialize texture to transparent black.
|
||||
}}
|
||||
|
||||
Canvas::~Canvas()
|
||||
{ @autoreleasepool {
|
||||
texture = nil;
|
||||
}}
|
||||
|
||||
void Canvas::generateMipmaps()
|
||||
{ @autoreleasepool {
|
||||
id<MTLBlitCommandEncoder> encoder = Graphics::getInstance()->useBlitEncoder();
|
||||
[encoder generateMipmapsForTexture:texture];
|
||||
}}
|
||||
|
||||
} // metal
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -40,9 +40,7 @@ public:
|
||||
// Implements Module.
|
||||
const char *getName() const override { return "love.graphics.metal"; }
|
||||
|
||||
love::graphics::Image *newImage(const Image::Slices &data, const Image::Settings &settings) override;
|
||||
love::graphics::Image *newImage(TextureType textype, PixelFormat format, int width, int height, int slices, const Image::Settings &settings) override;
|
||||
love::graphics::Canvas *newCanvas(const Canvas::Settings &settings) override;
|
||||
love::graphics::Texture *newTexture(const Texture::Settings &settings, const Texture::Slices *data = nullptr) override;
|
||||
love::graphics::Buffer *newBuffer(size_t size, const void *data, BufferType type, vertex::Usage usage, uint32 mapflags) override;
|
||||
|
||||
void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
|
||||
@@ -53,7 +51,7 @@ public:
|
||||
|
||||
void draw(const DrawCommand &cmd) override;
|
||||
void draw(const DrawIndexedCommand &cmd) override;
|
||||
void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture) override;
|
||||
void drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, love::graphics::Texture *texture) override;
|
||||
|
||||
void clear(OptionalColorf color, OptionalInt stencil, OptionalDouble depth) override;
|
||||
void clear(const std::vector<OptionalColorf> &colors, OptionalInt stencil, OptionalDouble depth) override;
|
||||
@@ -83,10 +81,9 @@ public:
|
||||
void setPointSize(float size) override;
|
||||
|
||||
void setWireframe(bool enable) override;
|
||||
|
||||
bool isCanvasFormatSupported(PixelFormat format) const override;
|
||||
bool isCanvasFormatSupported(PixelFormat format, bool readable) const override;
|
||||
bool isImageFormatSupported(PixelFormat format, bool sRGB) const override;
|
||||
|
||||
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const override;
|
||||
bool isPixelFormatSupported(PixelFormat format, bool rendertarget, bool readable, bool sRGB = false) override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
RendererInfo getRendererInfo() const override;
|
||||
@@ -105,7 +102,7 @@ public:
|
||||
id<MTLBlitCommandEncoder> getBlitEncoder() const { return blitEncoder; }
|
||||
void submitBlitEncoder();
|
||||
|
||||
id<MTLSamplerState> getCachedSampler(const Texture::Filter &f, const Texture::Wrap &w, float maxAnisotropy, Optional<CompareMode> depthSampleMode);
|
||||
id<MTLSamplerState> getCachedSampler(const SamplerState &s);
|
||||
|
||||
static Graphics *getInstance() { return Module::getInstance<Graphics>(M_GRAPHICS); }
|
||||
|
||||
@@ -164,7 +161,7 @@ private:
|
||||
love::graphics::ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
|
||||
love::graphics::Shader *newShaderInternal(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel) override;
|
||||
love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override;
|
||||
void setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) override;
|
||||
void setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) override;
|
||||
void initCapabilities() override;
|
||||
void getAPIStats(int &shaderswitches) const override;
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
#include "Graphics.h"
|
||||
#include "StreamBuffer.h"
|
||||
#include "Buffer.h"
|
||||
#include "Canvas.h"
|
||||
#include "Image.h"
|
||||
#include "Texture.h"
|
||||
#include "Shader.h"
|
||||
#include "window/Window.h"
|
||||
#include "image/Image.h"
|
||||
@@ -34,44 +33,43 @@ namespace graphics
|
||||
namespace metal
|
||||
{
|
||||
|
||||
static MTLSamplerMinMagFilter getMTLSamplerFilter(Texture::FilterMode mode)
|
||||
static MTLSamplerMinMagFilter getMTLSamplerFilter(SamplerState::FilterMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case Texture::FILTER_NONE: return MTLSamplerMinMagFilterLinear;
|
||||
case Texture::FILTER_LINEAR: return MTLSamplerMinMagFilterLinear;
|
||||
case Texture::FILTER_NEAREST: return MTLSamplerMinMagFilterNearest;
|
||||
case Texture::FILTER_MAX_ENUM: return MTLSamplerMinMagFilterLinear;
|
||||
case SamplerState::FILTER_LINEAR: return MTLSamplerMinMagFilterLinear;
|
||||
case SamplerState::FILTER_NEAREST: return MTLSamplerMinMagFilterNearest;
|
||||
case SamplerState::FILTER_MAX_ENUM: return MTLSamplerMinMagFilterLinear;
|
||||
}
|
||||
return MTLSamplerMinMagFilterLinear;
|
||||
}
|
||||
|
||||
static MTLSamplerMipFilter getMTLSamplerMipFilter(Texture::FilterMode mode)
|
||||
static MTLSamplerMipFilter getMTLSamplerMipFilter(SamplerState::MipmapFilterMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case Texture::FILTER_NONE: return MTLSamplerMipFilterNotMipmapped;
|
||||
case Texture::FILTER_LINEAR: return MTLSamplerMipFilterLinear;
|
||||
case Texture::FILTER_NEAREST: return MTLSamplerMipFilterNearest;
|
||||
case Texture::FILTER_MAX_ENUM: return MTLSamplerMipFilterNotMipmapped;
|
||||
case SamplerState::MIPMAP_FILTER_NONE: return MTLSamplerMipFilterNotMipmapped;
|
||||
case SamplerState::MIPMAP_FILTER_LINEAR: return MTLSamplerMipFilterLinear;
|
||||
case SamplerState::MIPMAP_FILTER_NEAREST: return MTLSamplerMipFilterNearest;
|
||||
case SamplerState::MIPMAP_FILTER_MAX_ENUM: return MTLSamplerMipFilterNotMipmapped;
|
||||
}
|
||||
return MTLSamplerMipFilterNotMipmapped;
|
||||
}
|
||||
|
||||
static MTLSamplerAddressMode getMTLSamplerAddressMode(Texture::WrapMode mode)
|
||||
static MTLSamplerAddressMode getMTLSamplerAddressMode(SamplerState::WrapMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case Texture::WRAP_CLAMP: return MTLSamplerAddressModeClampToEdge;
|
||||
case Texture::WRAP_CLAMP_ZERO: return MTLSamplerAddressModeClampToZero;
|
||||
case SamplerState::WRAP_CLAMP: return MTLSamplerAddressModeClampToEdge;
|
||||
case SamplerState::WRAP_CLAMP_ZERO: return MTLSamplerAddressModeClampToZero;
|
||||
#ifdef LOVE_MACOS
|
||||
case Texture::WRAP_CLAMP_ONE: return MTLSamplerAddressModeClampToBorderColor;
|
||||
case SamplerState::WRAP_CLAMP_ONE: return MTLSamplerAddressModeClampToBorderColor;
|
||||
#else
|
||||
case Texture::WRAP_CLAMP_ONE: return MTLSamplerAddressModeClampToZero;
|
||||
case SamplerState::WRAP_CLAMP_ONE: return MTLSamplerAddressModeClampToZero;
|
||||
#endif
|
||||
case Texture::WRAP_REPEAT: return MTLSamplerAddressModeRepeat;
|
||||
case Texture::WRAP_MIRRORED_REPEAT: return MTLSamplerAddressModeMirrorRepeat;
|
||||
case Texture::WRAP_MAX_ENUM: return MTLSamplerAddressModeClampToEdge;
|
||||
case SamplerState::WRAP_REPEAT: return MTLSamplerAddressModeRepeat;
|
||||
case SamplerState::WRAP_MIRRORED_REPEAT: return MTLSamplerAddressModeMirrorRepeat;
|
||||
case SamplerState::WRAP_MAX_ENUM: return MTLSamplerAddressModeClampToEdge;
|
||||
}
|
||||
return MTLSamplerAddressModeClampToEdge;
|
||||
}
|
||||
@@ -202,19 +200,9 @@ love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferType type, size_t
|
||||
return CreateStreamBuffer(device, type, size);
|
||||
}
|
||||
|
||||
love::graphics::Image *Graphics::newImage(const Image::Slices &data, const Image::Settings &settings)
|
||||
love::graphics::Texture *Graphics::newTexture(const Texture::Settings &settings, const Texture::Slices *data)
|
||||
{
|
||||
return new Image(device, data, settings);
|
||||
}
|
||||
|
||||
love::graphics::Image *Graphics::newImage(TextureType textype, PixelFormat format, int width, int height, int slices, const Image::Settings &settings)
|
||||
{
|
||||
return new Image(device, textype, format, width, height, slices, settings);
|
||||
}
|
||||
|
||||
love::graphics::Canvas *Graphics::newCanvas(const Canvas::Settings &settings)
|
||||
{
|
||||
return new Canvas(device, settings);
|
||||
return new Texture(device, settings, data);
|
||||
}
|
||||
|
||||
love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles)
|
||||
@@ -245,9 +233,9 @@ void Graphics::initCapabilities()
|
||||
}
|
||||
}
|
||||
|
||||
capabilities.features[FEATURE_MULTI_CANVAS_FORMATS] = true;
|
||||
capabilities.features[FEATURE_MULTI_RENDER_TARGET_FORMATS] = true;
|
||||
capabilities.features[FEATURE_CLAMP_ZERO] = true;
|
||||
capabilities.features[FEATURE_BLENDMINMAX] = true;
|
||||
capabilities.features[FEATURE_BLEND_MINMAX] = true;
|
||||
capabilities.features[FEATURE_LIGHTEN] = true;
|
||||
capabilities.features[FEATURE_FULL_NPOT] = true;
|
||||
capabilities.features[FEATURE_PIXEL_SHADER_HIGHP] = true;
|
||||
@@ -263,8 +251,8 @@ void Graphics::initCapabilities()
|
||||
capabilities.limits[LIMIT_TEXTURE_LAYERS] = 2048;
|
||||
capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = 2048;
|
||||
capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = 16384; // TODO
|
||||
capabilities.limits[LIMIT_MULTI_CANVAS] = 8; // TODO
|
||||
capabilities.limits[LIMIT_CANVAS_MSAA] = msaa;
|
||||
capabilities.limits[LIMIT_RENDER_TARGETS] = 8; // TODO
|
||||
capabilities.limits[LIMIT_TEXTURE_MSAA] = msaa;
|
||||
capabilities.limits[LIMIT_ANISOTROPY] = 16.0f;
|
||||
static_assert(LIMIT_MAX_ENUM == 8, "Graphics::initCapabilities must be updated when adding a new system limit!");
|
||||
|
||||
@@ -279,7 +267,7 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
|
||||
this->pixelWidth = pixelwidth;
|
||||
this->pixelHeight = pixelheight;
|
||||
|
||||
if (!isCanvasActive())
|
||||
if (!isRenderTargetActive())
|
||||
{
|
||||
dirtyRenderState |= STATEBIT_VIEWPORT | STATEBIT_SCISSOR;
|
||||
|
||||
@@ -343,10 +331,10 @@ void Graphics::unSetMode()
|
||||
|
||||
submitCommandBuffer();
|
||||
|
||||
for (auto temp : temporaryCanvases)
|
||||
temp.canvas->release();
|
||||
for (auto temp : temporaryTextures)
|
||||
temp.texture->release();
|
||||
|
||||
temporaryCanvases.clear();
|
||||
temporaryTextures.clear();
|
||||
|
||||
created = false;
|
||||
}
|
||||
@@ -418,28 +406,31 @@ void Graphics::submitBlitEncoder()
|
||||
}
|
||||
}
|
||||
|
||||
id<MTLSamplerState> Graphics::getCachedSampler(const Texture::Filter &f, const Texture::Wrap &w, float maxAnisotropy, Optional<CompareMode> depthSampleMode)
|
||||
id<MTLSamplerState> Graphics::getCachedSampler(const SamplerState &s)
|
||||
{ @autoreleasepool {
|
||||
id<MTLSamplerState> sampler = nil;
|
||||
|
||||
{
|
||||
MTLSamplerDescriptor *desc = [MTLSamplerDescriptor new];
|
||||
|
||||
desc.minFilter = getMTLSamplerFilter(f.min);
|
||||
desc.magFilter = getMTLSamplerFilter(f.mag);
|
||||
desc.mipFilter = getMTLSamplerMipFilter(f.mipmap);
|
||||
desc.maxAnisotropy = std::max(1.0f, std::min(maxAnisotropy, 16.0f));
|
||||
desc.minFilter = getMTLSamplerFilter(s.minFilter);
|
||||
desc.magFilter = getMTLSamplerFilter(s.magFilter);
|
||||
desc.mipFilter = getMTLSamplerMipFilter(s.mipmapFilter);
|
||||
desc.maxAnisotropy = std::max(1.0f, std::min((float)s.maxAnisotropy, 16.0f));
|
||||
|
||||
desc.sAddressMode = getMTLSamplerAddressMode(w.s);
|
||||
desc.tAddressMode = getMTLSamplerAddressMode(w.t);
|
||||
desc.rAddressMode = getMTLSamplerAddressMode(w.r);
|
||||
desc.sAddressMode = getMTLSamplerAddressMode(s.wrapU);
|
||||
desc.tAddressMode = getMTLSamplerAddressMode(s.wrapV);
|
||||
desc.rAddressMode = getMTLSamplerAddressMode(s.wrapW);
|
||||
|
||||
#ifdef LOVE_MACOS
|
||||
desc.borderColor = MTLSamplerBorderColorOpaqueWhite;
|
||||
#endif
|
||||
|
||||
if (depthSampleMode.hasValue)
|
||||
desc.compareFunction = getMTLCompareFunction(depthSampleMode.value);
|
||||
desc.lodMinClamp = s.minLod;
|
||||
desc.lodMaxClamp = s.maxLod;
|
||||
|
||||
if (s.depthSampleMode.hasValue)
|
||||
desc.compareFunction = getMTLCompareFunction(s.depthSampleMode.value);
|
||||
|
||||
sampler = [device newSamplerStateWithDescriptor:desc];
|
||||
}
|
||||
@@ -531,10 +522,10 @@ void Graphics::applyRenderState(id<MTLRenderCommandEncoder> encoder)
|
||||
int rth = 0;
|
||||
|
||||
const auto &rt = state.renderTargets.getFirstTarget();
|
||||
if (rt.canvas.get())
|
||||
if (rt.texture.get())
|
||||
{
|
||||
rtw = rt.canvas->getPixelWidth();
|
||||
rth = rt.canvas->getPixelHeight();
|
||||
rtw = rt.texture->getPixelWidth();
|
||||
rth = rt.texture->getPixelHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -653,7 +644,7 @@ void Graphics::draw(const DrawIndexedCommand &cmd)
|
||||
instanceCount:cmd.instanceCount];
|
||||
}}
|
||||
|
||||
void Graphics::drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, Texture *texture)
|
||||
void Graphics::drawQuads(int start, int count, const vertex::Attributes &attributes, const vertex::BufferBindings &buffers, love::graphics::Texture *texture)
|
||||
{ @autoreleasepool {
|
||||
const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
|
||||
const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
|
||||
@@ -693,7 +684,7 @@ void Graphics::drawQuads(int start, int count, const vertex::Attributes &attribu
|
||||
}
|
||||
}}
|
||||
|
||||
void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas)
|
||||
void Graphics::setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas)
|
||||
{
|
||||
const DisplayState &state = states.back();
|
||||
// TODO
|
||||
@@ -707,7 +698,7 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix
|
||||
void Graphics::endPass()
|
||||
{
|
||||
auto &rts = states.back().renderTargets;
|
||||
love::graphics::Canvas *depthstencil = rts.depthStencil.canvas.get();
|
||||
love::graphics::Texture *depthstencil = rts.depthStencil.texture.get();
|
||||
|
||||
// Discard the depth/stencil buffer if we're using an internal cached one.
|
||||
if (depthstencil == nullptr && (rts.temporaryRTFlags & (TEMPORARY_RT_DEPTH | TEMPORARY_RT_STENCIL)) != 0)
|
||||
@@ -715,15 +706,15 @@ void Graphics::endPass()
|
||||
|
||||
// Resolve MSAA buffers. MSAA is only supported for 2D render targets so we
|
||||
// don't have to worry about resolving to slices.
|
||||
if (rts.colors.size() > 0 && rts.colors[0].canvas->getMSAA() > 1)
|
||||
if (rts.colors.size() > 0 && rts.colors[0].texture->getMSAA() > 1)
|
||||
{
|
||||
int mip = rts.colors[0].mipmap;
|
||||
int w = rts.colors[0].canvas->getPixelWidth(mip);
|
||||
int h = rts.colors[0].canvas->getPixelHeight(mip);
|
||||
int w = rts.colors[0].texture->getPixelWidth(mip);
|
||||
int h = rts.colors[0].texture->getPixelHeight(mip);
|
||||
|
||||
for (int i = 0; i < (int) rts.colors.size(); i++)
|
||||
{
|
||||
Canvas *c = (Canvas *) rts.colors[i].canvas.get();
|
||||
Texture *c = (Texture *) rts.colors[i].texture.get();
|
||||
|
||||
if (!c->isReadable())
|
||||
continue;
|
||||
@@ -739,12 +730,12 @@ void Graphics::endPass()
|
||||
|
||||
for (const auto &rt : rts.colors)
|
||||
{
|
||||
if (rt.canvas->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0)
|
||||
rt.canvas->generateMipmaps();
|
||||
if (rt.texture->getMipmapsMode() == Texture::MIPMAPS_AUTO && rt.mipmap == 0)
|
||||
rt.texture->generateMipmaps();
|
||||
}
|
||||
|
||||
int dsmipmap = rts.depthStencil.mipmap;
|
||||
if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAPS_AUTO && dsmipmap == 0)
|
||||
if (depthstencil != nullptr && depthstencil->getMipmapsMode() == Texture::MIPMAPS_AUTO && dsmipmap == 0)
|
||||
depthstencil->generateMipmaps();
|
||||
}
|
||||
|
||||
@@ -786,8 +777,8 @@ void Graphics::present(void *screenshotCallbackData)
|
||||
if (!isActive())
|
||||
return;
|
||||
|
||||
if (isCanvasActive())
|
||||
throw love::Exception("present cannot be called while a Canvas is active.");
|
||||
if (isRenderTargetActive())
|
||||
throw love::Exception("present cannot be called while a render target is active.");
|
||||
|
||||
deprecations.draw(this);
|
||||
|
||||
@@ -865,20 +856,20 @@ void Graphics::present(void *screenshotCallbackData)
|
||||
// Reset the per-frame stat counts.
|
||||
drawCalls = 0;
|
||||
//gl.stats.shaderSwitches = 0;
|
||||
canvasSwitchCount = 0;
|
||||
renderTargetSwitchCount = 0;
|
||||
drawCallsBatched = 0;
|
||||
|
||||
// This assumes temporary canvases will only be used within a render pass.
|
||||
for (int i = (int) temporaryCanvases.size() - 1; i >= 0; i--)
|
||||
for (int i = (int) temporaryTextures.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (temporaryCanvases[i].framesSinceUse >= MAX_TEMPORARY_CANVAS_UNUSED_FRAMES)
|
||||
if (temporaryTextures[i].framesSinceUse >= MAX_TEMPORARY_TEXTURE_UNUSED_FRAMES)
|
||||
{
|
||||
temporaryCanvases[i].canvas->release();
|
||||
temporaryCanvases[i] = temporaryCanvases.back();
|
||||
temporaryCanvases.pop_back();
|
||||
temporaryTextures[i].texture->release();
|
||||
temporaryTextures[i] = temporaryTextures.back();
|
||||
temporaryTextures.pop_back();
|
||||
}
|
||||
else
|
||||
temporaryCanvases[i].framesSinceUse++;
|
||||
temporaryTextures[i].framesSinceUse++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,11 +897,11 @@ void Graphics::setScissor()
|
||||
void Graphics::drawToStencilBuffer(StencilAction action, int value)
|
||||
{
|
||||
const auto &rts = states.back().renderTargets;
|
||||
love::graphics::Canvas *dscanvas = rts.depthStencil.canvas.get();
|
||||
love::graphics::Texture *dstexture = rts.depthStencil.texture.get();
|
||||
|
||||
if (!isCanvasActive() && !windowHasStencil)
|
||||
if (!isRenderTargetActive() && !windowHasStencil)
|
||||
throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer.");
|
||||
else if (isCanvasActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dscanvas == nullptr || !isPixelFormatStencil(dscanvas->getPixelFormat())))
|
||||
else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dstexture == nullptr || !isPixelFormatStencil(dstexture->getPixelFormat())))
|
||||
throw love::Exception("Drawing to the stencil buffer with a Canvas active requires either stencil=true or a custom stencil-type Canvas to be used, in setCanvas.");
|
||||
|
||||
flushStreamDraws();
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2020 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/Color.h"
|
||||
#include "common/int.h"
|
||||
#include "graphics/Image.h"
|
||||
#include "Metal.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
namespace metal
|
||||
{
|
||||
|
||||
class Image final : public love::graphics::Image
|
||||
{
|
||||
public:
|
||||
|
||||
Image(id<MTLDevice> device, const Slices &data, const Settings &settings);
|
||||
Image(id<MTLDevice> device, TextureType textype, PixelFormat format, int width, int height, int slices, const Settings &settings);
|
||||
virtual ~Image();
|
||||
|
||||
ptrdiff_t getHandle() const override { return (ptrdiff_t) texture; }
|
||||
|
||||
void setFilter(const Texture::Filter &f) override;
|
||||
bool setWrap(const Texture::Wrap &w) override;
|
||||
|
||||
bool setMipmapSharpness(float sharpness) override;
|
||||
|
||||
private:
|
||||
|
||||
void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override;
|
||||
void generateMipmaps() override;
|
||||
|
||||
void create(id<MTLDevice> device);
|
||||
|
||||
id<MTLTexture> texture;
|
||||
id<MTLSamplerState> sampler;
|
||||
|
||||
}; // Image
|
||||
|
||||
} // metal
|
||||
} // graphics
|
||||
} // love
|
||||
@@ -45,10 +45,10 @@ public:
|
||||
const UniformInfo *getUniformInfo(const std::string &name) const override;
|
||||
const UniformInfo *getUniformInfo(BuiltinUniform builtin) const override;
|
||||
void updateUniform(const UniformInfo *info, int count) override;
|
||||
void sendTextures(const UniformInfo *info, Texture **textures, int count) override;
|
||||
void sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count) override;
|
||||
bool hasUniform(const std::string &name) const override;
|
||||
ptrdiff_t getHandle() const override;
|
||||
void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) override;
|
||||
void setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture) override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "common/config.h"
|
||||
#include "common/Color.h"
|
||||
#include "common/int.h"
|
||||
#include "graphics/Canvas.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "Metal.h"
|
||||
|
||||
namespace love
|
||||
@@ -33,39 +33,29 @@ namespace graphics
|
||||
namespace metal
|
||||
{
|
||||
|
||||
class Canvas final : public love::graphics::Canvas
|
||||
class Texture final : public love::graphics::Texture
|
||||
{
|
||||
public:
|
||||
|
||||
Canvas(id<MTLDevice> device, const Settings &settings);
|
||||
virtual ~Canvas();
|
||||
Texture(id<MTLDevice> device, const Settings &settings, const Slices *data);
|
||||
virtual ~Texture();
|
||||
|
||||
// Implements Texture.
|
||||
void setFilter(const Texture::Filter &f) override;
|
||||
bool setWrap(const Texture::Wrap &w) override;
|
||||
bool setMipmapSharpness(float sharpness) override;
|
||||
void setDepthSampleMode(Optional<CompareMode> mode) override;
|
||||
ptrdiff_t getHandle() const override { return (ptrdiff_t) texture; }
|
||||
|
||||
love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect) override;
|
||||
void generateMipmaps() override;
|
||||
love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect) override;
|
||||
void setSamplerState(const SamplerState &s) override;
|
||||
|
||||
int getMSAA() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptrdiff_t getRenderTargetHandle() const override
|
||||
{
|
||||
return (ptrdiff_t) texture;
|
||||
}
|
||||
ptrdiff_t getHandle() const override { return (ptrdiff_t) texture; }
|
||||
ptrdiff_t getRenderTargetHandle() const override { return (ptrdiff_t) texture; /* TODO */ }
|
||||
int getMSAA() const override { return 1 /* TODO*/; }
|
||||
|
||||
private:
|
||||
|
||||
id<MTLTexture> texture;
|
||||
id<MTLTexture> resolveTexture;
|
||||
void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd = nullptr) override;
|
||||
|
||||
}; // Canvas
|
||||
id<MTLTexture> texture;
|
||||
id<MTLSamplerState> sampler;
|
||||
|
||||
}; // Texture
|
||||
|
||||
} // metal
|
||||
} // graphics
|
||||
@@ -18,7 +18,7 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Image.h"
|
||||
#include "Texture.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
namespace love
|
||||
@@ -28,48 +28,39 @@ namespace graphics
|
||||
namespace metal
|
||||
{
|
||||
|
||||
Image::Image(id<MTLDevice> device, TextureType textype, PixelFormat format, int width, int height, int slices, const Settings &settings)
|
||||
: love::graphics::Image(textype, format, width, height, slices, settings)
|
||||
Texture::Texture(id<MTLDevice> device, const Settings &settings, const Slices *data)
|
||||
: love::graphics::Texture(settings, data)
|
||||
, texture(nil)
|
||||
, sampler(nil)
|
||||
{ @autoreleasepool {
|
||||
create(device);
|
||||
}}
|
||||
|
||||
Image::Image(id<MTLDevice> device, const Slices &slices, const Settings &settings)
|
||||
: love::graphics::Image(slices, settings)
|
||||
, texture(nil)
|
||||
, sampler(nil)
|
||||
{ @autoreleasepool {
|
||||
create(device);
|
||||
}}
|
||||
|
||||
Image::~Image()
|
||||
{ @autoreleasepool {
|
||||
texture = nil;
|
||||
sampler = nil;
|
||||
}}
|
||||
|
||||
void Image::create(id<MTLDevice> device)
|
||||
{
|
||||
MTLTextureDescriptor *desc = [MTLTextureDescriptor new];
|
||||
|
||||
desc.width = pixelWidth;
|
||||
desc.height = pixelHeight;
|
||||
int w = pixelWidth;
|
||||
int h = pixelHeight;
|
||||
|
||||
// TODO: sampleCount validation
|
||||
desc.sampleCount = getRequestedMSAA();
|
||||
|
||||
desc.width = w;
|
||||
desc.height = h;
|
||||
desc.depth = depth;
|
||||
desc.arrayLength = layers;
|
||||
desc.mipmapLevelCount = mipmapCount;
|
||||
desc.textureType = Metal::getTextureType(texType, 1);
|
||||
desc.textureType = Metal::getTextureType(texType, (int)desc.sampleCount);
|
||||
desc.pixelFormat = Metal::convertPixelFormat(format, sRGB);
|
||||
desc.usage = MTLTextureUsageShaderRead;
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
|
||||
if (readable)
|
||||
desc.usage |= MTLTextureUsageShaderRead;
|
||||
if (renderTarget)
|
||||
desc.usage |= MTLTextureUsageRenderTarget;
|
||||
|
||||
texture = [device newTextureWithDescriptor:desc];
|
||||
|
||||
if (texture == nil)
|
||||
throw love::Exception("Out of graphics memory.");
|
||||
|
||||
int mipcount = mipmapsType == MIPMAPS_GENERATED ? 1 : getMipmapCount();
|
||||
int mipcount = getMipmapCount();
|
||||
|
||||
int slicecount = 1;
|
||||
if (texType == TEXTURE_VOLUME)
|
||||
@@ -83,17 +74,41 @@ void Image::create(id<MTLDevice> device)
|
||||
{
|
||||
for (int slice = 0; slice < slicecount; slice++)
|
||||
{
|
||||
love::image::ImageDataBase *imgd = data.get(slice, mip);
|
||||
auto imgd = data != nullptr ? data->get(slice, mip) : nullptr;
|
||||
if (imgd != nullptr)
|
||||
uploadImageData(imgd, mip, slice, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (mipmapsType == MIPMAPS_GENERATED)
|
||||
generateMipmaps();
|
||||
}
|
||||
if (data == nullptr || data->get(0, 0) == nullptr)
|
||||
{
|
||||
// Initialize all slices to transparent black.
|
||||
if (!isPixelFormatDepthStencil(format))
|
||||
{
|
||||
std::vector<uint8> emptydata(getPixelFormatSliceSize(format, w, h));
|
||||
Rect r = {0, 0, w, h};
|
||||
for (int i = 0; i < slicecount; i++)
|
||||
uploadByteData(format, emptydata.data(), emptydata.size(), 0, i, r);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void Image::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r)
|
||||
// Non-readable textures can't have mipmaps (enforced in the base class),
|
||||
// so generateMipmaps here is fine - when they aren't already initialized.
|
||||
if (getMipmapCount() > 1 && (data == nullptr || data->getMipmapCount() <= 1))
|
||||
generateMipmaps();
|
||||
}}
|
||||
|
||||
Texture::~Texture()
|
||||
{ @autoreleasepool {
|
||||
texture = nil;
|
||||
sampler = nil;
|
||||
}}
|
||||
|
||||
void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *)
|
||||
{ @autoreleasepool {
|
||||
auto gfx = Graphics::getInstance();
|
||||
id<MTLBuffer> buffer = [gfx->device newBufferWithBytes:data
|
||||
@@ -127,10 +142,19 @@ void Image::uploadByteData(PixelFormat pixelformat, const void *data, size_t siz
|
||||
break;
|
||||
}
|
||||
|
||||
size_t rowSize = 0;
|
||||
if (isCompressed())
|
||||
rowSize = getPixelFormatCompressedBlockRowSize(format, r.w);
|
||||
else
|
||||
rowSize = getPixelFormatUncompressedRowSize(format, r.w);
|
||||
|
||||
// TODO: Verify this is correct for compressed formats at small sizes.
|
||||
size_t sliceSize = getPixelFormatSliceSize(format, r.w, r.h);
|
||||
|
||||
[encoder copyFromBuffer:buffer
|
||||
sourceOffset:0
|
||||
sourceBytesPerRow:getPixelFormatRowStride(pixelformat, r.w)
|
||||
sourceBytesPerImage:0 // TODO?
|
||||
sourceBytesPerRow:rowSize
|
||||
sourceBytesPerImage:sliceSize
|
||||
sourceSize:MTLSizeMake(r.w, r.h, 1)
|
||||
toTexture:texture
|
||||
destinationSlice:slice
|
||||
@@ -139,8 +163,10 @@ void Image::uploadByteData(PixelFormat pixelformat, const void *data, size_t siz
|
||||
options:options];
|
||||
}}
|
||||
|
||||
void Image::generateMipmaps()
|
||||
void Texture::generateMipmaps()
|
||||
{ @autoreleasepool {
|
||||
// TODO: alternate method for non-color-renderable and non-filterable
|
||||
// pixel formats.
|
||||
id<MTLBlitCommandEncoder> encoder = Graphics::getInstance()->useBlitEncoder();
|
||||
[encoder generateMipmapsForTexture:texture];
|
||||
}}
|
||||
Reference in New Issue
Block a user