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
18namespace {
19
20static GrGLFuncPtr osmesa_get(void* ctx, const char name[]) {
21    SkASSERT(nullptr == ctx);
22    SkASSERT(OSMesaGetCurrentContext());
23    return OSMesaGetProcAddress(name);
24}
25
26static const GrGLInterface* create_mesa_interface() {
27    if (nullptr == OSMesaGetCurrentContext()) {
28        return nullptr;
29    }
30    return GrGLAssembleInterface(nullptr, osmesa_get);
31}
32
33static const GrGLint gBOGUS_SIZE = 16;
34
35class MesaGLContext : public sk_gpu_test::GLTestContext {
36private:
37    typedef intptr_t Context;
38
39public:
40    MesaGLContext(MesaGLContext* shareContext);
41    ~MesaGLContext() override;
42
43private:
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
56MesaGLContext::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
111MesaGLContext::~MesaGLContext() {
112    this->teardown();
113    this->destroyGLContext();
114}
115
116void 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
129void 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
138void MesaGLContext::onPlatformSwapBuffers() const { }
139
140GrGLFuncPtr MesaGLContext::onPlatformGetProcAddress(const char *procName) const {
141    return OSMesaGetProcAddress(procName);
142}
143}  // anonymous namespace
144
145
146namespace sk_gpu_test {
147GLTestContext *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