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