]> git.cworth.org Git - apitrace/blob - helpers/eglsize.cpp
specs: Recognize GL_PROGRAM_BINARY_LENGTH
[apitrace] / helpers / eglsize.cpp
1 /*********************************************************************
2  *
3  * Copyright 2012 Intel Corporation
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use, copy,
10  * modify, merge, publish, distribute, sublicense, and/or sell copies
11  * of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  *
26  *********************************************************************/
27
28 /*
29  * Auxiliary functions to compute the size of array/blob arguments.
30  */
31
32 #ifndef _WIN32
33
34 #include <string.h>
35
36 #include "os_thread.hpp"
37 #include "glimports.hpp"
38 #include "glproc.hpp"
39 #include "glsize.hpp"
40 #include "eglsize.hpp"
41 #include "assert.h"
42
43
44 static int
45 bisect_val(int min, int max, bool is_valid_val(int val))
46 {
47     bool valid;
48
49     while (1) {
50         int try_val = min + (max - min + 1) / 2;
51
52         valid = is_valid_val(try_val);
53         if (min == max)
54             break;
55
56         if (valid)
57             min = try_val;
58         else
59             max = try_val - 1;
60     }
61
62     return valid ? min : -1;
63 }
64
65 static bool
66 is_valid_width(int val)
67 {
68     _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, val, 1);
69     return _glGetError() == GL_NO_ERROR;
70 }
71
72 static bool
73 is_valid_height(int val)
74 {
75     _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, val);
76     return _glGetError() == GL_NO_ERROR;
77 }
78
79 static int
80 detect_size(int *width_ret, int *height_ret)
81 {
82     GLint max_tex_size;
83     int width;
84     int height;
85
86     max_tex_size = 0;
87     _glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
88
89     width = bisect_val(1, max_tex_size, is_valid_width);
90     if (width < 0)
91         return -1;
92
93     height = bisect_val(1, max_tex_size, is_valid_height);
94     if (height < 0)
95         return -1;
96
97     *width_ret = width;
98     *height_ret = height;
99
100     return 0;
101 }
102
103 /* XXX */
104 static inline bool
105 can_unpack_subimage(void) {
106     return false;
107 }
108
109 static void
110 _eglCreateImageKHR_get_image_size(EGLImageKHR image, image_info *info)
111 {
112     GLuint fbo = 0;
113     GLuint orig_fbo = 0;
114     GLuint texture = 0;
115     GLuint orig_texture;
116     GLenum status;
117
118     _glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&orig_fbo);
119     _glGenFramebuffers(1, &fbo);
120     _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
121
122     _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&orig_texture);
123     _glGenTextures(1, &texture);
124     _glBindTexture(GL_TEXTURE_2D, texture);
125
126     _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
127
128     info->width = 0;
129     info->height = 0;
130
131     _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
132                             GL_TEXTURE_2D, texture, 0);
133     status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
134     if (status == GL_FRAMEBUFFER_COMPLETE) {
135         if (detect_size(&info->width, &info->height) != 0)
136             os::log("%s: can't detect image size\n", __func__);
137     } else {
138         os::log("%s: error: %x\n", __func__, status);
139     }
140
141     /* Don't leak errors to the traced application. */
142     (void)_glGetError();
143
144     _glBindTexture(GL_TEXTURE_2D, orig_texture);
145     _glDeleteTextures(1, &texture);
146
147     _glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
148     _glDeleteFramebuffers(1, &fbo);
149 }
150
151 static void
152 get_texture_2d_image(image_info *info)
153 {
154     GLuint fbo = 0;
155     GLint prev_fbo = 0;
156     GLint texture;
157     GLenum status;
158
159     _glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
160     if (!texture)
161         return;
162
163     _glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
164     _glGenFramebuffers(1, &fbo);
165     _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
166
167     _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
168                             texture, 0);
169     status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
170     if (status != GL_FRAMEBUFFER_COMPLETE)
171         os::log("%s: error: %d\n", __func__, status);
172     _glReadPixels(0, 0, info->width, info->height, info->format, info->type, info->pixels);
173     /* Don't leak errors to the traced application. */
174     (void)_glGetError();
175
176     _glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
177     _glDeleteFramebuffers(1, &fbo);
178 }
179
180 struct image_info *
181 _EGLImageKHR_get_image_info(GLenum target, EGLImageKHR image)
182 {
183     GLuint tex;
184     GLuint bound_tex;
185     struct image_info *info;
186
187     info = new image_info;
188
189     memset(info, 0, sizeof *info);
190
191     info->internalformat = GL_RGBA;
192     info->format = GL_RGBA;
193     info->type = GL_UNSIGNED_BYTE;
194
195     _eglCreateImageKHR_get_image_size(image, info);
196
197     _glGenTextures(1, &tex);
198     _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&bound_tex);
199     _glBindTexture(GL_TEXTURE_2D, tex);
200     _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
201
202     info->size = _glTexImage2D_size(info->format, info->type, info->width, info->height);
203     info->pixels = malloc(info->size);
204
205     get_texture_2d_image(info);
206     _glBindTexture(GL_TEXTURE_2D, bound_tex);
207     _glDeleteBuffers(1, &tex);
208
209     return info;
210 }
211
212 void
213 _EGLImageKHR_free_image_info(struct image_info *info)
214 {
215     free(info->pixels);
216     delete info;
217 }
218
219 #endif // !defined(_WIN32)
220