1 // SuperTux
2 // Copyright (C) 2018 Ingo Ruhnke <grumbel@gmail.com>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17 #include "video/gl/gl_pixel_request.hpp"
18
19 #include <iostream>
20
21 #include "util/log.hpp"
22 #include "video/glutil.hpp"
23
24 #ifndef USE_OPENGLES2
25
GLPixelRequest(int width,int height)26 GLPixelRequest::GLPixelRequest(int width, int height) :
27 m_buffer(),
28 m_width(width),
29 m_height(height),
30 m_offset(0),
31 m_sync()
32 {
33 assert_gl();
34
35 glGenBuffers(1, &m_buffer);
36 glBindBuffer(GL_PIXEL_PACK_BUFFER, m_buffer);
37 glBufferData(GL_PIXEL_PACK_BUFFER, m_width * m_height * 4, nullptr, GL_DYNAMIC_READ);
38 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
39
40 assert_gl();
41 }
42
~GLPixelRequest()43 GLPixelRequest::~GLPixelRequest()
44 {
45 glDeleteBuffers(1, &m_buffer);
46 }
47
48 void
request(int x,int y)49 GLPixelRequest::request(int x, int y)
50 {
51 assert_gl();
52
53 glBindBuffer(GL_PIXEL_PACK_BUFFER, m_buffer);
54 glReadPixels(x, y, m_width, m_height, GL_RGB, GL_UNSIGNED_BYTE,
55 reinterpret_cast<GLvoid*>(m_offset));
56 m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, GL_NONE_BIT);
57 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
58
59 assert_gl();
60 }
61
62 bool
is_ready() const63 GLPixelRequest::is_ready() const
64 {
65 assert_gl();
66
67 GLenum ret = glClientWaitSync(m_sync, GL_NONE_BIT, 0);
68
69 if (ret == GL_CONDITION_SATISFIED ||
70 ret == GL_ALREADY_SIGNALED)
71 {
72 //std::cout << "fence ready: " << static_cast<int>(ret) << " " << GL_ALREADY_SIGNALED << std::endl;
73 return true;
74 }
75 else if (ret == GL_TIMEOUT_EXPIRED)
76
77 {
78 //std::cout << "timeout: " << static_cast<int>(ret) << std::endl;
79 return false;
80 }
81 else if (ret == GL_WAIT_FAILED)
82 {
83 return true;
84 }
85 else
86 {
87 log_warning << "unknown glClientWaitSync() return value: " << static_cast<int>(ret) << std::endl;
88 return true;
89 }
90
91 assert_gl();
92 }
93
94 void
get(void * buffer,size_t length) const95 GLPixelRequest::get(void* buffer, size_t length) const
96 {
97 assert_gl();
98
99 glBindBuffer(GL_PIXEL_PACK_BUFFER, m_buffer);
100 glGetBufferSubData(GL_PIXEL_PACK_BUFFER, m_offset, length, buffer);
101 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
102
103 assert_gl();
104 }
105
106 Color
get_color() const107 GLPixelRequest::get_color() const
108 {
109 uint8_t data[3];
110 get(data, sizeof(data));
111 return Color::from_rgb888(data[0], data[1], data[2]);
112 }
113
114 #endif
115
116 /* EOF */
117