1 2 /* 3 * Copyright 2011 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 <GL/osmesa.h> 10 11 #include "gl/mesa/GLTestContext_mesa.h" 12 #include "gl/GrGLDefines.h" 13 14 #include "gl/GrGLAssembleInterface.h" 15 #include "gl/GrGLUtil.h" 16 #include "osmesa_wrapper.h" 17 18 namespace { 19 20 static GrGLFuncPtr osmesa_get(void* ctx, const char name[]) { 21 SkASSERT(nullptr == ctx); 22 SkASSERT(OSMesaGetCurrentContext()); 23 return OSMesaGetProcAddress(name); 24 } 25 26 static const GrGLInterface* create_mesa_interface() { 27 if (nullptr == OSMesaGetCurrentContext()) { 28 return nullptr; 29 } 30 return GrGLAssembleInterface(nullptr, osmesa_get); 31 } 32 33 static const GrGLint gBOGUS_SIZE = 16; 34 35 class MesaGLContext : public sk_gpu_test::GLTestContext { 36 private: 37 typedef intptr_t Context; 38 39 public: 40 MesaGLContext(MesaGLContext* shareContext); 41 ~MesaGLContext() override; 42 43 private: 44 void destroyGLContext(); 45 46 void onPlatformMakeCurrent() const override; 47 48 void onPlatformSwapBuffers() const override; 49 50 GrGLFuncPtr onPlatformGetProcAddress(const char *) const override; 51 52 Context fContext; 53 GrGLubyte *fImage; 54 }; 55 56 MesaGLContext::MesaGLContext(MesaGLContext* shareContext) 57 : fContext(static_cast<Context>(0)) 58 , fImage(nullptr) { 59 GR_STATIC_ASSERT(sizeof(Context) == sizeof(OSMesaContext)); 60 OSMesaContext mesaShareContext = shareContext ? (OSMesaContext)(shareContext->fContext) 61 : nullptr; 62 63 /* Create an RGBA-mode context */ 64 #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 65 /* specify Z, stencil, accum sizes */ 66 fContext = (Context)OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, mesaShareContext); 67 #else 68 fContext = (Context) OSMesaCreateContext(OSMESA_BGRA, mesaShareContext); 69 #endif 70 if (!fContext) { 71 SkDebugf("OSMesaCreateContext failed!\n"); 72 this->destroyGLContext(); 73 return; 74 } 75 // Allocate the image buffer 76 fImage = (GrGLubyte *) sk_malloc_throw(gBOGUS_SIZE * gBOGUS_SIZE * 77 4 * sizeof(GrGLubyte)); 78 if (!fImage) { 79 SkDebugf("Alloc image buffer failed!\n"); 80 this->destroyGLContext(); 81 return; 82 } 83 84 // Bind the buffer to the context and make it current 85 if (!OSMesaMakeCurrent((OSMesaContext) fContext, 86 fImage, 87 GR_GL_UNSIGNED_BYTE, 88 gBOGUS_SIZE, 89 gBOGUS_SIZE)) { 90 SkDebugf("OSMesaMakeCurrent failed!\n"); 91 this->destroyGLContext(); 92 return; 93 } 94 95 sk_sp<const GrGLInterface> gl(create_mesa_interface()); 96 if (nullptr == gl.get()) { 97 SkDebugf("Could not create GL interface!\n"); 98 this->destroyGLContext(); 99 return; 100 } 101 102 if (!gl->validate()) { 103 SkDebugf("Could not validate GL interface!\n"); 104 this->destroyGLContext(); 105 return; 106 } 107 108 this->init(gl.release()); 109 } 110 111 MesaGLContext::~MesaGLContext() { 112 this->teardown(); 113 this->destroyGLContext(); 114 } 115 116 void MesaGLContext::destroyGLContext() { 117 if (fImage) { 118 sk_free(fImage); 119 fImage = nullptr; 120 } 121 122 if (fContext) { 123 OSMesaDestroyContext((OSMesaContext) fContext); 124 fContext = static_cast<Context>(0); 125 } 126 } 127 128 129 void MesaGLContext::onPlatformMakeCurrent() const { 130 if (fContext) { 131 if (!OSMesaMakeCurrent((OSMesaContext) fContext, fImage, 132 GR_GL_UNSIGNED_BYTE, gBOGUS_SIZE, gBOGUS_SIZE)) { 133 SkDebugf("Could not make MESA context current."); 134 } 135 } 136 } 137 138 void MesaGLContext::onPlatformSwapBuffers() const { } 139 140 GrGLFuncPtr MesaGLContext::onPlatformGetProcAddress(const char *procName) const { 141 return OSMesaGetProcAddress(procName); 142 } 143 } // anonymous namespace 144 145 146 namespace sk_gpu_test { 147 GLTestContext *CreateMesaGLTestContext(GLTestContext* shareContext) { 148 MesaGLContext* mesaShareContext = reinterpret_cast<MesaGLContext*>(shareContext); 149 MesaGLContext *ctx = new MesaGLContext(mesaShareContext); 150 if (!ctx->isValid()) { 151 delete ctx; 152 return nullptr; 153 } 154 return ctx; 155 } 156 } // sk_gpu_test 157