[graphite] Add support to Mac Viewer.
Adds a type enum to WindowContext to determine which kind of GPU context (GrDirectContext or skgpu::Context) we're using. Bug: skia:12466 Change-Id: I288878740392a43cd9e82c925fbe2c372d140dc5 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/454699 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
6868f78d40
commit
7bb0ff05ce
7
BUILD.gn
7
BUILD.gn
@ -2655,8 +2655,15 @@ if (skia_enable_tools) {
|
||||
if (skia_use_metal) {
|
||||
sources += [ "tools/sk_app/MetalWindowContext.mm" ]
|
||||
sources += [ "tools/sk_app/MetalWindowContext.h" ]
|
||||
if (skia_enable_graphite) {
|
||||
sources += [ "tools/sk_app/GraphiteMetalWindowContext.mm" ]
|
||||
sources += [ "tools/sk_app/GraphiteMetalWindowContext.h" ]
|
||||
}
|
||||
if (is_mac) {
|
||||
sources += [ "tools/sk_app/mac/MetalWindowContext_mac.mm" ]
|
||||
if (skia_enable_graphite) {
|
||||
sources += [ "tools/sk_app/mac/GraphiteMetalWindowContext_mac.mm" ]
|
||||
}
|
||||
} else if (is_ios) {
|
||||
sources += [ "tools/sk_app/ios/MetalWindowContext_ios.mm" ]
|
||||
}
|
||||
|
56
tools/sk_app/GraphiteMetalWindowContext.h
Normal file
56
tools/sk_app/GraphiteMetalWindowContext.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef GraphiteMetalWindowContext_DEFINED
|
||||
#define GraphiteMetalWindowContext_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/ports/SkCFObject.h"
|
||||
|
||||
#include "tools/sk_app/WindowContext.h"
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
class SkSurface;
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
class GraphiteMetalWindowContext : public WindowContext {
|
||||
public:
|
||||
sk_sp<SkSurface> getBackbufferSurface() override;
|
||||
|
||||
bool isValid() override { return fValid; }
|
||||
|
||||
void swapBuffers() override;
|
||||
|
||||
void setDisplayParams(const DisplayParams& params) override;
|
||||
|
||||
void activate(bool isActive) override;
|
||||
|
||||
protected:
|
||||
GraphiteMetalWindowContext(const DisplayParams&);
|
||||
// This should be called by subclass constructor. It is also called when window/display
|
||||
// parameters change. This will in turn call onInitializeContext().
|
||||
void initializeContext();
|
||||
virtual bool onInitializeContext() = 0;
|
||||
|
||||
// This should be called by subclass destructor. It is also called when window/display
|
||||
// parameters change prior to initializing a new Metal context. This will in turn call
|
||||
// onDestroyContext().
|
||||
void destroyContext();
|
||||
virtual void onDestroyContext() = 0;
|
||||
|
||||
bool fValid;
|
||||
sk_cfp<id<MTLDevice>> fDevice;
|
||||
sk_cfp<id<MTLCommandQueue>> fQueue;
|
||||
CAMetalLayer* fMetalLayer;
|
||||
CFTypeRef fDrawableHandle;
|
||||
};
|
||||
|
||||
} // namespace sk_app
|
||||
|
||||
#endif
|
127
tools/sk_app/GraphiteMetalWindowContext.mm
Normal file
127
tools/sk_app/GraphiteMetalWindowContext.mm
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "src/core/SkMathPriv.h"
|
||||
#include "tools/sk_app/GraphiteMetalWindowContext.h"
|
||||
|
||||
#include "experimental/graphite/include/Context.h"
|
||||
#include "experimental/graphite/include/mtl/MtlBackendContext.h"
|
||||
|
||||
using sk_app::DisplayParams;
|
||||
using sk_app::GraphiteMetalWindowContext;
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
GraphiteMetalWindowContext::GraphiteMetalWindowContext(const DisplayParams& params)
|
||||
: WindowContext(params)
|
||||
, fValid(false)
|
||||
, fDrawableHandle(nil) {
|
||||
fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext::initializeContext() {
|
||||
SkASSERT(!fContext);
|
||||
SkASSERT(!fGraphiteContext);
|
||||
|
||||
fDevice.reset(MTLCreateSystemDefaultDevice());
|
||||
fQueue.reset([*fDevice newCommandQueue]);
|
||||
|
||||
if (fDisplayParams.fMSAASampleCount > 1) {
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
if (![*fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
fSampleCount = fDisplayParams.fMSAASampleCount;
|
||||
fStencilBits = 8;
|
||||
|
||||
fValid = this->onInitializeContext();
|
||||
|
||||
skgpu::mtl::BackendContext backendContext = {};
|
||||
backendContext.fDevice.retain((GrMTLHandle)fDevice.get());
|
||||
backendContext.fQueue.retain((GrMTLHandle)fQueue.get());
|
||||
fGraphiteContext = skgpu::Context::MakeMetal(backendContext);
|
||||
// TODO
|
||||
// if (!fGraphiteContext && fDisplayParams.fMSAASampleCount > 1) {
|
||||
// fDisplayParams.fMSAASampleCount /= 2;
|
||||
// this->initializeContext();
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext::destroyContext() {
|
||||
if (fGraphiteContext) {
|
||||
// TODO?
|
||||
// in case we have outstanding refs to this (lua?)
|
||||
// fGraphiteContext->abandonContext();
|
||||
fGraphiteContext.reset();
|
||||
}
|
||||
|
||||
this->onDestroyContext();
|
||||
|
||||
fMetalLayer = nil;
|
||||
fValid = false;
|
||||
|
||||
#if GR_METAL_SDK_VERSION >= 230
|
||||
if (@available(macOS 11.0, iOS 14.0, *)) {
|
||||
[fPipelineArchive release];
|
||||
}
|
||||
#endif
|
||||
fQueue.reset();
|
||||
fDevice.reset();
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> GraphiteMetalWindowContext::getBackbufferSurface() {
|
||||
sk_sp<SkSurface> surface;
|
||||
id<CAMetalDrawable> currentDrawable = [fMetalLayer nextDrawable];
|
||||
|
||||
// TODO
|
||||
// GrMtlTextureInfo fbInfo;
|
||||
// fbInfo.fTexture.retain(currentDrawable.texture);
|
||||
//
|
||||
// GrBackendRenderTarget backendRT(fWidth,
|
||||
// fHeight,
|
||||
// fSampleCount,
|
||||
// fbInfo);
|
||||
//
|
||||
// surface = SkSurface::MakeFromBackendRenderTarget(fContext.get(), backendRT,
|
||||
// kTopLeft_GrSurfaceOrigin,
|
||||
// kBGRA_8888_SkColorType,
|
||||
// fDisplayParams.fColorSpace,
|
||||
// &fDisplayParams.fSurfaceProps);
|
||||
|
||||
fDrawableHandle = CFRetain((GrMTLHandle) currentDrawable);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext::swapBuffers() {
|
||||
id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;
|
||||
|
||||
id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]);
|
||||
commandBuffer.label = @"Present";
|
||||
|
||||
[commandBuffer presentDrawable:currentDrawable];
|
||||
[commandBuffer commit];
|
||||
// ARC is off in sk_app, so we need to release the CF ref manually
|
||||
CFRelease(fDrawableHandle);
|
||||
fDrawableHandle = nil;
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext::setDisplayParams(const DisplayParams& params) {
|
||||
this->destroyContext();
|
||||
fDisplayParams = params;
|
||||
this->initializeContext();
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext::activate(bool isActive) {}
|
||||
|
||||
} //namespace sk_app
|
@ -24,6 +24,10 @@ class SkSurface;
|
||||
class SkSurfaceProps;
|
||||
class SkString;
|
||||
|
||||
namespace skgpu {
|
||||
class Context;
|
||||
}
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
class WindowContext;
|
||||
@ -66,6 +70,9 @@ public:
|
||||
#endif
|
||||
#ifdef SK_METAL
|
||||
kMetal_BackendType,
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
kGraphiteMetal_BackendType,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SK_DIRECT3D
|
||||
kDirect3D_BackendType,
|
||||
@ -144,6 +151,7 @@ public:
|
||||
|
||||
// Returns null if there is not a GPU backend or if the backend is not yet created.
|
||||
GrDirectContext* directContext() const;
|
||||
skgpu::Context* graphiteContext() const;
|
||||
|
||||
protected:
|
||||
Window();
|
||||
|
@ -8,13 +8,14 @@
|
||||
#include "tools/sk_app/WindowContext.h"
|
||||
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
#include "experimental/graphite/include/Context.h"
|
||||
#endif
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
WindowContext::WindowContext(const DisplayParams& params)
|
||||
: fDisplayParams(params)
|
||||
, fSampleCount(1)
|
||||
, fStencilBits(0) {}
|
||||
: fDisplayParams(params) {}
|
||||
|
||||
WindowContext::~WindowContext() {}
|
||||
|
||||
|
@ -14,6 +14,11 @@
|
||||
|
||||
class GrDirectContext;
|
||||
class SkSurface;
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
namespace skgpu {
|
||||
class Context;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
@ -37,6 +42,9 @@ public:
|
||||
virtual void setDisplayParams(const DisplayParams& params) = 0;
|
||||
|
||||
GrDirectContext* directContext() const { return fContext.get(); }
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
skgpu::Context* graphiteContext() const { return fGraphiteContext.get(); }
|
||||
#endif
|
||||
|
||||
int width() const { return fWidth; }
|
||||
int height() const { return fHeight; }
|
||||
@ -47,6 +55,9 @@ protected:
|
||||
virtual bool isGpuContext() { return true; }
|
||||
|
||||
sk_sp<GrDirectContext> fContext;
|
||||
#if SK_GRAPHITE_ENABLED
|
||||
sk_sp<skgpu::Context> fGraphiteContext;
|
||||
#endif
|
||||
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
@ -55,8 +66,8 @@ protected:
|
||||
// parameters obtained from the native window
|
||||
// Note that the platform .cpp file is responsible for
|
||||
// initializing fSampleCount and fStencilBits!
|
||||
int fSampleCount;
|
||||
int fStencilBits;
|
||||
int fSampleCount = 1;
|
||||
int fStencilBits = 0;
|
||||
};
|
||||
|
||||
} // namespace sk_app
|
||||
|
109
tools/sk_app/mac/GraphiteMetalWindowContext_mac.mm
Normal file
109
tools/sk_app/mac/GraphiteMetalWindowContext_mac.mm
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "tools/sk_app/GraphiteMetalWindowContext.h"
|
||||
#include "tools/sk_app/mac/WindowContextFactory_mac.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/CAConstraintLayoutManager.h>
|
||||
|
||||
using sk_app::DisplayParams;
|
||||
using sk_app::window_context_factory::MacWindowInfo;
|
||||
using sk_app::GraphiteMetalWindowContext;
|
||||
|
||||
namespace {
|
||||
|
||||
class GraphiteMetalWindowContext_mac : public GraphiteMetalWindowContext {
|
||||
public:
|
||||
GraphiteMetalWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
|
||||
|
||||
~GraphiteMetalWindowContext_mac() override;
|
||||
|
||||
bool onInitializeContext() override;
|
||||
void onDestroyContext() override;
|
||||
|
||||
void resize(int w, int h) override;
|
||||
|
||||
private:
|
||||
NSView* fMainView;
|
||||
|
||||
using INHERITED = GraphiteMetalWindowContext;
|
||||
};
|
||||
|
||||
GraphiteMetalWindowContext_mac::GraphiteMetalWindowContext_mac(const MacWindowInfo& info,
|
||||
const DisplayParams& params)
|
||||
: INHERITED(params)
|
||||
, fMainView(info.fMainView) {
|
||||
|
||||
// any config code here (particularly for msaa)?
|
||||
|
||||
this->initializeContext();
|
||||
}
|
||||
|
||||
GraphiteMetalWindowContext_mac::~GraphiteMetalWindowContext_mac() {
|
||||
this->destroyContext();
|
||||
}
|
||||
|
||||
bool GraphiteMetalWindowContext_mac::onInitializeContext() {
|
||||
SkASSERT(nil != fMainView);
|
||||
|
||||
fMetalLayer = [CAMetalLayer layer];
|
||||
fMetalLayer.device = fDevice.get();
|
||||
fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
|
||||
// resize ignores the passed values and uses the fMainView directly.
|
||||
this->resize(0, 0);
|
||||
|
||||
BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES;
|
||||
fMetalLayer.displaySyncEnabled = useVsync; // TODO: need solution for 10.12 or lower
|
||||
fMetalLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
|
||||
fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
|
||||
fMetalLayer.contentsGravity = kCAGravityTopLeft;
|
||||
fMetalLayer.magnificationFilter = kCAFilterNearest;
|
||||
NSColorSpace* cs = fMainView.window.colorSpace;
|
||||
fMetalLayer.colorspace = cs.CGColorSpace;
|
||||
|
||||
fMainView.layer = fMetalLayer;
|
||||
fMainView.wantsLayer = YES;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext_mac::onDestroyContext() {
|
||||
fMainView.layer = nil;
|
||||
fMainView.wantsLayer = NO;
|
||||
}
|
||||
|
||||
void GraphiteMetalWindowContext_mac::resize(int w, int h) {
|
||||
CGFloat backingScaleFactor = sk_app::GetBackingScaleFactor(fMainView);
|
||||
CGSize backingSize = fMainView.bounds.size;
|
||||
backingSize.width *= backingScaleFactor;
|
||||
backingSize.height *= backingScaleFactor;
|
||||
|
||||
fMetalLayer.drawableSize = backingSize;
|
||||
fMetalLayer.contentsScale = backingScaleFactor;
|
||||
|
||||
fWidth = backingSize.width;
|
||||
fHeight = backingSize.height;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace sk_app {
|
||||
namespace window_context_factory {
|
||||
|
||||
std::unique_ptr<WindowContext> MakeGraphiteMetalForMac(const MacWindowInfo& info,
|
||||
const DisplayParams& params) {
|
||||
std::unique_ptr<WindowContext> ctx(new GraphiteMetalWindowContext_mac(info, params));
|
||||
if (!ctx->isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
} // namespace window_context_factory
|
||||
} // namespace sk_app
|
@ -53,6 +53,9 @@ std::unique_ptr<WindowContext> MakeDawnMTLForMac(const MacWindowInfo&, const Dis
|
||||
|
||||
#ifdef SK_METAL
|
||||
std::unique_ptr<WindowContext> MakeMetalForMac(const MacWindowInfo&, const DisplayParams&);
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
std::unique_ptr<WindowContext> MakeGraphiteMetalForMac(const MacWindowInfo&, const DisplayParams&);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace window_context_factory
|
||||
|
@ -136,6 +136,11 @@ bool Window_mac::attach(BackendType attachType) {
|
||||
case kMetal_BackendType:
|
||||
fWindowContext = MakeMetalForMac(info, fRequestedDisplayParams);
|
||||
break;
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
case kGraphiteMetal_BackendType:
|
||||
fWindowContext = MakeGraphiteMetalForMac(info, fRequestedDisplayParams);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SK_GL
|
||||
case kNativeGL_BackendType:
|
||||
|
@ -200,6 +200,9 @@ const char* kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
|
||||
#endif
|
||||
#ifdef SK_METAL
|
||||
"Metal",
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
"Metal (Graphite)",
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SK_DIRECT3D
|
||||
"Direct3D",
|
||||
@ -227,6 +230,11 @@ static sk_app::Window::BackendType get_backend_type(const char* str) {
|
||||
if (0 == strcmp(str, "mtl")) {
|
||||
return sk_app::Window::kMetal_BackendType;
|
||||
} else
|
||||
#ifdef SK_GRAPHITE_ENABLED
|
||||
if (0 == strcmp(str, "grmtl")) {
|
||||
return sk_app::Window::kGraphiteMetal_BackendType;
|
||||
} else
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SK_DIRECT3D
|
||||
if (0 == strcmp(str, "d3d")) {
|
||||
@ -1881,6 +1889,11 @@ void Viewer::drawImGui() {
|
||||
#if defined(SK_METAL)
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Metal", &newBackend, sk_app::Window::kMetal_BackendType);
|
||||
#if defined(SK_GRAPHITE_ENABLED)
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Metal (Graphite)", &newBackend,
|
||||
sk_app::Window::kGraphiteMetal_BackendType);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(SK_DIRECT3D)
|
||||
ImGui::SameLine();
|
||||
|
Loading…
Reference in New Issue
Block a user