OLD | NEW |
(Empty) | |
| 1 |
| 2 /* |
| 3 * Copyright 2016 Google Inc. |
| 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. |
| 7 */ |
| 8 |
| 9 #include "../GLWindowContext.h" |
| 10 #include "SkCanvas.h" |
| 11 #include "SkGammaColorFilter.h" |
| 12 #include "WindowContextFactory_mac.h" |
| 13 |
| 14 #include "SDL.h" |
| 15 |
| 16 #include <OpenGL/gl.h> |
| 17 |
| 18 using sk_app::DisplayParams; |
| 19 using sk_app::window_context_factory::MacWindowInfo; |
| 20 using sk_app::GLWindowContext; |
| 21 |
| 22 namespace { |
| 23 |
| 24 // We use SDL to support Mac windowing mainly for convenience's sake. However, i
t |
| 25 // does not allow us to support a purely raster backend because we have no hooks
into |
| 26 // the NSWindow's drawRect: method. Hence we use GL to handle the update. Should
we |
| 27 // want to avoid this, we will probably need to write our own windowing backend. |
| 28 |
| 29 class RasterWindowContext_mac : public GLWindowContext { |
| 30 public: |
| 31 RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&); |
| 32 |
| 33 ~RasterWindowContext_mac() override; |
| 34 |
| 35 sk_sp<SkSurface> getBackbufferSurface() override; |
| 36 |
| 37 void onSwapBuffers() override; |
| 38 |
| 39 void onInitializeContext() override; |
| 40 void onDestroyContext() override; |
| 41 |
| 42 private: |
| 43 SDL_Window* fWindow; |
| 44 SDL_GLContext fGLContext; |
| 45 sk_sp<SkSurface> fBackbufferSurface; |
| 46 |
| 47 typedef GLWindowContext INHERITED; |
| 48 }; |
| 49 |
| 50 RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info, |
| 51 const DisplayParams& params) |
| 52 : INHERITED(params) |
| 53 , fWindow(info.fWindow) |
| 54 , fGLContext(nullptr) { |
| 55 |
| 56 // any config code here (particularly for msaa)? |
| 57 |
| 58 this->initializeContext(); |
| 59 } |
| 60 |
| 61 RasterWindowContext_mac::~RasterWindowContext_mac() { |
| 62 this->destroyContext(); |
| 63 } |
| 64 |
| 65 void RasterWindowContext_mac::onInitializeContext() { |
| 66 SkASSERT(fWindow); |
| 67 |
| 68 fGLContext = SDL_GL_CreateContext(fWindow); |
| 69 if (!fGLContext) { |
| 70 SkDebugf("%s\n", SDL_GetError()); |
| 71 return; |
| 72 } |
| 73 |
| 74 if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) { |
| 75 glClearStencil(0); |
| 76 glClearColor(0, 0, 0, 0); |
| 77 glStencilMask(0xffffffff); |
| 78 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); |
| 79 |
| 80 int redBits, greenBits, blueBits; |
| 81 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits); |
| 82 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits); |
| 83 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blueBits); |
| 84 fColorBits = redBits + greenBits + blueBits; |
| 85 |
| 86 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits); |
| 87 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount); |
| 88 |
| 89 SDL_GetWindowSize(fWindow, &fWidth, &fHeight); |
| 90 glViewport(0, 0, fWidth, fHeight); |
| 91 } else { |
| 92 SkDebugf("MakeCurrent failed: %s\n", SDL_GetError()); |
| 93 } |
| 94 |
| 95 // make the offscreen image |
| 96 SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorT
ype, |
| 97 kPremul_SkAlphaType, fDisplayParams.fCo
lorSpace); |
| 98 fBackbufferSurface = SkSurface::MakeRaster(info); |
| 99 } |
| 100 |
| 101 void RasterWindowContext_mac::onDestroyContext() { |
| 102 if (!fWindow || !fGLContext) { |
| 103 return; |
| 104 } |
| 105 fBackbufferSurface.reset(nullptr); |
| 106 SDL_GL_DeleteContext(fGLContext); |
| 107 fGLContext = nullptr; |
| 108 } |
| 109 |
| 110 sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackb
ufferSurface; } |
| 111 |
| 112 void RasterWindowContext_mac::onSwapBuffers() { |
| 113 if (fWindow && fGLContext) { |
| 114 // We made/have an off-screen surface. Get the contents as an SkImage: |
| 115 sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot(); |
| 116 |
| 117 // With ten-bit output, we need to manually apply the gamma of the outpu
t device |
| 118 // (unless we're in non-gamma correct mode, in which case our data is al
ready |
| 119 // fake-sRGB, like we're expected to put in the 10-bit buffer): |
| 120 bool doGamma = (fActualColorBits == 30) && |
| 121 (fDisplayParams.fColorSpace != nullptr || |
| 122 kRGBA_F16_SkColorType == fDisplayParams.fColorType); |
| 123 SkPaint gammaPaint; |
| 124 gammaPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
| 125 if (doGamma) { |
| 126 gammaPaint.setColorFilter(SkGammaColorFilter::Make(1.0f / 2.2f)); |
| 127 } |
| 128 |
| 129 sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface(); |
| 130 SkCanvas* gpuCanvas = gpuSurface->getCanvas(); |
| 131 gpuCanvas->drawImage(snapshot, 0, 0, &gammaPaint); |
| 132 gpuCanvas->flush(); |
| 133 |
| 134 SDL_GL_SwapWindow(fWindow); |
| 135 } |
| 136 } |
| 137 |
| 138 } // anonymous namespace |
| 139 |
| 140 namespace sk_app { |
| 141 namespace window_context_factory { |
| 142 |
| 143 WindowContext* NewRasterForMac(const MacWindowInfo& info, const DisplayParams& p
arams) { |
| 144 WindowContext* ctx = new RasterWindowContext_mac(info, params); |
| 145 if (!ctx->isValid()) { |
| 146 delete ctx; |
| 147 return nullptr; |
| 148 } |
| 149 return ctx; |
| 150 } |
| 151 |
| 152 } // namespace window_context_factory |
| 153 } // namespace sk_app |
OLD | NEW |