summaryrefslogtreecommitdiffstats
path: root/host/libs/virglrenderer/EglSurface.h
blob: 4bb880dbb0acda986cc9fc7578daf13e83801d86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>
#include <map>

#include <EGL/egl.h>

struct ANativeWindow;

struct EglSurface {
    static std::map<uint32_t, EglSurface*> map;
    static uint32_t nextId;

    EglSurface(EGLConfig config_, uint32_t ctx_, uint32_t width_, uint32_t height_)
        : create_ctx(ctx_), config(config_), height(height_), width(width_), id(nextId++) {
        map.emplace(id, this);
    }

    ~EglSurface() {
        map.erase(id);
    }

    EglSurface* bind(uint32_t ctx_, bool read_) {
        for (auto const& it : EglSurface::map) {
            EglSurface* sur = it.second;
            if (sur == this)
                continue;
            if (sur->bound_ctx == ctx_) {
                if (read_ && sur->read)
                    return sur;
                if (!read_ && sur->draw)
                    return sur;
            }
        }
        if (read_) {
            read = true;
        } else {
            draw = true;
        }
        bound_ctx = ctx_;
        return nullptr;
    }

    void unbind(bool read_) {
        if (read || draw) {
            if (read_)
                read = false;
            else
                draw = false;
            if (read || draw)
                return;
            bound_ctx = 0U;
        }
        return;
    }

    bool disposable() {
        return surface == EGL_NO_SURFACE && bound_ctx == 0U;
    }

    EGLSurface surface = EGL_NO_SURFACE;
    ANativeWindow* window = nullptr;
    uint32_t create_ctx;
    EGLConfig config;
    uint32_t height;
    uint32_t width;
    uint32_t id;

  private:
    uint32_t bound_ctx = 0U;
    bool draw = false;
    bool read = false;
};