macOS HIDPI fixes; buffer pools

This commit is contained in:
Jack Andersen 2016-12-09 16:31:50 -10:00
parent 4c0c01f84f
commit fa45c6750a
6 changed files with 225 additions and 41 deletions

View File

@ -19,9 +19,13 @@ class GLDataFactory : public IGraphicsDataFactory
uint32_t m_drawSamples;
static ThreadLocalPtr<struct GLData> m_deferredData;
std::unordered_set<struct GLData*> m_committedData;
std::unordered_set<struct GLPool*> m_committedPools;
std::mutex m_committedMutex;
void destroyData(IGraphicsData*);
void destroyAllData();
void destroyPool(IGraphicsBufferPool*);
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use,
size_t stride, size_t count);
public:
GLDataFactory(IGraphicsContext* parent, uint32_t drawSamples);
~GLDataFactory() {destroyAllData();}
@ -50,7 +54,8 @@ public:
bool enableShaderColorBinding, bool enableShaderDepthBinding);
bool bindingNeedsVertexFormat() const {return true;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert = 0, size_t baseInst = 0);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
size_t texCount, const char** texNames,
@ -64,10 +69,11 @@ public:
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs);
size_t texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0);
};
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
GraphicsBufferPoolToken newBufferPool();
};
}

View File

@ -152,6 +152,10 @@ struct IShaderDataBinding {};
struct IGraphicsData {};
class GraphicsDataToken;
/** Opaque object for maintaining ownership of factory-created pool buffers */
struct IGraphicsBufferPool {};
class GraphicsBufferPoolToken;
/** Used wherever distinction of pipeline stages is needed */
enum class PipelineStage
{
@ -226,7 +230,8 @@ struct IGraphicsDataFactory
virtual bool bindingNeedsVertexFormat() const=0;
virtual IVertexFormat*
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0;
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert = 0, size_t baseInst = 0)=0;
virtual IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline,
@ -234,32 +239,39 @@ struct IGraphicsDataFactory
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs)=0;
size_t texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0)=0;
IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
size_t texCount, ITexture** texs)
size_t texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0)
{
return newShaderDataBinding(pipeline, vtxFormat, vbo, instVbo, ibo,
ubufCount, ubufs, ubufStages, nullptr, nullptr, texCount, texs);
ubufCount, ubufs, ubufStages, nullptr,
nullptr, texCount, texs, baseVert, baseInst);
}
};
virtual GraphicsDataToken commitTransaction(const std::function<bool(Context& ctx)>&)=0;
virtual GraphicsBufferPoolToken newBufferPool()=0;
private:
friend class GraphicsDataToken;
virtual void destroyData(IGraphicsData*)=0;
virtual void destroyAllData()=0;
friend class GraphicsBufferPoolToken;
virtual void destroyPool(IGraphicsBufferPool*)=0;
virtual IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use,
size_t stride, size_t count)=0;
};
using FactoryCommitFunc = std::function<bool(IGraphicsDataFactory::Context& ctx)>;
/** Ownership token for maintaining lifetime of factory-created resources
* deletion of this token triggers mass-deallocation of the factory's
/** Ownership token for maintaining lifetime of factory-created resources.
* Deletion of this token triggers mass-deallocation of the factory's
* IGraphicsData (please don't delete and draw contained resources in the same frame). */
class GraphicsDataToken
{
@ -305,6 +317,59 @@ public:
operator bool() const {return m_factory && m_data;}
};
/** Ownership token for maintaining lifetimes of an appendable list of dynamic buffers.
* Deletion of this token triggers mass-deallocation of the IGraphicsBufferPool
* (please don't delete and draw contained resources in the same frame). */
class GraphicsBufferPoolToken
{
friend class GLDataFactory;
friend class D3D12DataFactory;
friend class D3D11DataFactory;
friend class MetalDataFactory;
friend class VulkanDataFactory;
IGraphicsDataFactory* m_factory = nullptr;
IGraphicsBufferPool* m_pool = nullptr;
GraphicsBufferPoolToken(IGraphicsDataFactory* factory, IGraphicsBufferPool* pool)
: m_factory(factory), m_pool(pool) {}
public:
void doDestroy()
{
if (m_factory && m_pool)
{
m_factory->destroyPool(m_pool);
m_factory = nullptr;
m_pool = nullptr;
}
}
GraphicsBufferPoolToken() = default;
GraphicsBufferPoolToken(const GraphicsBufferPoolToken& other) = delete;
GraphicsBufferPoolToken(GraphicsBufferPoolToken&& other)
{
m_factory = other.m_factory;
other.m_factory = nullptr;
m_pool = other.m_pool;
other.m_pool = nullptr;
}
GraphicsBufferPoolToken& operator=(const GraphicsBufferPoolToken& other) = delete;
GraphicsBufferPoolToken& operator=(GraphicsBufferPoolToken&& other)
{
doDestroy();
m_factory = other.m_factory;
other.m_factory = nullptr;
m_pool = other.m_pool;
other.m_pool = nullptr;
return *this;
}
~GraphicsBufferPoolToken() {doDestroy();}
operator bool() const {return m_factory && m_pool;}
IGraphicsBufferD* newPoolBuffer(BufferUse use,
size_t stride, size_t count)
{
return m_factory->newPoolBuffer(m_pool, use, stride, count);
}
};
}
#endif // IGFXDATAFACTORY_HPP

View File

@ -21,12 +21,16 @@ class MetalDataFactory : public IGraphicsDataFactory
IGraphicsContext* m_parent;
static ThreadLocalPtr<struct MetalData> m_deferredData;
std::unordered_set<struct MetalData*> m_committedData;
std::unordered_set<struct MetalPool*> m_committedPools;
std::mutex m_committedMutex;
struct MetalContext* m_ctx;
uint32_t m_sampleCount;
void destroyData(IGraphicsData*);
void destroyAllData();
void destroyPool(IGraphicsBufferPool*);
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use,
size_t stride, size_t count);
public:
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount);
~MetalDataFactory() {}
@ -55,7 +59,8 @@ public:
bool enableShaderColorBinding, bool enableShaderDepthBinding);
bool bindingNeedsVertexFormat() const {return false;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert = 0, size_t baseInst = 0);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples,
@ -68,10 +73,11 @@ public:
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs);
size_t texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0);
};
virtual GraphicsDataToken commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>&);
GraphicsDataToken commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>&);
GraphicsBufferPoolToken newBufferPool();
};
}

View File

@ -30,6 +30,11 @@ struct GLData : IGraphicsData
std::vector<std::unique_ptr<struct GLVertexFormat>> m_VFmts;
};
struct GLPool : IGraphicsBufferPool
{
std::vector<std::unique_ptr<class GLGraphicsBufferD>> m_DBufs;
};
static const GLenum USE_TABLE[] =
{
GL_INVALID_ENUM,
@ -533,9 +538,11 @@ struct GLVertexFormat : IVertexFormat
GLCommandQueue* m_q;
GLuint m_vao[3] = {};
size_t m_elementCount;
GLuint m_baseVert, m_baseInst;
std::unique_ptr<VertexElementDescriptor[]> m_elements;
GLVertexFormat(GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements);
const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst);
~GLVertexFormat();
void bind(int idx) const {glBindVertexArray(m_vao[idx]);}
};
@ -652,10 +659,11 @@ GLDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs)
size_t texCount, ITexture** texs, size_t baseVert, size_t baseInst)
{
GLShaderDataBinding* retval =
new GLShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs);
new GLShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs,
ubufOffs, ubufSizes, texCount, texs);
m_deferredData->m_SBinds.emplace_back(retval);
return retval;
}
@ -690,6 +698,14 @@ GraphicsDataToken GLDataFactory::commitTransaction(const FactoryCommitFunc& tran
return GraphicsDataToken(this, retval);
}
GraphicsBufferPoolToken GLDataFactory::newBufferPool()
{
std::unique_lock<std::mutex> lk(m_committedMutex);
GLPool* retval = new GLPool;
m_committedPools.insert(retval);
return GraphicsBufferPoolToken(this, retval);
}
void GLDataFactory::destroyData(IGraphicsData* d)
{
std::unique_lock<std::mutex> lk(m_committedMutex);
@ -703,7 +719,27 @@ void GLDataFactory::destroyAllData()
std::unique_lock<std::mutex> lk(m_committedMutex);
for (IGraphicsData* data : m_committedData)
delete static_cast<GLData*>(data);
for (IGraphicsBufferPool* pool : m_committedPools)
delete static_cast<GLPool*>(pool);
m_committedData.clear();
m_committedPools.clear();
}
void GLDataFactory::destroyPool(IGraphicsBufferPool* p)
{
std::unique_lock<std::mutex> lk(m_committedMutex);
GLPool* pool = static_cast<GLPool*>(p);
m_committedPools.erase(pool);
delete pool;
}
IGraphicsBufferD* GLDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
size_t stride, size_t count)
{
GLPool* pool = static_cast<GLPool*>(p);
GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count);
pool->m_DBufs.emplace_back(retval);
return retval;
}
static const GLint SEMANTIC_COUNT_TABLE[] =
@ -844,8 +880,8 @@ struct GLCommandQueue : IGraphicsCommandQueue
for (int b=0 ; b<3 ; ++b)
{
size_t offset = 0;
size_t instOffset = 0;
size_t offset = fmt->m_baseVert * stride;
size_t instOffset = fmt->m_baseInst * instStride;
glBindVertexArray(fmt->m_vao[b]);
IGraphicsBuffer* lastVBO = nullptr;
IGraphicsBuffer* lastEBO = nullptr;
@ -1259,6 +1295,11 @@ struct GLCommandQueue : IGraphicsCommandQueue
for (std::unique_ptr<GLTextureD>& t : d->m_DTexs)
t->update(m_completeBuf);
}
for (GLPool* p : gfxF->m_committedPools)
{
for (std::unique_ptr<GLGraphicsBufferD>& b : p->m_DBufs)
b->update(m_completeBuf);
}
datalk.unlock();
glFlush();
@ -1464,10 +1505,12 @@ GLDataFactory::Context::newRenderTexture(size_t width, size_t height,
}
GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements)
const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst)
: m_q(q),
m_elementCount(elementCount),
m_elements(new VertexElementDescriptor[elementCount])
m_elements(new VertexElementDescriptor[elementCount]),
m_baseVert(baseVert), m_baseInst(baseInst)
{
for (size_t i=0 ; i<elementCount ; ++i)
m_elements[i] = elements[i];
@ -1476,10 +1519,11 @@ GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount,
GLVertexFormat::~GLVertexFormat() {m_q->delVertexFormat(this);}
IVertexFormat* GLDataFactory::Context::newVertexFormat
(size_t elementCount, const VertexElementDescriptor* elements)
(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst)
{
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent.m_parent->getCommandQueue());
GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements);
GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements, baseVert, baseInst);
m_deferredData->m_VFmts.emplace_back(retval);
return retval;
}

View File

@ -31,6 +31,11 @@ struct MetalData : IGraphicsData
std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts;
};
struct MetalPool : IGraphicsBufferPool
{
std::vector<std::unique_ptr<class MetalGraphicsBufferD>> m_DBufs;
};
#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
#define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
@ -401,29 +406,29 @@ struct MetalVertexFormat : IVertexFormat
{
size_t m_elementCount;
MTLVertexDescriptor* m_vdesc;
size_t m_stride = 0;
size_t m_instStride = 0;
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
: m_elementCount(elementCount)
{
size_t stride = 0;
size_t instStride = 0;
for (size_t i=0 ; i<elementCount ; ++i)
{
const VertexElementDescriptor* elemin = &elements[i];
int semantic = int(elemin->semantic & VertexSemantic::SemanticMask);
if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
instStride += SEMANTIC_SIZE_TABLE[semantic];
m_instStride += SEMANTIC_SIZE_TABLE[semantic];
else
stride += SEMANTIC_SIZE_TABLE[semantic];
m_stride += SEMANTIC_SIZE_TABLE[semantic];
}
m_vdesc = [MTLVertexDescriptor vertexDescriptor];
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.layouts[0];
layoutDesc.stride = stride;
layoutDesc.stride = m_stride;
layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex;
layoutDesc.stepRate = 1;
layoutDesc = m_vdesc.layouts[1];
layoutDesc.stride = instStride;
layoutDesc.stride = m_instStride;
layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance;
layoutDesc.stepRate = 1;
@ -475,14 +480,16 @@ class MetalShaderPipeline : public IShaderPipeline
{
friend class MetalDataFactory;
friend class MetalCommandQueue;
friend struct MetalShaderDataBinding;
MTLCullMode m_cullMode = MTLCullModeNone;
MTLPrimitiveType m_drawPrim;
const MetalVertexFormat* m_vtxFmt;
MetalShaderPipeline(MetalContext* ctx, id<MTLFunction> vert, id<MTLFunction> frag,
const MetalVertexFormat* vtxFmt, NSUInteger targetSamples,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling)
: m_drawPrim(PRIMITIVE_TABLE[int(prim)])
: m_drawPrim(PRIMITIVE_TABLE[int(prim)]), m_vtxFmt(vtxFmt)
{
if (backfaceCulling)
m_cullMode = MTLCullModeBack;
@ -580,12 +587,15 @@ struct MetalShaderDataBinding : IShaderDataBinding
std::unique_ptr<bool[]> m_fubufs;
size_t m_texCount;
std::unique_ptr<ITexture*[]> m_texs;
size_t m_baseVert;
size_t m_baseInst;
MetalShaderDataBinding(MetalContext* ctx,
IShaderPipeline* pipeline,
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs)
size_t texCount, ITexture** texs, size_t baseVert, size_t baseInst)
: m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)),
m_vbuf(vbuf),
m_instVbo(instVbo),
@ -593,7 +603,9 @@ struct MetalShaderDataBinding : IShaderDataBinding
m_ubufCount(ubufCount),
m_ubufs(new IGraphicsBuffer*[ubufCount]),
m_texCount(texCount),
m_texs(new ITexture*[texCount])
m_texs(new ITexture*[texCount]),
m_baseVert(baseVert),
m_baseInst(baseInst)
{
if (ubufCount && ubufStages)
{
@ -631,10 +643,13 @@ struct MetalShaderDataBinding : IShaderDataBinding
void bind(id<MTLRenderCommandEncoder> enc, int b)
{
m_pipeline->bind(enc);
if (m_vbuf)
[enc setVertexBuffer:GetBufferGPUResource(m_vbuf, b) offset:0 atIndex:0];
[enc setVertexBuffer:GetBufferGPUResource(m_vbuf, b)
offset:m_pipeline->m_vtxFmt->m_stride * m_baseVert atIndex:0];
if (m_instVbo)
[enc setVertexBuffer:GetBufferGPUResource(m_instVbo, b) offset:0 atIndex:1];
[enc setVertexBuffer:GetBufferGPUResource(m_instVbo, b)
offset:m_pipeline->m_vtxFmt->m_instStride * m_baseInst atIndex:1];
if (m_ubufOffs)
for (size_t i=0 ; i<m_ubufCount ; ++i)
{
@ -871,6 +886,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue
for (std::unique_ptr<MetalTextureD>& t : d->m_DTexs)
t->update(m_fillBuf);
}
for (MetalPool* p : gfxF->m_committedPools)
{
for (std::unique_ptr<MetalGraphicsBufferD>& b : p->m_DBufs)
b->update(m_fillBuf);
}
datalk.unlock();
@autoreleasepool
@ -1048,7 +1068,8 @@ ITextureR* MetalDataFactory::Context::newRenderTexture(size_t width, size_t heig
return retval;
}
IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst)
{
MetalVertexFormat* retval = new struct MetalVertexFormat(elementCount, elements);
m_deferredData->m_VFmts.emplace_back(retval);
@ -1091,11 +1112,12 @@ MetalDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs)
size_t texCount, ITexture** texs, size_t baseVert, size_t baseInst)
{
MetalShaderDataBinding* retval =
new MetalShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf,
ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs);
ubufCount, ubufs, ubufStages, ubufOffs,
ubufSizes, texCount, texs, baseVert, baseInst);
m_deferredData->m_SBinds.emplace_back(retval);
return retval;
}
@ -1120,6 +1142,15 @@ GraphicsDataToken MetalDataFactory::commitTransaction(const FactoryCommitFunc& t
m_committedData.insert(retval);
return GraphicsDataToken(this, retval);
}
GraphicsBufferPoolToken MetalDataFactory::newBufferPool()
{
std::unique_lock<std::mutex> lk(m_committedMutex);
MetalPool* retval = new MetalPool;
m_committedPools.insert(retval);
return GraphicsBufferPoolToken(this, retval);
}
void MetalDataFactory::destroyData(IGraphicsData* d)
{
std::unique_lock<std::mutex> lk(m_committedMutex);
@ -1127,12 +1158,34 @@ void MetalDataFactory::destroyData(IGraphicsData* d)
m_committedData.erase(data);
delete data;
}
void MetalDataFactory::destroyAllData()
{
std::unique_lock<std::mutex> lk(m_committedMutex);
for (IGraphicsData* data : m_committedData)
delete static_cast<MetalData*>(data);
for (IGraphicsBufferPool* pool : m_committedPools)
delete static_cast<MetalPool*>(pool);
m_committedData.clear();
m_committedPools.clear();
}
void MetalDataFactory::destroyPool(IGraphicsBufferPool* p)
{
std::unique_lock<std::mutex> lk(m_committedMutex);
MetalPool* pool = static_cast<MetalPool*>(p);
m_committedPools.erase(pool);
delete pool;
}
IGraphicsBufferD* MetalDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
size_t stride, size_t count)
{
MetalPool* pool = static_cast<MetalPool*>(p);
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(m_parent->getCommandQueue());
MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(q, use, m_ctx, stride, count);
pool->m_DBufs.emplace_back(retval);
return retval;
}
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,

View File

@ -1123,8 +1123,9 @@ static boo::ESpecialKey translateKeycode(short code)
- (void)reshape
{
boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y),
int(self.frame.size.width), int(self.frame.size.height)};
NSRect frame = [self convertRectToBacking:self.frame];
boo::SWindowRect rect = {int(frame.origin.x), int(frame.origin.y),
int(frame.size.width), int(frame.size.height)};
if (resp->booContext->m_callback)
resp->booContext->m_callback->resized(rect);
[super reshape];
@ -1145,6 +1146,11 @@ static boo::ESpecialKey translateKeycode(short code)
return resp;
}
- (BOOL)wantsBestResolutionOpenGLSurface
{
return YES;
}
@end
#if BOO_HAS_METAL
@ -1193,8 +1199,9 @@ static boo::ESpecialKey translateKeycode(short code)
- (void)reshapeHandler
{
boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y),
int(self.frame.size.width), int(self.frame.size.height)};
NSRect frame = [self convertRectToBacking:self.frame];
boo::SWindowRect rect = {int(frame.origin.x), int(frame.origin.y),
int(frame.size.width), int(frame.size.height)};
boo::MetalContext::Window& w = m_ctx->m_windows[m_window];
std::unique_lock<std::mutex> lk(w.m_resizeLock);
if (resp->booContext->m_callback)
@ -1351,7 +1358,8 @@ public:
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
{
NSRect wFrame = [[m_nsWindow contentView] frame];
NSView* view = [m_nsWindow contentView];
NSRect wFrame = [view convertRectToBacking:view.frame];
xOut = wFrame.origin.x;
yOut = wFrame.origin.y;
wOut = wFrame.size.width;
@ -1360,7 +1368,8 @@ public:
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
{
NSRect wFrame = [[m_nsWindow contentView] frame];
NSView* view = [m_nsWindow contentView];
NSRect wFrame = [view convertRectToBacking:view.frame];
xOut = wFrame.origin.x;
yOut = wFrame.origin.y;
wOut = wFrame.size.width;
@ -1525,7 +1534,8 @@ IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx,
styleMask:NSWindowStyleMaskTitled|
NSWindowStyleMaskClosable|
NSWindowStyleMaskMiniaturizable|
NSWindowStyleMaskTitled
NSWindowStyleMaskTitled|
NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered
defer:YES];
self.releasedWhenClosed = NO;