]> git.cworth.org Git - apitrace/blob - helpers/eglsize.cpp
Use skiplist-based FastCallSet within trace::CallSet
[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 #include <string.h>
33
34 #include "os_thread.hpp"
35 #include "glimports.hpp"
36 #include "glproc.hpp"
37 #include "glsize.hpp"
38 #include "eglsize.hpp"
39 #include "assert.h"
40
41
42 static int
43 bisect_val(int min, int max, bool is_valid_val(int val))
44 {
45     bool valid;
46
47     while (1) {
48         int try_val = min + (max - min + 1) / 2;
49
50         valid = is_valid_val(try_val);
51         if (min == max)
52             break;
53
54         if (valid)
55             min = try_val;
56         else
57             max = try_val - 1;
58     }
59
60     return valid ? min : -1;
61 }
62
63 static bool
64 is_valid_width(int val)
65 {
66     _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, val, 1);
67     return _glGetError() == GL_NO_ERROR;
68 }
69
70 static bool
71 is_valid_height(int val)
72 {
73     _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, val);
74     return _glGetError() == GL_NO_ERROR;
75 }
76
77 static int
78 detect_size(int *width_ret, int *height_ret)
79 {
80     GLint max_tex_size;
81     int width;
82     int height;
83
84     max_tex_size = 0;
85     _glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
86
87     width = bisect_val(1, max_tex_size, is_valid_width);
88     if (width < 0)
89         return -1;
90
91     height = bisect_val(1, max_tex_size, is_valid_height);
92     if (height < 0)
93         return -1;
94
95     *width_ret = width;
96     *height_ret = height;
97
98     return 0;
99 }
100
101 /* XXX */
102 static inline bool
103 can_unpack_subimage(void) {
104     return false;
105 }
106
107 static void
108 _eglCreateImageKHR_get_image_size(EGLImageKHR image, image_info *info)
109 {
110     GLuint fbo = 0;
111     GLuint orig_fbo = 0;
112     GLuint texture = 0;
113     GLuint orig_texture;
114     GLenum status;
115
116     _glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&orig_fbo);
117     _glGenFramebuffers(1, &fbo);
118     _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
119
120     _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&orig_texture);
121     _glGenTextures(1, &texture);
122     _glBindTexture(GL_TEXTURE_2D, texture);
123
124     _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
125
126     info->width = 0;
127     info->height = 0;
128
129     _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
130                             GL_TEXTURE_2D, texture, 0);
131     status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
132     if (status == GL_FRAMEBUFFER_COMPLETE) {
133         if (detect_size(&info->width, &info->height) != 0)
134             os::log("%s: can't detect image size\n", __func__);
135     } else {
136         os::log("%s: error: %x\n", __func__, status);
137     }
138
139     /* Don't leak errors to the traced application. */
140     (void)_glGetError();
141
142     _glBindTexture(GL_TEXTURE_2D, orig_texture);
143     _glDeleteTextures(1, &texture);
144
145     _glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
146     _glDeleteFramebuffers(1, &fbo);
147 }
148
149 static void
150 get_texture_2d_image(image_info *info)
151 {
152     GLuint fbo = 0;
153     GLint prev_fbo = 0;
154     GLint texture;
155     GLenum status;
156
157     _glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
158     if (!texture)
159         return;
160
161     _glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
162     _glGenFramebuffers(1, &fbo);
163     _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
164
165     _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
166                             texture, 0);
167     status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
168     if (status != GL_FRAMEBUFFER_COMPLETE)
169         os::log("%s: error: %d\n", __func__, status);
170     _glReadPixels(0, 0, info->width, info->height, info->format, info->type, info->pixels);
171     /* Don't leak errors to the traced application. */
172     (void)_glGetError();
173
174     _glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
175     _glDeleteFramebuffers(1, &fbo);
176 }
177
178 struct image_info *
179 _EGLImageKHR_get_image_info(GLenum target, EGLImageKHR image)
180 {
181     GLuint tex;
182     GLuint bound_tex;
183     struct image_info *info;
184
185     info = new image_info;
186
187     memset(info, 0, sizeof *info);
188
189     info->internalformat = GL_RGBA;
190     info->format = GL_RGBA;
191     info->type = GL_UNSIGNED_BYTE;
192
193     _eglCreateImageKHR_get_image_size(image, info);
194
195     _glGenTextures(1, &tex);
196     _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&bound_tex);
197     _glBindTexture(GL_TEXTURE_2D, tex);
198     _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
199
200     info->size = _glTexImage2D_size(info->format, info->type, info->width, info->height);
201     info->pixels = malloc(info->size);
202
203     get_texture_2d_image(info);
204     _glBindTexture(GL_TEXTURE_2D, bound_tex);
205     _glDeleteBuffers(1, &tex);
206
207     return info;
208 }
209
210 void
211 _EGLImageKHR_free_image_info(struct image_info *info)
212 {
213     free(info->pixels);
214     delete info;
215 }
216
217