1 /*********************************************************************
3 * Copyright 2012 Intel Corporation
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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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
26 *********************************************************************/
29 * Auxiliary functions to compute the size of array/blob arguments.
34 #include "os_thread.hpp"
35 #include "glimports.hpp"
37 #include "eglsize.hpp"
41 static os::recursive_mutex image_map_mutex;
42 static std::map<EGLImageKHR, struct image_info *>image_map;
45 bisect_val(int min, int max, bool is_valid_val(int val))
50 int try_val = min + (max - min + 1) / 2;
52 valid = is_valid_val(try_val);
62 return valid ? min : -1;
66 is_valid_width(int val)
68 _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, val, 1);
69 return _glGetError() == GL_NO_ERROR;
73 is_valid_height(int val)
75 _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, val);
76 return _glGetError() == GL_NO_ERROR;
80 detect_size(int *width_ret, int *height_ret)
82 static GLint max_tex_size;
87 _glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
89 width = bisect_val(1, max_tex_size, is_valid_width);
93 height = bisect_val(1, max_tex_size, is_valid_height);
104 _eglCreateImageKHR_get_image_info(EGLImageKHR image, struct image_info *info)
112 _glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&orig_fbo);
113 _glGenFramebuffers(1, &fbo);
114 _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
116 _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&orig_texture);
117 _glGenTextures(1, &texture);
118 _glBindTexture(GL_TEXTURE_2D, texture);
120 _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
122 memset(info, sizeof *info, 0);
124 _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
125 GL_TEXTURE_2D, texture, 0);
126 status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
127 if (status == GL_FRAMEBUFFER_COMPLETE) {
128 if (detect_size(&info->width, &info->height) != 0)
129 os::log("%s: can't detect image size\n", __func__);
131 os::log("%s: error: %x\n", __func__, status);
134 /* Don't leak errors to the traced application. */
137 _glBindTexture(GL_TEXTURE_2D, orig_texture);
138 _glDeleteTextures(1, &texture);
140 _glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
141 _glDeleteFramebuffers(1, &fbo);
146 static struct image_info *
147 get_image_info(EGLImageKHR image)
149 struct image_info *info;
151 image_map_mutex.lock();
152 info = image_map[image];
153 image_map_mutex.unlock();
159 _eglCreateImageKHR_epilog(EGLDisplay dpy, EGLContext ctx, EGLenum target,
160 EGLClientBuffer buffer, const EGLint *attrib_list,
163 struct image_info *info;
165 info = (struct image_info *)malloc(sizeof *info);
166 _eglCreateImageKHR_get_image_info(image, info);
168 image_map_mutex.lock();
169 assert(image_map.find(image) == image_map.end());
170 image_map[image] = info;
171 image_map_mutex.unlock();
175 _eglDestroyImageKHR_epilog(EGLImageKHR image)
177 struct image_info *info;
179 info = get_image_info(image);
181 image_map_mutex.lock();
182 image_map.erase(image);
183 image_map_mutex.unlock();
189 get_texture_2d_image(struct image_blob *blob)
196 _glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
200 _glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
201 _glGenFramebuffers(1, &fbo);
202 _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
204 _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
206 status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
207 if (status != GL_FRAMEBUFFER_COMPLETE)
208 os::log("%s: error: %d\n", __func__, status);
209 _glReadPixels(0, 0, blob->info.width, blob->info.height, GL_RGBA,
210 GL_UNSIGNED_BYTE, blob->data);
211 /* Don't leak errors to the traced application. */
214 _glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
215 _glDeleteFramebuffers(1, &fbo);
219 _glEGLImageTargetTexture2DOES_size(GLint target, EGLImageKHR image)
221 struct image_info *info;
224 info = get_image_info(image);
225 size = sizeof(struct image_blob) - 1;
226 /* We always read out the pixels in RGBA format */
227 size += info->width * info->height * 4;
233 _glEGLImageTargetTexture2DOES_get_ptr(GLenum target, EGLImageKHR image)
237 size_t image_blob_size = _glEGLImageTargetTexture2DOES_size(target, image);
238 struct image_blob *blob;
239 struct image_info *info;
241 _glGenTextures(1, &tex);
242 _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&bound_tex);
243 _glBindTexture(GL_TEXTURE_2D, tex);
244 _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
245 blob = (struct image_blob *)malloc(image_blob_size);
246 info = get_image_info(image);
248 get_texture_2d_image(blob);
249 _glBindTexture(GL_TEXTURE_2D, bound_tex);
250 _glDeleteBuffers(1, &tex);
256 _glEGLImageTargetTexture2DOES_put_ptr(const void *buffer)
258 free((void *)buffer);