skia2/tools/sk_app/mac/RasterWindowContext_mac.cpp
Brian Osman 4013db8e08 Fix flicker when changing backend on Mac viewer
Tie the SDL GL context to the Window, not the context. Deleting the context
causes the window to render a frame of black - this keeps the context alive
along with the window, so that never happens.

Change-Id: Id4df18a6f2fe09f617ec2ff1809d000f18f547ba
Reviewed-on: https://skia-review.googlesource.com/107941
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2018-02-15 19:14:32 +00:00

128 lines
3.8 KiB
C++

/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <OpenGL/gl.h>
#include "../GLWindowContext.h"
#include "SDL.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "WindowContextFactory_mac.h"
#include "gl/GrGLInterface.h"
#include "sk_tool_utils.h"
using sk_app::DisplayParams;
using sk_app::window_context_factory::MacWindowInfo;
using sk_app::GLWindowContext;
namespace {
// We use SDL to support Mac windowing mainly for convenience's sake. However, it
// does not allow us to support a purely raster backend because we have no hooks into
// the NSWindow's drawRect: method. Hence we use GL to handle the update. Should we
// want to avoid this, we will probably need to write our own windowing backend.
class RasterWindowContext_mac : public GLWindowContext {
public:
RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
~RasterWindowContext_mac() override;
sk_sp<SkSurface> getBackbufferSurface() override;
void onSwapBuffers() override;
sk_sp<const GrGLInterface> onInitializeContext() override;
void onDestroyContext() override;
private:
SDL_Window* fWindow;
SDL_GLContext fGLContext;
sk_sp<SkSurface> fBackbufferSurface;
typedef GLWindowContext INHERITED;
};
RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
const DisplayParams& params)
: INHERITED(params)
, fWindow(info.fWindow)
, fGLContext(info.fGLContext) {
// any config code here (particularly for msaa)?
this->initializeContext();
}
RasterWindowContext_mac::~RasterWindowContext_mac() {
this->destroyContext();
}
sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
SkASSERT(fWindow);
SkASSERT(fGLContext);
if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
glClearStencil(0);
glClearColor(0, 0, 0, 0);
glStencilMask(0xffffffff);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
fSampleCount = SkTMax(fSampleCount, 1);
SDL_GetWindowSize(fWindow, &fWidth, &fHeight);
glViewport(0, 0, fWidth, fHeight);
} else {
SkDebugf("MakeCurrent failed: %s\n", SDL_GetError());
}
// make the offscreen image
SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
kPremul_SkAlphaType, fDisplayParams.fColorSpace);
fBackbufferSurface = SkSurface::MakeRaster(info);
return GrGLMakeNativeInterface();
}
void RasterWindowContext_mac::onDestroyContext() {
fBackbufferSurface.reset(nullptr);
}
sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; }
void RasterWindowContext_mac::onSwapBuffers() {
if (fWindow && fGLContext) {
// We made/have an off-screen surface. Get the contents as an SkImage:
sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface();
SkCanvas* gpuCanvas = gpuSurface->getCanvas();
gpuCanvas->drawImage(snapshot, 0, 0);
gpuCanvas->flush();
SDL_GL_SwapWindow(fWindow);
}
}
} // anonymous namespace
namespace sk_app {
namespace window_context_factory {
WindowContext* NewRasterForMac(const MacWindowInfo& info, const DisplayParams& params) {
WindowContext* ctx = new RasterWindowContext_mac(info, params);
if (!ctx->isValid()) {
delete ctx;
return nullptr;
}
return ctx;
}
} // namespace window_context_factory
} // namespace sk_app